XTLS Vision processes struct TLS Conn's input and rawInput

Fixes https://github.com/XTLS/Xray-core/issues/1444
This commit is contained in:
RPRX 2023-01-06 05:37:16 +00:00 committed by GitHub
parent c0ceebe709
commit 6f61021f7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 2 deletions

View File

@ -250,6 +250,7 @@ func ReadV(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, c
// XtlsRead filter and read xtls protocol // XtlsRead filter and read xtls protocol
func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, rawConn syscall.RawConn, func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, rawConn syscall.RawConn,
input *bytes.Reader, rawInput *bytes.Buffer,
counter stats.Counter, ctx context.Context, userUUID []byte, numberOfPacketToFilter *int, enableXtls *bool, counter stats.Counter, ctx context.Context, userUUID []byte, numberOfPacketToFilter *int, enableXtls *bool,
isTLS12orAbove *bool, isTLS *bool, cipher *uint16, remainingServerHello *int32, isTLS12orAbove *bool, isTLS *bool, cipher *uint16, remainingServerHello *int32,
) error { ) error {
@ -301,6 +302,17 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater
} else if currentCommand == 2 { } else if currentCommand == 2 {
filterUUID = false filterUUID = false
shouldSwitchToDirectCopy = true shouldSwitchToDirectCopy = true
// XTLS Vision processes struct TLS Conn's input and rawInput
if inputBuffer, err := buf.ReadFrom(input); err == nil {
if !inputBuffer.IsEmpty() {
buffer, _ = buf.MergeMulti(buffer, inputBuffer)
}
}
if rawInputBuffer, err := buf.ReadFrom(rawInput); err == nil {
if !rawInputBuffer.IsEmpty() {
buffer, _ = buf.MergeMulti(buffer, rawInputBuffer)
}
}
} else if currentCommand != 0 { } else if currentCommand != 0 {
newError("XtlsRead unknown command ", currentCommand, buffer.Len()).WriteToLog(session.ExportIDToError(ctx)) newError("XtlsRead unknown command ", currentCommand, buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
} }

View File

