Compare commits

...

9 Commits

Author SHA1 Message Date
RPRX
e254424c43 v1.2.1 2021-01-10 07:58:53 +00:00
RPRX
ee15cc253f Improve configuration detector (cone or symmetric) 2021-01-10 07:50:21 +00:00
RPRX
43eb5d1b25 16 -> 60, 8 -> 300
https://github.com/XTLS/Xray-core/issues/129#issuecomment-757355137

十分感谢 @GleenJi 等协助测试
2021-01-10 04:50:26 +00:00
RPRX
700966508f Improve the response to UDP Associate in Socks5 2021-01-09 16:36:20 +00:00
RPRX
7427a55ef1 Adjust Trojan Outbound postRequest 2021-01-08 12:00:46 +00:00
RPRX
fb0e517158 Adjust Trojan & Socks handleUDPPayload 2021-01-08 06:00:51 +00:00
maskedeken
d5aeb6c545 Refine Trojan packet reader & writer (#142) 2021-01-08 03:55:25 +00:00
RPRX
161e18299c Fix TPROXY UDP/IPv6
https://github.com/XTLS/Xray-core/issues/137#issuecomment-756064627

十分感谢 @Ninedyz @changyp6
2021-01-07 12:21:27 +00:00
eMeab
be9421fedf Optimized log (#121) 2021-01-04 05:05:38 +00:00
19 changed files with 133 additions and 137 deletions

View File

@@ -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,7 +292,11 @@ 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 != "" {
accessMessage.Detour = tag if inTag != "" {
accessMessage.Detour = inTag + " -> " + tag
} else {
accessMessage.Detour = tag
}
} }
log.Record(accessMessage) log.Record(accessMessage)
} }

View File

@@ -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)
} }

View File

@@ -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()

View File

@@ -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,
} }

View File

@@ -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.

View File

@@ -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."

View File

@@ -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
View File

@@ -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
View File

@@ -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=

View File

@@ -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)

View File

@@ -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
IP: dest.Address.IP(), } else {
Port: int(dest.Port), dest.Address = net.AnyIPv6
} }
} }
addr := &net.UDPAddr{
IP: dest.Address.IP(),
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

View File

@@ -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
} }
} }

View File

@@ -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
} }

View File

@@ -39,10 +39,10 @@ var addrParser = protocol.NewAddressParser(
) )
type ServerSession struct { 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 {

View File

@@ -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
} }
@@ -89,10 +91,10 @@ func (s *Server) processTCP(ctx context.Context, conn internet.Connection, dispa
} }
svrSession := &ServerSession{ svrSession := &ServerSession{
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
} }

View File

@@ -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()
} }

View File

@@ -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 {

View File

@@ -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)
} }
} }

View File

@@ -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)
From: inbound.Source, if b == nil {
To: p.Target, continue
Status: log.AccessAccepted, }
Reason: "", destination := *b.UDP
Email: user.Email,
})
newError("tunnelling request to ", p.Target).WriteToLog(session.ExportIDToError(ctx))
if !buf.Cone || dest == nil { currentPacketCtx := ctx
dest = &p.Target if inbound.Source.IsValid() {
currentPacketCtx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
From: inbound.Source,
To: destination,
Status: log.AccessAccepted,
Reason: "",
Email: user.Email,
})
}
newError("tunnelling request to ", destination).WriteToLog(session.ExportIDToError(ctx))
if !s.cone || dest == nil {
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)
} }
} }
} }