mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-22 17:46:48 +08:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e254424c43 | ||
![]() |
ee15cc253f | ||
![]() |
43eb5d1b25 | ||
![]() |
700966508f | ||
![]() |
7427a55ef1 | ||
![]() |
fb0e517158 | ||
![]() |
d5aeb6c545 | ||
![]() |
161e18299c | ||
![]() |
be9421fedf |
@@ -263,9 +263,11 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
|
|||||||
skipRoutePick = content.SkipRoutePick
|
skipRoutePick = content.SkipRoutePick
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var inTag string
|
||||||
if d.router != nil && !skipRoutePick {
|
if d.router != nil && !skipRoutePick {
|
||||||
if route, err := d.router.PickRoute(routing_session.AsRoutingContext(ctx)); err == nil {
|
if route, err := d.router.PickRoute(routing_session.AsRoutingContext(ctx)); err == nil {
|
||||||
tag := route.GetOutboundTag()
|
tag := route.GetOutboundTag()
|
||||||
|
inTag = route.GetInboundTag()
|
||||||
if h := d.ohm.GetHandler(tag); h != nil {
|
if h := d.ohm.GetHandler(tag); h != nil {
|
||||||
newError("taking detour [", tag, "] for [", destination, "]").WriteToLog(session.ExportIDToError(ctx))
|
newError("taking detour [", tag, "] for [", destination, "]").WriteToLog(session.ExportIDToError(ctx))
|
||||||
handler = h
|
handler = h
|
||||||
@@ -290,8 +292,12 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
|
|||||||
|
|
||||||
if accessMessage := log.AccessMessageFromContext(ctx); accessMessage != nil {
|
if accessMessage := log.AccessMessageFromContext(ctx); accessMessage != nil {
|
||||||
if tag := handler.Tag(); tag != "" {
|
if tag := handler.Tag(); tag != "" {
|
||||||
|
if inTag != "" {
|
||||||
|
accessMessage.Detour = inTag + " -> " + tag
|
||||||
|
} else {
|
||||||
accessMessage.Detour = tag
|
accessMessage.Detour = tag
|
||||||
}
|
}
|
||||||
|
}
|
||||||
log.Record(accessMessage)
|
log.Record(accessMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -136,6 +136,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
stream: mss,
|
stream: mss,
|
||||||
|
ctx: ctx,
|
||||||
}
|
}
|
||||||
h.workers = append(h.workers, worker)
|
h.workers = append(h.workers, worker)
|
||||||
}
|
}
|
||||||
|
@@ -156,6 +156,7 @@ func (h *DynamicInboundHandler) refresh() error {
|
|||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
stream: h.streamSettings,
|
stream: h.streamSettings,
|
||||||
|
ctx: h.ctx,
|
||||||
}
|
}
|
||||||
if err := worker.Start(); err != nil {
|
if err := worker.Start(); err != nil {
|
||||||
newError("failed to create UDP worker").Base(err).AtWarning().WriteToLog()
|
newError("failed to create UDP worker").Base(err).AtWarning().WriteToLog()
|
||||||
|
@@ -239,6 +239,9 @@ type udpWorker struct {
|
|||||||
|
|
||||||
checker *task.Periodic
|
checker *task.Periodic
|
||||||
activeConn map[connID]*udpConn
|
activeConn map[connID]*udpConn
|
||||||
|
|
||||||
|
ctx context.Context
|
||||||
|
cone bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *udpWorker) getConnection(id connID) (*udpConn, bool) {
|
func (w *udpWorker) getConnection(id connID) (*udpConn, bool) {
|
||||||
@@ -279,7 +282,7 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
|
|||||||
src: source,
|
src: source,
|
||||||
}
|
}
|
||||||
if originalDest.IsValid() {
|
if originalDest.IsValid() {
|
||||||
if !buf.Cone {
|
if !w.cone {
|
||||||
id.dest = originalDest
|
id.dest = originalDest
|
||||||
}
|
}
|
||||||
b.UDP = &originalDest
|
b.UDP = &originalDest
|
||||||
@@ -339,7 +342,7 @@ func (w *udpWorker) clean() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for addr, conn := range w.activeConn {
|
for addr, conn := range w.activeConn {
|
||||||
if nowSec-atomic.LoadInt64(&conn.lastActivityTime) > 8 { // TODO Timeout too small
|
if nowSec-atomic.LoadInt64(&conn.lastActivityTime) > 300 {
|
||||||
delete(w.activeConn, addr)
|
delete(w.activeConn, addr)
|
||||||
conn.Close()
|
conn.Close()
|
||||||
}
|
}
|
||||||
@@ -360,8 +363,10 @@ func (w *udpWorker) Start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
w.cone = w.ctx.Value("cone").(bool)
|
||||||
|
|
||||||
w.checker = &task.Periodic{
|
w.checker = &task.Periodic{
|
||||||
Interval: time.Second * 16,
|
Interval: time.Minute,
|
||||||
Execute: w.clean,
|
Execute: w.clean,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,8 +14,6 @@ const (
|
|||||||
|
|
||||||
var pool = bytespool.GetPool(Size)
|
var pool = bytespool.GetPool(Size)
|
||||||
|
|
||||||
var Cone = true
|
|
||||||
|
|
||||||
// Buffer is a recyclable allocation of a byte array. Buffer.Release() recycles
|
// Buffer is a recyclable allocation of a byte array. Buffer.Release() recycles
|
||||||
// the buffer into an internal buffer pool, in order to recreate a buffer more
|
// the buffer into an internal buffer pool, in order to recreate a buffer more
|
||||||
// quickly.
|
// quickly.
|
||||||
|
@@ -18,7 +18,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
version = "1.2.0"
|
version = "1.2.1"
|
||||||
build = "Custom"
|
build = "Custom"
|
||||||
codename = "Xray, Penetrates Everything."
|
codename = "Xray, Penetrates Everything."
|
||||||
intro = "A unified platform for anti-censorship."
|
intro = "A unified platform for anti-censorship."
|
||||||
|
30
core/xray.go
30
core/xray.go
@@ -3,8 +3,13 @@ package core
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"runtime/debug"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/app/proxyman"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
"github.com/xtls/xray-core/features"
|
"github.com/xtls/xray-core/features"
|
||||||
@@ -179,6 +184,31 @@ func NewWithContext(ctx context.Context, config *Config) (*Instance, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func initInstanceWithConfig(config *Config, server *Instance) (bool, error) {
|
func initInstanceWithConfig(config *Config, server *Instance) (bool, error) {
|
||||||
|
cone := true
|
||||||
|
v, t := false, false
|
||||||
|
for _, outbound := range config.Outbound {
|
||||||
|
s := strings.ToLower(outbound.ProxySettings.Type)
|
||||||
|
l := len(s)
|
||||||
|
if l >= 16 && s[11:16] == "vless" || l >= 16 && s[11:16] == "vmess" {
|
||||||
|
v = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if l >= 17 && s[11:17] == "trojan" || l >= 22 && s[11:22] == "shadowsocks" {
|
||||||
|
t = true
|
||||||
|
var m proxyman.SenderConfig
|
||||||
|
proto.Unmarshal(outbound.SenderSettings.Value, &m)
|
||||||
|
if m.MultiplexSettings != nil && m.MultiplexSettings.Enabled {
|
||||||
|
cone = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v && !t {
|
||||||
|
cone = false
|
||||||
|
}
|
||||||
|
server.ctx = context.WithValue(server.ctx, "cone", cone)
|
||||||
|
defer debug.FreeOSMemory()
|
||||||
|
|
||||||
if config.Transport != nil {
|
if config.Transport != nil {
|
||||||
features.PrintDeprecatedFeatureWarning("global transport settings")
|
features.PrintDeprecatedFeatureWarning("global transport settings")
|
||||||
}
|
}
|
||||||
|
2
go.mod
2
go.mod
@@ -19,7 +19,7 @@ require (
|
|||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
||||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b
|
golang.org/x/net v0.0.0-20201224014010-6772e930b67b
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
|
||||||
golang.org/x/sys v0.0.0-20201231184435-2d18734c6014
|
golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061
|
||||||
google.golang.org/grpc v1.34.0
|
google.golang.org/grpc v1.34.0
|
||||||
google.golang.org/protobuf v1.25.0
|
google.golang.org/protobuf v1.25.0
|
||||||
h12.io/socks v1.0.2
|
h12.io/socks v1.0.2
|
||||||
|
4
go.sum
4
go.sum
@@ -242,8 +242,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201231184435-2d18734c6014 h1:joucsQqXmyBVxViHCPFjG3hx8JzIFSaym3l3MM/Jsdg=
|
golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061 h1:DQmQoKxQWtyybCtX/3dIuDBcAhFszqq8YiNeS6sNu1c=
|
||||||
golang.org/x/sys v0.0.0-20201231184435-2d18734c6014/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
24
main/run.go
24
main/run.go
@@ -14,10 +14,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/proxyman"
|
|
||||||
"github.com/xtls/xray-core/common/buf"
|
|
||||||
"github.com/xtls/xray-core/common/cmdarg"
|
"github.com/xtls/xray-core/common/cmdarg"
|
||||||
"github.com/xtls/xray-core/common/platform"
|
"github.com/xtls/xray-core/common/platform"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
@@ -185,26 +181,6 @@ func startXray() (core.Server, error) {
|
|||||||
return nil, newError("failed to load config files: [", configFiles.String(), "]").Base(err)
|
return nil, newError("failed to load config files: [", configFiles.String(), "]").Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
v, t := false, false
|
|
||||||
for _, outbound := range config.Outbound {
|
|
||||||
s := strings.ToLower(outbound.ProxySettings.Type)
|
|
||||||
l := len(s)
|
|
||||||
if l >= 16 && s[11:16] == "vless" || l >= 16 && s[11:16] == "vmess" {
|
|
||||||
v = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if l >= 17 && s[11:17] == "trojan" || l >= 22 && s[11:22] == "shadowsocks" {
|
|
||||||
var m proxyman.SenderConfig
|
|
||||||
proto.Unmarshal(outbound.SenderSettings.Value, &m)
|
|
||||||
if m.MultiplexSettings == nil || !m.MultiplexSettings.Enabled {
|
|
||||||
t = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if v && !t {
|
|
||||||
buf.Cone = false
|
|
||||||
}
|
|
||||||
|
|
||||||
server, err := core.New(config)
|
server, err := core.New(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, newError("failed to create server").Base(err)
|
return nil, newError("failed to create server").Base(err)
|
||||||
|
@@ -163,14 +163,19 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in
|
|||||||
if !destinationOverridden {
|
if !destinationOverridden {
|
||||||
writer = &buf.SequentialWriter{Writer: conn}
|
writer = &buf.SequentialWriter{Writer: conn}
|
||||||
} else {
|
} else {
|
||||||
var addr *net.UDPAddr
|
back := conn.RemoteAddr().(*net.UDPAddr)
|
||||||
var mark int
|
if !dest.Address.Family().IsIP() {
|
||||||
if dest.Address.Family().IsIP() {
|
if len(back.IP) == 4 {
|
||||||
addr = &net.UDPAddr{
|
dest.Address = net.AnyIP
|
||||||
|
} else {
|
||||||
|
dest.Address = net.AnyIPv6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addr := &net.UDPAddr{
|
||||||
IP: dest.Address.IP(),
|
IP: dest.Address.IP(),
|
||||||
Port: int(dest.Port),
|
Port: int(dest.Port),
|
||||||
}
|
}
|
||||||
}
|
var mark int
|
||||||
if d.sockopt != nil {
|
if d.sockopt != nil {
|
||||||
mark = int(d.sockopt.Mark)
|
mark = int(d.sockopt.Mark)
|
||||||
}
|
}
|
||||||
@@ -178,8 +183,7 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
back := net.DestinationFromAddr(conn.RemoteAddr())
|
writer = NewPacketWriter(pConn, &dest, mark, back)
|
||||||
writer = NewPacketWriter(pConn, &dest, mark, &back)
|
|
||||||
defer writer.(*PacketWriter).Close()
|
defer writer.(*PacketWriter).Close()
|
||||||
/*
|
/*
|
||||||
sockopt := &internet.SocketConfig{
|
sockopt := &internet.SocketConfig{
|
||||||
@@ -236,15 +240,12 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPacketWriter(conn net.PacketConn, d *net.Destination, mark int, back *net.Destination) buf.Writer {
|
func NewPacketWriter(conn net.PacketConn, d *net.Destination, mark int, back *net.UDPAddr) buf.Writer {
|
||||||
writer := &PacketWriter{
|
writer := &PacketWriter{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
conns: make(map[net.Destination]net.PacketConn),
|
conns: make(map[net.Destination]net.PacketConn),
|
||||||
mark: mark,
|
mark: mark,
|
||||||
back: &net.UDPAddr{
|
back: back,
|
||||||
IP: back.Address.IP(),
|
|
||||||
Port: int(back.Port),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
writer.conns[*d] = conn
|
writer.conns[*d] = conn
|
||||||
return writer
|
return writer
|
||||||
|
@@ -6,19 +6,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
func FakeUDP(addr *net.UDPAddr, mark int) (net.PacketConn, error) {
|
func FakeUDP(addr *net.UDPAddr, mark int) (net.PacketConn, error) {
|
||||||
|
|
||||||
if addr == nil {
|
|
||||||
addr = &net.UDPAddr{
|
|
||||||
IP: []byte{0, 0, 0, 0},
|
|
||||||
Port: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
localSocketAddress, af, err := udpAddrToSocketAddr(addr)
|
localSocketAddress, af, err := udpAddrToSocketAddr(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("build local socket address: %s", err)}
|
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("build local socket address: %s", err)}
|
||||||
@@ -75,11 +67,6 @@ func udpAddrToSocketAddr(addr *net.UDPAddr) (syscall.Sockaddr, int, error) {
|
|||||||
ip := [16]byte{}
|
ip := [16]byte{}
|
||||||
copy(ip[:], addr.IP.To16())
|
copy(ip[:], addr.IP.To16())
|
||||||
|
|
||||||
zoneID, err := strconv.ParseUint(addr.Zone, 10, 32)
|
return &syscall.SockaddrInet6{Addr: ip, Port: addr.Port, ZoneId: 0}, syscall.AF_INET6, nil
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &syscall.SockaddrInet6{Addr: ip, Port: addr.Port, ZoneId: uint32(zoneID)}, syscall.AF_INET6, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,7 @@ type Server struct {
|
|||||||
config *ServerConfig
|
config *ServerConfig
|
||||||
user *protocol.MemoryUser
|
user *protocol.MemoryUser
|
||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
|
cone bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer create a new Shadowsocks server.
|
// NewServer create a new Shadowsocks server.
|
||||||
@@ -42,6 +43,7 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
|||||||
config: config,
|
config: config,
|
||||||
user: mUser,
|
user: mUser,
|
||||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
|
cone: ctx.Value("cone").(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
@@ -144,7 +146,7 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
|
|||||||
|
|
||||||
data.UDP = &destination
|
data.UDP = &destination
|
||||||
|
|
||||||
if !buf.Cone || dest == nil {
|
if !s.cone || dest == nil {
|
||||||
dest = &destination
|
dest = &destination
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -42,7 +42,7 @@ type ServerSession struct {
|
|||||||
config *ServerConfig
|
config *ServerConfig
|
||||||
address net.Address
|
address net.Address
|
||||||
port net.Port
|
port net.Port
|
||||||
clientAddress net.Address
|
localAddress net.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServerSession) handshake4(cmd byte, reader io.Reader, writer io.Writer) (*protocol.RequestHeader, error) {
|
func (s *ServerSession) handshake4(cmd byte, reader io.Reader, writer io.Writer) (*protocol.RequestHeader, error) {
|
||||||
@@ -192,14 +192,11 @@ func (s *ServerSession) handshake5(nMethod byte, reader io.Reader, writer io.Wri
|
|||||||
//nolint:gocritic // Use if else chain for clarity
|
//nolint:gocritic // Use if else chain for clarity
|
||||||
if request.Command == protocol.RequestCommandUDP {
|
if request.Command == protocol.RequestCommandUDP {
|
||||||
if s.config.Address != nil {
|
if s.config.Address != nil {
|
||||||
// Use configured IP as remote address in the response to UdpAssociate
|
// Use configured IP as remote address in the response to UDP Associate
|
||||||
responseAddress = s.config.Address.AsAddress()
|
responseAddress = s.config.Address.AsAddress()
|
||||||
} else if s.clientAddress == net.LocalHostIP || s.clientAddress == net.LocalHostIPv6 {
|
|
||||||
// For localhost clients use loopback IP
|
|
||||||
responseAddress = s.clientAddress
|
|
||||||
} else {
|
} else {
|
||||||
// For non-localhost clients use inbound listening address
|
// Use conn.LocalAddr() IP as remote address in the response by default
|
||||||
responseAddress = s.address
|
responseAddress = s.localAddress
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := writeSocks5Response(writer, statusSuccess, responseAddress, responsePort); err != nil {
|
if err := writeSocks5Response(writer, statusSuccess, responseAddress, responsePort); err != nil {
|
||||||
|
@@ -26,6 +26,7 @@ import (
|
|||||||
type Server struct {
|
type Server struct {
|
||||||
config *ServerConfig
|
config *ServerConfig
|
||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
|
cone bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer creates a new Server object.
|
// NewServer creates a new Server object.
|
||||||
@@ -34,6 +35,7 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
|||||||
s := &Server{
|
s := &Server{
|
||||||
config: config,
|
config: config,
|
||||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
|
cone: ctx.Value("cone").(bool),
|
||||||
}
|
}
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
@@ -92,7 +94,7 @@ func (s *Server) processTCP(ctx context.Context, conn internet.Connection, dispa
|
|||||||
config: s.config,
|
config: s.config,
|
||||||
address: inbound.Gateway.Address,
|
address: inbound.Gateway.Address,
|
||||||
port: inbound.Gateway.Port,
|
port: inbound.Gateway.Port,
|
||||||
clientAddress: inbound.Source.Address,
|
localAddress: net.IPAddress(conn.LocalAddr().(*net.TCPAddr).IP),
|
||||||
}
|
}
|
||||||
|
|
||||||
reader := &buf.BufferedReader{Reader: buf.NewReader(conn)}
|
reader := &buf.BufferedReader{Reader: buf.NewReader(conn)}
|
||||||
@@ -218,7 +220,8 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn internet.Connection,
|
|||||||
conn.Write(udpMessage.Bytes())
|
conn.Write(udpMessage.Bytes())
|
||||||
})
|
})
|
||||||
|
|
||||||
if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Source.IsValid() {
|
inbound := session.InboundFromContext(ctx)
|
||||||
|
if inbound != nil && inbound.Source.IsValid() {
|
||||||
newError("client UDP connection from ", inbound.Source).WriteToLog(session.ExportIDToError(ctx))
|
newError("client UDP connection from ", inbound.Source).WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +252,7 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn internet.Connection,
|
|||||||
|
|
||||||
currentPacketCtx := ctx
|
currentPacketCtx := ctx
|
||||||
newError("send packet to ", destination, " with ", payload.Len(), " bytes").AtDebug().WriteToLog(session.ExportIDToError(ctx))
|
newError("send packet to ", destination, " with ", payload.Len(), " bytes").AtDebug().WriteToLog(session.ExportIDToError(ctx))
|
||||||
if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Source.IsValid() {
|
if inbound != nil && inbound.Source.IsValid() {
|
||||||
currentPacketCtx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
|
currentPacketCtx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
|
||||||
From: inbound.Source,
|
From: inbound.Source,
|
||||||
To: destination,
|
To: destination,
|
||||||
@@ -260,7 +263,7 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn internet.Connection,
|
|||||||
|
|
||||||
payload.UDP = &destination
|
payload.UDP = &destination
|
||||||
|
|
||||||
if !buf.Cone || dest == nil {
|
if !s.cone || dest == nil {
|
||||||
dest = &destination
|
dest = &destination
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/platform"
|
"github.com/xtls/xray-core/common/platform"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
@@ -145,12 +146,13 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
|||||||
postRequest := func() error {
|
postRequest := func() error {
|
||||||
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
||||||
|
|
||||||
var bodyWriter buf.Writer
|
|
||||||
bufferWriter := buf.NewBufferedWriter(buf.NewWriter(conn))
|
bufferWriter := buf.NewBufferedWriter(buf.NewWriter(conn))
|
||||||
|
|
||||||
connWriter.Writer = bufferWriter
|
connWriter.Writer = bufferWriter
|
||||||
connWriter.Target = destination
|
connWriter.Target = destination
|
||||||
connWriter.Account = account
|
connWriter.Account = account
|
||||||
|
|
||||||
|
var bodyWriter buf.Writer
|
||||||
if destination.Network == net.Network_UDP {
|
if destination.Network == net.Network_UDP {
|
||||||
bodyWriter = &PacketWriter{Writer: connWriter, Target: destination}
|
bodyWriter = &PacketWriter{Writer: connWriter, Target: destination}
|
||||||
} else {
|
} else {
|
||||||
@@ -167,6 +169,11 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
|||||||
return newError("failed to flush payload").Base(err).AtWarning()
|
return newError("failed to flush payload").Base(err).AtWarning()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send header if not sent yet
|
||||||
|
if _, err = connWriter.Write([]byte{}); err != nil {
|
||||||
|
return err.(*errors.Error).AtWarning()
|
||||||
|
}
|
||||||
|
|
||||||
if err = buf.Copy(link.Reader, bodyWriter, buf.UpdateActivity(timer)); err != nil {
|
if err = buf.Copy(link.Reader, bodyWriter, buf.UpdateActivity(timer)); err != nil {
|
||||||
return newError("failed to transfer request payload").Base(err).AtInfo()
|
return newError("failed to transfer request payload").Base(err).AtInfo()
|
||||||
}
|
}
|
||||||
|
@@ -146,26 +146,6 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteMultiBufferWithMetadata writes udp packet with destination specified
|
|
||||||
func (w *PacketWriter) WriteMultiBufferWithMetadata(mb buf.MultiBuffer, dest net.Destination) error {
|
|
||||||
for {
|
|
||||||
mb2, b := buf.SplitFirst(mb)
|
|
||||||
mb = mb2
|
|
||||||
if b == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
source := &dest
|
|
||||||
if b.UDP != nil {
|
|
||||||
source = b.UDP
|
|
||||||
}
|
|
||||||
if _, err := w.writePacket(b.Bytes(), *source); err != nil {
|
|
||||||
buf.ReleaseMulti(mb)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *PacketWriter) writePacket(payload []byte, dest net.Destination) (int, error) {
|
func (w *PacketWriter) writePacket(payload []byte, dest net.Destination) (int, error) {
|
||||||
buffer := buf.StackNew()
|
buffer := buf.StackNew()
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
@@ -259,12 +239,6 @@ func (c *ConnReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
|||||||
return buf.MultiBuffer{b}, err
|
return buf.MultiBuffer{b}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// PacketPayload combines udp payload and destination
|
|
||||||
type PacketPayload struct {
|
|
||||||
Target net.Destination
|
|
||||||
Buffer buf.MultiBuffer
|
|
||||||
}
|
|
||||||
|
|
||||||
// PacketReader is UDP Connection Reader Wrapper for trojan protocol
|
// PacketReader is UDP Connection Reader Wrapper for trojan protocol
|
||||||
type PacketReader struct {
|
type PacketReader struct {
|
||||||
io.Reader
|
io.Reader
|
||||||
@@ -272,15 +246,6 @@ type PacketReader struct {
|
|||||||
|
|
||||||
// ReadMultiBuffer implements buf.Reader
|
// ReadMultiBuffer implements buf.Reader
|
||||||
func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||||
p, err := r.ReadMultiBufferWithMetadata()
|
|
||||||
if p != nil {
|
|
||||||
return p.Buffer, err
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadMultiBufferWithMetadata reads udp packet with destination
|
|
||||||
func (r *PacketReader) ReadMultiBufferWithMetadata() (*PacketPayload, error) {
|
|
||||||
addr, port, err := addrParser.ReadAddressPort(nil, r)
|
addr, port, err := addrParser.ReadAddressPort(nil, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, newError("failed to read address and port").Base(err)
|
return nil, newError("failed to read address and port").Base(err)
|
||||||
@@ -321,7 +286,7 @@ func (r *PacketReader) ReadMultiBufferWithMetadata() (*PacketPayload, error) {
|
|||||||
remain -= int(n)
|
remain -= int(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &PacketPayload{Target: dest, Buffer: mb}, nil
|
return mb, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadV(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn *xtls.Conn, rawConn syscall.RawConn, counter stats.Counter, sctx context.Context) error {
|
func ReadV(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn *xtls.Conn, rawConn syscall.RawConn, counter stats.Counter, sctx context.Context) error {
|
||||||
|
@@ -71,21 +71,22 @@ func TestUDPRequest(t *testing.T) {
|
|||||||
common.Must(connReader.ParseHeader())
|
common.Must(connReader.ParseHeader())
|
||||||
|
|
||||||
packetReader := &PacketReader{Reader: connReader}
|
packetReader := &PacketReader{Reader: connReader}
|
||||||
p, err := packetReader.ReadMultiBufferWithMetadata()
|
mb, err := packetReader.ReadMultiBuffer()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
if p.Buffer.IsEmpty() {
|
if mb.IsEmpty() {
|
||||||
t.Error("no request data")
|
t.Error("no request data")
|
||||||
}
|
}
|
||||||
|
|
||||||
if r := cmp.Diff(p.Target, destination); r != "" {
|
mb2, b := buf.SplitFirst(mb)
|
||||||
|
defer buf.ReleaseMulti(mb2)
|
||||||
|
|
||||||
|
dest := *b.UDP
|
||||||
|
if r := cmp.Diff(dest, destination); r != "" {
|
||||||
t.Error("destination: ", r)
|
t.Error("destination: ", r)
|
||||||
}
|
}
|
||||||
|
|
||||||
mb, decoded := buf.SplitFirst(p.Buffer)
|
if r := cmp.Diff(b.Bytes(), payload); r != "" {
|
||||||
buf.ReleaseMulti(mb)
|
|
||||||
|
|
||||||
if r := cmp.Diff(decoded.Bytes(), payload); r != "" {
|
|
||||||
t.Error("data: ", r)
|
t.Error("data: ", r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -47,6 +47,7 @@ type Server struct {
|
|||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
validator *Validator
|
validator *Validator
|
||||||
fallbacks map[string]map[string]*Fallback // or nil
|
fallbacks map[string]map[string]*Fallback // or nil
|
||||||
|
cone bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer creates a new trojan inbound handler.
|
// NewServer creates a new trojan inbound handler.
|
||||||
@@ -67,6 +68,7 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
|||||||
server := &Server{
|
server := &Server{
|
||||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
validator: validator,
|
validator: validator,
|
||||||
|
cone: ctx.Value("cone").(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Fallbacks != nil {
|
if config.Fallbacks != nil {
|
||||||
@@ -250,7 +252,11 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet
|
|||||||
|
|
||||||
func (s *Server) handleUDPPayload(ctx context.Context, clientReader *PacketReader, clientWriter *PacketWriter, dispatcher routing.Dispatcher) error {
|
func (s *Server) handleUDPPayload(ctx context.Context, clientReader *PacketReader, clientWriter *PacketWriter, dispatcher routing.Dispatcher) error {
|
||||||
udpServer := udp.NewDispatcher(dispatcher, func(ctx context.Context, packet *udp_proto.Packet) {
|
udpServer := udp.NewDispatcher(dispatcher, func(ctx context.Context, packet *udp_proto.Packet) {
|
||||||
common.Must(clientWriter.WriteMultiBufferWithMetadata(buf.MultiBuffer{packet.Payload}, packet.Source))
|
udpPayload := packet.Payload
|
||||||
|
if udpPayload.UDP == nil {
|
||||||
|
udpPayload.UDP = &packet.Source
|
||||||
|
}
|
||||||
|
common.Must(clientWriter.WriteMultiBuffer(buf.MultiBuffer{udpPayload}))
|
||||||
})
|
})
|
||||||
|
|
||||||
inbound := session.InboundFromContext(ctx)
|
inbound := session.InboundFromContext(ctx)
|
||||||
@@ -263,7 +269,7 @@ func (s *Server) handleUDPPayload(ctx context.Context, clientReader *PacketReade
|
|||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
p, err := clientReader.ReadMultiBufferWithMetadata()
|
mb, err := clientReader.ReadMultiBuffer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Cause(err) != io.EOF {
|
if errors.Cause(err) != io.EOF {
|
||||||
return newError("unexpected EOF").Base(err)
|
return newError("unexpected EOF").Base(err)
|
||||||
@@ -271,21 +277,31 @@ func (s *Server) handleUDPPayload(ctx context.Context, clientReader *PacketReade
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
|
mb2, b := buf.SplitFirst(mb)
|
||||||
|
if b == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
destination := *b.UDP
|
||||||
|
|
||||||
|
currentPacketCtx := ctx
|
||||||
|
if inbound.Source.IsValid() {
|
||||||
|
currentPacketCtx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
|
||||||
From: inbound.Source,
|
From: inbound.Source,
|
||||||
To: p.Target,
|
To: destination,
|
||||||
Status: log.AccessAccepted,
|
Status: log.AccessAccepted,
|
||||||
Reason: "",
|
Reason: "",
|
||||||
Email: user.Email,
|
Email: user.Email,
|
||||||
})
|
})
|
||||||
newError("tunnelling request to ", p.Target).WriteToLog(session.ExportIDToError(ctx))
|
}
|
||||||
|
newError("tunnelling request to ", destination).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
|
||||||
if !buf.Cone || dest == nil {
|
if !s.cone || dest == nil {
|
||||||
dest = &p.Target
|
dest = &destination
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, b := range p.Buffer {
|
udpServer.Dispatch(currentPacketCtx, *dest, b) // first packet
|
||||||
udpServer.Dispatch(ctx, *dest, b)
|
for _, payload := range mb2 {
|
||||||
|
udpServer.Dispatch(currentPacketCtx, *dest, payload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user