Add XTLS Splice to Trojan Outbound

This commit is contained in:
RPRX 2020-12-11 03:05:39 +00:00 committed by GitHub
parent ee19bcc08c
commit b4e84603a2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 9 deletions

View file

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

View file

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

View file

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