@ -3,12 +3,15 @@ package inbound
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen //go:generate go run github.com/xtls/xray-core/common/errors/errorgen
import ( import (
"bytes"
"context" "context"
"io" "io"
"reflect"
"strconv" "strconv"
"strings" "strings"
"syscall" "syscall"
"time" "time"
"unsafe"
"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"
@ -441,6 +444,8 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
var netConn net.Conn var netConn net.Conn
var rawConn syscall.RawConn var rawConn syscall.RawConn
var input *bytes.Reader
var rawInput *bytes.Buffer
allowNoneFlow := false allowNoneFlow := false
accountFlow := account.Flow accountFlow := account.Flow
flows := strings.Split(account.Flow, ",") flows := strings.Split(account.Flow, ",")
@ -462,11 +467,15 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
return newError(requestAddons.Flow + " doesn't support UDP").AtWarning() return newError(requestAddons.Flow + " doesn't support UDP").AtWarning()
case protocol.RequestCommandTCP: case protocol.RequestCommandTCP:
if requestAddons.Flow == vless.XRV { if requestAddons.Flow == vless.XRV {
var t reflect.Type
var p uintptr
if tlsConn, ok := iConn.(*tls.Conn); ok { if tlsConn, ok := iConn.(*tls.Conn); ok {
netConn = tlsConn.NetConn() netConn = tlsConn.NetConn()
if sc, ok := netConn.(syscall.Conn); ok { if sc, ok := netConn.(syscall.Conn); ok {
rawConn, _ = sc.SyscallConn() rawConn, _ = sc.SyscallConn()
} }
t = reflect.TypeOf(tlsConn.Conn).Elem()
p = uintptr(unsafe.Pointer(tlsConn.Conn))
} else if _, ok := iConn.(*tls.UConn); ok { } else if _, ok := iConn.(*tls.UConn); ok {
return newError("XTLS only supports UTLS fingerprint for the outbound.").AtWarning() return newError("XTLS only supports UTLS fingerprint for the outbound.").AtWarning()
} else if _, ok := iConn.(*xtls.Conn); ok { } else if _, ok := iConn.(*xtls.Conn); ok {
@ -474,6 +483,10 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
} else { } else {
return newError("XTLS only supports TCP, mKCP and DomainSocket for now.").AtWarning() return newError("XTLS only supports TCP, mKCP and DomainSocket for now.").AtWarning()
} }
i, _ := t.FieldByName("input")
r, _ := t.FieldByName("rawInput")
input = (*bytes.Reader)(unsafe.Pointer(p + i.Offset))
rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset))
} else if xtlsConn, ok := iConn.(*xtls.Conn); ok { } else if xtlsConn, ok := iConn.(*xtls.Conn); ok {
xtlsConn.RPRX = true xtlsConn.RPRX = true
xtlsConn.SHOW = xtls_show xtlsConn.SHOW = xtls_show
@ -545,7 +558,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
// TODO enable splice // TODO enable splice
ctx = session.ContextWithInbound(ctx, nil) ctx = session.ContextWithInbound(ctx, nil)
if requestAddons.Flow == vless.XRV { if requestAddons.Flow == vless.XRV {
err = encoding.XtlsRead(clientReader, serverWriter, timer, netConn, rawConn, counter, ctx, account.ID.Bytes(), err = encoding.XtlsRead(clientReader, serverWriter, timer, netConn, rawConn, input, rawInput, counter, ctx, account.ID.Bytes(),
&numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello) &numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
} else { } else {
err = encoding.ReadV(clientReader, serverWriter, timer, iConn.(*xtls.Conn), rawConn, counter, ctx) err = encoding.ReadV(clientReader, serverWriter, timer, iConn.(*xtls.Conn), rawConn, counter, ctx)

View File

@ -3,9 +3,12 @@ package outbound
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen //go:generate go run github.com/xtls/xray-core/common/errors/errorgen
import ( import (
"bytes"
"context" "context"
"reflect"
"syscall" "syscall"
"time" "time"
"unsafe"
"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"
@ -130,6 +133,8 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
var netConn net.Conn var netConn net.Conn
var rawConn syscall.RawConn var rawConn syscall.RawConn
var input *bytes.Reader
var rawInput *bytes.Buffer
allowUDP443 := false allowUDP443 := false
switch requestAddons.Flow { switch requestAddons.Flow {
case vless.XRO + "-udp443", vless.XRD + "-udp443", vless.XRS + "-udp443", vless.XRV + "-udp443": case vless.XRO + "-udp443", vless.XRD + "-udp443", vless.XRS + "-udp443", vless.XRV + "-udp443":
@ -147,21 +152,31 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
requestAddons.Flow = "" requestAddons.Flow = ""
case protocol.RequestCommandTCP: case protocol.RequestCommandTCP:
if requestAddons.Flow == vless.XRV { if requestAddons.Flow == vless.XRV {
var t reflect.Type
var p uintptr
if tlsConn, ok := iConn.(*tls.Conn); ok { if tlsConn, ok := iConn.(*tls.Conn); ok {
netConn = tlsConn.NetConn() netConn = tlsConn.NetConn()
if sc, ok := netConn.(syscall.Conn); ok { if sc, ok := netConn.(syscall.Conn); ok {
rawConn, _ = sc.SyscallConn() rawConn, _ = sc.SyscallConn()
} }
t = reflect.TypeOf(tlsConn.Conn).Elem()
p = uintptr(unsafe.Pointer(tlsConn.Conn))
} else if utlsConn, ok := iConn.(*tls.UConn); ok { } else if utlsConn, ok := iConn.(*tls.UConn); ok {
netConn = utlsConn.Conn.NetConn() netConn = utlsConn.Conn.NetConn()
if sc, ok := netConn.(syscall.Conn); ok { if sc, ok := netConn.(syscall.Conn); ok {
rawConn, _ = sc.SyscallConn() rawConn, _ = sc.SyscallConn()
} }
t = reflect.TypeOf(utlsConn.Conn).Elem()
p = uintptr(unsafe.Pointer(utlsConn.Conn))
} else if _, ok := iConn.(*xtls.Conn); ok { } else if _, ok := iConn.(*xtls.Conn); ok {
return newError(`failed to use ` + requestAddons.Flow + `, vision "security" must be "tls"`).AtWarning() return newError(`failed to use ` + requestAddons.Flow + `, vision "security" must be "tls"`).AtWarning()
} else { } else {
return newError("XTLS only supports TCP, mKCP and DomainSocket for now.").AtWarning() return newError("XTLS only supports TCP, mKCP and DomainSocket for now.").AtWarning()
} }
i, _ := t.FieldByName("input")
r, _ := t.FieldByName("rawInput")
input = (*bytes.Reader)(unsafe.Pointer(p + i.Offset))
rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset))
} else if xtlsConn, ok := iConn.(*xtls.Conn); ok { } else if xtlsConn, ok := iConn.(*xtls.Conn); ok {
xtlsConn.RPRX = true xtlsConn.RPRX = true
xtlsConn.SHOW = xtls_show xtlsConn.SHOW = xtls_show
@ -287,7 +302,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
counter = statConn.ReadCounter counter = statConn.ReadCounter
} }
if requestAddons.Flow == vless.XRV { if requestAddons.Flow == vless.XRV {
err = encoding.XtlsRead(serverReader, clientWriter, timer, netConn, rawConn, counter, ctx, account.ID.Bytes(), err = encoding.XtlsRead(serverReader, clientWriter, timer, netConn, rawConn, input, rawInput, counter, ctx, account.ID.Bytes(),
&numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello) &numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
} else { } else {
if requestAddons.Flow != vless.XRS { if requestAddons.Flow != vless.XRS {