Răsfoiți Sursa

Add XTLS Splice to Trojan Outbound

RPRX 4 ani în urmă
părinte
comite
b4e84603a2
3 a modificat fișierele cu 48 adăugiri și 9 ștergeri
  1. 13 7
      proxy/trojan/client.go
  2. 34 1
      proxy/trojan/protocol.go
  3. 1 1
      proxy/trojan/server.go

+ 13 - 7
proxy/trojan/client.go

@@ -94,15 +94,16 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
 	}
 
 	var rawConn syscall.RawConn
+	var sctx context.Context
 
 	connWriter := &ConnWriter{}
 	allowUDP443 := false
 	switch account.Flow {
-	case XRO + "-udp443", XRD + "-udp443":
+	case XRO + "-udp443", XRD + "-udp443", XRS + "-udp443":
 		allowUDP443 = true
 		account.Flow = account.Flow[:16]
 		fallthrough
-	case XRO, XRD:
+	case XRO, XRD, XRS:
 		if destination.Address.Family().IsDomain() && destination.Address.Domain() == muxCoolAddress {
 			return newError(account.Flow + " doesn't support Mux").AtWarning()
 		}
@@ -114,13 +115,18 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
 			if xtlsConn, ok := iConn.(*xtls.Conn); ok {
 				xtlsConn.RPRX = true
 				xtlsConn.SHOW = trojanXTLSShow
-				connWriter.Flow = account.Flow
+				xtlsConn.MARK = "XTLS"
+				if account.Flow == XRS {
+					sctx = ctx
+					account.Flow = XRD
+				}
 				if account.Flow == XRD {
 					xtlsConn.DirectMode = true
+					if sc, ok := xtlsConn.Connection.(syscall.Conn); ok {
+						rawConn, _ = sc.SyscallConn()
+					}
 				}
-				if sc, ok := xtlsConn.Connection.(syscall.Conn); ok {
-					rawConn, _ = sc.SyscallConn()
-				}
+				connWriter.Flow = account.Flow
 			} else {
 				return newError(`failed to use ` + account.Flow + `, maybe "security" is not "xtls"`).AtWarning()
 			}
@@ -185,7 +191,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
 			if statConn != nil {
 				counter = statConn.ReadCounter
 			}
-			return ReadV(reader, link.Writer, timer, iConn.(*xtls.Conn), rawConn, counter)
+			return ReadV(reader, link.Writer, timer, iConn.(*xtls.Conn), rawConn, counter, sctx)
 		}
 		return buf.Copy(reader, link.Writer, buf.UpdateActivity(timer))
 	}

+ 34 - 1
proxy/trojan/protocol.go

@@ -1,17 +1,21 @@
 package trojan
 
 import (
+	"context"
 	"encoding/binary"
 	fmt "fmt"
 	"io"
+	"runtime"
 	"syscall"
 
 	"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/protocol"
+	"github.com/xtls/xray-core/common/session"
 	"github.com/xtls/xray-core/common/signal"
 	"github.com/xtls/xray-core/features/stats"
+	"github.com/xtls/xray-core/transport/internet"
 	"github.com/xtls/xray-core/transport/internet/xtls"
 )
 
@@ -29,6 +33,8 @@ var (
 
 const (
 	maxLength = 8192
+	// XRS is constant for XTLS splice mode
+	XRS = "xtls-rprx-splice"
 	// XRD is constant for XTLS direct mode
 	XRD = "xtls-rprx-direct"
 	// XRO is constant for XTLS origin mode
@@ -307,12 +313,39 @@ func (r *PacketReader) ReadMultiBufferWithMetadata() (*PacketPayload, error) {
 	return &PacketPayload{Target: dest, Buffer: mb}, nil
 }
 
-func ReadV(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn *xtls.Conn, rawConn syscall.RawConn, counter stats.Counter) 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 {
 	err := func() error {
 		var ct stats.Counter
 		for {
 			if conn.DirectIn {
 				conn.DirectIn = false
+				if sctx != nil {
+					if inbound := session.InboundFromContext(sctx); inbound != nil && inbound.Conn != nil {
+						iConn := inbound.Conn
+						statConn, ok := iConn.(*internet.StatCouterConnection)
+						if ok {
+							iConn = statConn.Connection
+						}
+						if tc, ok := iConn.(*net.TCPConn); ok {
+							if conn.SHOW {
+								fmt.Println(conn.MARK, "Splice")
+							}
+							runtime.Gosched() // necessary
+							w, err := tc.ReadFrom(conn.Connection)
+							if counter != nil {
+								counter.Add(w)
+							}
+							if statConn != nil && statConn.WriteCounter != nil {
+								statConn.WriteCounter.Add(w)
+							}
+							return err
+						} else {
+							panic("XTLS Splice: not TCP inbound")
+						}
+					} else {
+						//panic("XTLS Splice: nil inbound or nil inbound.Conn")
+					}
+				}
 				reader = buf.NewReadVReader(conn.Connection, rawConn)
 				ct = counter
 				if conn.SHOW {

+ 1 - 1
proxy/trojan/server.go

@@ -310,7 +310,7 @@ func (s *Server) handleConnection(ctx context.Context, sessionPolicy policy.Sess
 			if statConn != nil {
 				counter = statConn.ReadCounter
 			}
-			err = ReadV(clientReader, link.Writer, timer, iConn.(*xtls.Conn), rawConn, counter)
+			err = ReadV(clientReader, link.Writer, timer, iConn.(*xtls.Conn), rawConn, counter, nil)
 		} else {
 			err = buf.Copy(clientReader, link.Writer, buf.UpdateActivity(timer))
 		}