Compare commits

...
1 Commits
Author SHA1 Message Date
Fangliding 969e5b6c11 fix new tls lib issue 2026-10-16 16:03:44 +08:00
4 changed files with 43 additions and 38 deletions
+9 -6
View File
@@ -180,14 +180,14 @@ type VisionReader struct {
isUplink bool
conn net.Conn
input *bytes.Reader
rawInput *bytes.Buffer
rawInput **bytes.Buffer
ob *session.Outbound
// internal
directReadCounter stats.Counter
}
func NewVisionReader(reader buf.Reader, trafficState *TrafficState, isUplink bool, ctx context.Context, conn net.Conn, input *bytes.Reader, rawInput *bytes.Buffer, ob *session.Outbound) *VisionReader {
func NewVisionReader(reader buf.Reader, trafficState *TrafficState, isUplink bool, ctx context.Context, conn net.Conn, input *bytes.Reader, rawInput **bytes.Buffer, ob *session.Outbound) *VisionReader {
return &VisionReader{
Reader: reader,
trafficState: trafficState,
@@ -261,12 +261,15 @@ func (w *VisionReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
if inputBuffer, err := buf.ReadFrom(w.input); err == nil && !inputBuffer.IsEmpty() {
buffer, _ = buf.MergeMulti(buffer, inputBuffer)
}
if rawInputBuffer, err := buf.ReadFrom(w.rawInput); err == nil && !rawInputBuffer.IsEmpty() {
buffer, _ = buf.MergeMulti(buffer, rawInputBuffer)
}
*w.input = bytes.Reader{} // release memory
w.input = nil
*w.rawInput = bytes.Buffer{} // release memory
if raw := *w.rawInput; raw != nil {
if rawInputBuffer, err := buf.ReadFrom(raw); err == nil && !rawInputBuffer.IsEmpty() {
buffer, _ = buf.MergeMulti(buffer, rawInputBuffer)
}
*raw = bytes.Buffer{} // release memory
}
w.rawInput = nil
if inbound := session.InboundFromContext(w.ctx); inbound != nil && inbound.Conn != nil {
+6 -15
View File
@@ -6,11 +6,9 @@ import (
gotls "crypto/tls"
"encoding/base64"
"io"
"reflect"
"strconv"
"strings"
"time"
"unsafe"
"github.com/xtls/xray-core/app/dispatcher"
"github.com/xtls/xray-core/app/reverse"
@@ -548,7 +546,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
}
var input *bytes.Reader
var rawInput *bytes.Buffer
var rawInput **bytes.Buffer
switch requestAddons.Flow {
case vless.XRV:
if account.Flow == requestAddons.Flow {
@@ -560,30 +558,23 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
inbound.CanSpliceCopy = 3
fallthrough // we will break Mux connections that contain TCP requests
case protocol.RequestCommandTCP:
var t reflect.Type
var p uintptr
var target net.Conn
if commonConn, ok := connection.(*encryption.CommonConn); ok {
if _, ok := commonConn.Conn.(*encryption.XorConn); ok || !proxy.IsRAWTransportWithoutSecurity(iConn) {
inbound.CanSpliceCopy = 3 // full-random xorConn / non-RAW transport / another securityConn should not be penetrated
}
t = reflect.TypeOf(commonConn).Elem()
p = uintptr(unsafe.Pointer(commonConn))
target = commonConn
} else if tlsConn, ok := iConn.(*tls.Conn); ok {
if tlsConn.ConnectionState().Version != gotls.VersionTLS13 {
return errors.New(`failed to use `+requestAddons.Flow+`, found outer tls version `, tlsConn.ConnectionState().Version)
}
t = reflect.TypeOf(tlsConn.Conn).Elem()
p = uintptr(unsafe.Pointer(tlsConn.Conn))
target = tlsConn.Conn
} else if realityConn, ok := iConn.(*reality.Conn); ok {
t = reflect.TypeOf(realityConn.Conn).Elem()
p = uintptr(unsafe.Pointer(realityConn.Conn))
target = realityConn.Conn
} else {
return errors.New("XTLS only supports TLS and REALITY directly for now.")
}
i, _ := t.FieldByName("input")
r, _ := t.FieldByName("rawInput")
input = (*bytes.Reader)(unsafe.Pointer(p + i.Offset))
rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset))
input, rawInput = vless.AccessTLSBuffers(target)
}
} else {
return errors.New("account " + account.ID.String() + " is not able to use the flow " + requestAddons.Flow)
+7 -17
View File
@@ -5,11 +5,9 @@ import (
"context"
gotls "crypto/tls"
"encoding/base64"
"reflect"
"strings"
"sync"
"time"
"unsafe"
utls "github.com/refraction-networking/utls"
proxymanConfig "github.com/xtls/xray-core/app/proxyman"
@@ -244,7 +242,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
}
var input *bytes.Reader
var rawInput *bytes.Buffer
var rawInput **bytes.Buffer
allowUDP443 := false
switch requestAddons.Flow {
case vless.XRV + "-udp443":
@@ -261,30 +259,22 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
case protocol.RequestCommandMux:
fallthrough // let server break Mux connections that contain TCP requests
case protocol.RequestCommandTCP, protocol.RequestCommandRvs:
var t reflect.Type
var p uintptr
var target net.Conn
if commonConn, ok := conn.(*encryption.CommonConn); ok {
if _, ok := commonConn.Conn.(*encryption.XorConn); ok || !proxy.IsRAWTransportWithoutSecurity(iConn) {
ob.CanSpliceCopy = 3 // full-random xorConn / non-RAW transport / another securityConn should not be penetrated
}
t = reflect.TypeOf(commonConn).Elem()
p = uintptr(unsafe.Pointer(commonConn))
target = commonConn
} else if tlsConn, ok := iConn.(*tls.Conn); ok {
t = reflect.TypeOf(tlsConn.Conn).Elem()
p = uintptr(unsafe.Pointer(tlsConn.Conn))
target = tlsConn.Conn
} else if utlsConn, ok := iConn.(*tls.UConn); ok {
t = reflect.TypeOf(utlsConn.Conn).Elem()
p = uintptr(unsafe.Pointer(utlsConn.Conn))
target = utlsConn.Conn
} else if realityConn, ok := iConn.(*reality.UConn); ok {
t = reflect.TypeOf(realityConn.Conn).Elem()
p = uintptr(unsafe.Pointer(realityConn.Conn))
target = realityConn.Conn
} else {
return errors.New("XTLS only supports TLS and REALITY directly for now.")
}
i, _ := t.FieldByName("input")
r, _ := t.FieldByName("rawInput")
input = (*bytes.Reader)(unsafe.Pointer(p + i.Offset))
rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset))
input, rawInput = vless.AccessTLSBuffers(target)
default:
panic("unknown VLESS request command")
}
+21
View File
@@ -5,7 +5,28 @@
// clients with 'socks' for proxying.
package vless
import (
"bytes"
"net"
"reflect"
"github.com/xtls/xray-core/common/utils"
)
const (
None = "none"
XRV = "xtls-rprx-vision"
)
// Old TLS lib holds bytes.Buffer, but new TLS lib holds *bytes.Buffer
// Since Xray has 3 TLS libraries (std, utls, REALITY server)
// we detect the type of rawInput and return the appropriate pointer
func AccessTLSBuffers(conn net.Conn) (*bytes.Reader, **bytes.Buffer) {
input := utils.AccessField[bytes.Reader](conn, "input")
field := reflect.ValueOf(conn).Elem().FieldByName("rawInput")
if field.Kind() == reflect.Pointer {
return input, utils.AccessField[*bytes.Buffer](conn, "rawInput")
}
raw := utils.AccessField[bytes.Buffer](conn, "rawInput")
return input, &raw
}