This commit is contained in:
H1JK 2023-02-22 16:37:14 +08:00
parent abced62f4d
commit fc58f80cc8
3 changed files with 67 additions and 39 deletions

View File

@ -479,7 +479,7 @@ func NewVless(option VlessOption) (*Vless, error) {
if option.Network != "ws" && len(option.Flow) >= 16 { if option.Network != "ws" && len(option.Flow) >= 16 {
option.Flow = option.Flow[:16] option.Flow = option.Flow[:16]
switch option.Flow { switch option.Flow {
case vless.XRO, vless.XRD, vless.XRS: case vless.XRO, vless.XRD, vless.XRS, vless.XRV:
addons = &vless.Addons{ addons = &vless.Addons{
Flow: option.Flow, Flow: option.Flow,
} }

View File

@ -7,12 +7,6 @@ import (
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
tlsC "github.com/Dreamacro/clash/component/tls"
"github.com/Dreamacro/clash/log"
utls "github.com/refraction-networking/utls"
buf2 "github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/rw"
"io" "io"
"net" "net"
"reflect" "reflect"
@ -23,7 +17,13 @@ import (
"github.com/Dreamacro/clash/common/buf" "github.com/Dreamacro/clash/common/buf"
N "github.com/Dreamacro/clash/common/net" N "github.com/Dreamacro/clash/common/net"
tlsC "github.com/Dreamacro/clash/component/tls"
"github.com/Dreamacro/clash/log"
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
utls "github.com/refraction-networking/utls"
buf2 "github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/rw"
xtls "github.com/xtls/go" xtls "github.com/xtls/go"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
@ -54,7 +54,6 @@ type Conn struct {
readRemainingContent int readRemainingContent int
readRemainingPadding int readRemainingPadding int
readFilter bool readFilter bool
readDirect bool
readLastCommand byte readLastCommand byte
writeFilterApplicationData bool writeFilterApplicationData bool
writeDirect bool writeDirect bool
@ -84,18 +83,23 @@ func (vc *Conn) ReadBuffer(buffer *buf.Buffer) error {
if vc.readRemainingContent < buffer.FreeLen() { if vc.readRemainingContent < buffer.FreeLen() {
toRead = toRead[:vc.readRemainingContent] toRead = toRead[:vc.readRemainingContent]
} }
n, err := vc.ExtendedReader.Read(buffer.FreeBytes()) n, err := vc.ExtendedReader.Read(toRead)
buffer.Truncate(n) buffer.Truncate(n)
vc.readRemainingPadding -= n vc.readRemainingContent -= n
vc.FilterTLS(buffer.Bytes())
return err return err
} }
if vc.readRemainingPadding > 0 { if vc.readRemainingPadding > 0 {
rw.SkipN(vc.ExtendedReader, vc.readRemainingPadding) err := rw.SkipN(vc.ExtendedReader, vc.readRemainingPadding)
if err != nil {
return err
}
vc.readRemainingPadding = 0
} }
if vc.readFilter { if vc.readFilter {
switch vc.readLastCommand { switch vc.readLastCommand {
case commandPaddingContinue: case commandPaddingContinue:
if vc.isTLS || vc.packetsToFilter > 0 { //if vc.isTLS || vc.packetsToFilter > 0 {
header := buffer.FreeBytes()[:paddingHeaderLen] header := buffer.FreeBytes()[:paddingHeaderLen]
_, err := io.ReadFull(vc.ExtendedReader, header) _, err := io.ReadFull(vc.ExtendedReader, header)
if err != nil { if err != nil {
@ -108,11 +112,15 @@ func (vc *Conn) ReadBuffer(buffer *buf.Buffer) error {
vc.readLastCommand = header[uuid.Size] vc.readLastCommand = header[uuid.Size]
vc.readRemainingContent = int(binary.BigEndian.Uint16(header[uuid.Size+1:])) vc.readRemainingContent = int(binary.BigEndian.Uint16(header[uuid.Size+1:]))
vc.readRemainingPadding = int(binary.BigEndian.Uint16(header[uuid.Size+3:])) vc.readRemainingPadding = int(binary.BigEndian.Uint16(header[uuid.Size+3:]))
log.Debugln("XTLS Vision read padding: command=%d, payloadLen=%d, paddingLen=%d",
vc.readLastCommand, vc.readRemainingContent, vc.readRemainingPadding)
return vc.ReadBuffer(buffer) return vc.ReadBuffer(buffer)
} //}
case commandPaddingEnd: case commandPaddingEnd:
vc.readFilter = false vc.readFilter = false
return vc.ReadBuffer(buffer)
case commandPaddingDirect: case commandPaddingDirect:
log.Debugln("command read direct")
if vc.input != nil { if vc.input != nil {
_, err := buffer.ReadFrom(vc.input) _, err := buffer.ReadFrom(vc.input)
if err != nil { if err != nil {
@ -121,6 +129,9 @@ func (vc *Conn) ReadBuffer(buffer *buf.Buffer) error {
if vc.input.Len() == 0 { if vc.input.Len() == 0 {
vc.input = nil vc.input = nil
} }
if buffer.IsFull() {
return nil
}
} }
if vc.rawInput != nil { if vc.rawInput != nil {
_, err := buffer.ReadFrom(vc.rawInput) _, err := buffer.ReadFrom(vc.rawInput)
@ -134,7 +145,10 @@ func (vc *Conn) ReadBuffer(buffer *buf.Buffer) error {
if vc.input == nil && vc.rawInput == nil { if vc.input == nil && vc.rawInput == nil {
vc.readFilter = false vc.readFilter = false
vc.ExtendedReader = N.NewExtendedReader(vc.Conn) vc.ExtendedReader = N.NewExtendedReader(vc.Conn)
log.Debugln("XTLS Vision Direct read start")
} }
default:
log.Debugln("XTLS Vision read unknown command: %d", vc.readLastCommand)
} }
} }
return vc.ExtendedReader.ReadBuffer(buffer) return vc.ExtendedReader.ReadBuffer(buffer)
@ -190,44 +204,51 @@ func (vc *Conn) WriteBuffer(buffer *buf.Buffer) error {
if vc.writeFilterApplicationData && vc.isTLS { if vc.writeFilterApplicationData && vc.isTLS {
buffer2 := ReshapeBuffer(buffer) buffer2 := ReshapeBuffer(buffer)
defer buffer2.Release() defer buffer2.Release()
if buffer.Len() > 6 && bytes.Equal(buffer.To(3), tlsApplicationDataStart) { vc.FilterTLS(buffer.Bytes())
command := commandPaddingEnd command := commandPaddingContinue
if buffer.Len() > 6 && bytes.Equal(buffer.To(3), tlsApplicationDataStart) || vc.packetsToFilter <= 0 {
command = commandPaddingEnd
if vc.enableXTLS { if vc.enableXTLS {
command = commandPaddingDirect command = commandPaddingDirect
vc.writeDirect = true vc.writeDirect = true
} }
vc.writeFilterApplicationData = false vc.writeFilterApplicationData = false
ApplyPadding(buffer, command, vc.id)
} }
ApplyPadding(buffer, command, vc.id)
err := vc.ExtendedWriter.WriteBuffer(buffer) err := vc.ExtendedWriter.WriteBuffer(buffer)
if err != nil { if err != nil {
return err return err
} }
if vc.writeDirect { if vc.writeDirect {
vc.ExtendedWriter = N.NewExtendedWriter(vc.Conn) vc.ExtendedWriter = N.NewExtendedWriter(vc.Conn)
time.Sleep(5 * time.Millisecond) time.Sleep(20 * time.Millisecond)
} }
if buffer2 != nil { if buffer2 != nil {
if vc.writeDirect { if vc.writeDirect {
return vc.ExtendedWriter.WriteBuffer(buffer2) return vc.ExtendedWriter.WriteBuffer(buffer2)
} }
if buffer2.Len() > 6 && bytes.Equal(buffer2.To(3), tlsApplicationDataStart) { vc.FilterTLS(buffer2.Bytes())
command := commandPaddingEnd command = commandPaddingContinue
if buffer2.Len() > 6 && bytes.Equal(buffer2.To(3), tlsApplicationDataStart) || vc.packetsToFilter <= 0 {
command = commandPaddingEnd
if vc.enableXTLS { if vc.enableXTLS {
command = commandPaddingDirect command = commandPaddingDirect
vc.writeDirect = true vc.writeDirect = true
} }
vc.writeFilterApplicationData = false vc.writeFilterApplicationData = false
}
ApplyPadding(buffer2, command, vc.id) ApplyPadding(buffer2, command, vc.id)
}
err = vc.ExtendedWriter.WriteBuffer(buffer2) err = vc.ExtendedWriter.WriteBuffer(buffer2)
}
if vc.writeDirect { if vc.writeDirect {
vc.ExtendedWriter = N.NewExtendedWriter(vc.Conn) vc.ExtendedWriter = N.NewExtendedWriter(vc.Conn)
time.Sleep(5 * time.Millisecond) time.Sleep(20 * time.Millisecond)
}
} }
return err return err
} }
if vc.writeDirect {
log.Debugln("XTLS Vision Direct write, payloadLen=%d", buffer.Len())
}
return vc.ExtendedWriter.WriteBuffer(buffer) return vc.ExtendedWriter.WriteBuffer(buffer)
} }
@ -376,7 +397,10 @@ func (vc *Conn) FrontHeadroom() int {
} }
func (vc *Conn) Upstream() any { func (vc *Conn) Upstream() any {
if vc.tlsConn == nil {
return vc.Conn return vc.Conn
}
return vc.tlsConn
} }
func (vc *Conn) IsXTLSVisionEnabled() bool { func (vc *Conn) IsXTLSVisionEnabled() bool {
@ -413,9 +437,10 @@ func newConn(conn net.Conn, client *Client, dst *DstAddr) (*Conn, error) {
return nil, fmt.Errorf("failed to use %s, maybe \"security\" is not \"xtls\"", client.Addons.Flow) return nil, fmt.Errorf("failed to use %s, maybe \"security\" is not \"xtls\"", client.Addons.Flow)
} }
case XRV: case XRV:
c.packetsToFilter = 2048 c.packetsToFilter = 10
c.readFilter = true c.readFilter = true
c.writeFilterApplicationData = true c.writeFilterApplicationData = true
c.addons = client.Addons
var t reflect.Type var t reflect.Type
var p uintptr var p uintptr
switch underlying := conn.(type) { switch underlying := conn.(type) {

View File

@ -7,12 +7,13 @@ import (
"github.com/Dreamacro/clash/common/buf" "github.com/Dreamacro/clash/common/buf"
"github.com/Dreamacro/clash/log"
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
buf2 "github.com/sagernet/sing/common/buf" buf2 "github.com/sagernet/sing/common/buf"
) )
const ( const (
paddingHeaderLen = 16 + 1 + 2 + 2 // =21 paddingHeaderLen = uuid.Size + 1 + 2 + 2 // =21
commandPaddingContinue byte = 0x00 commandPaddingContinue byte = 0x00
commandPaddingEnd byte = 0x01 commandPaddingEnd byte = 0x01
@ -34,6 +35,7 @@ func WriteWithPadding(buffer *buf.Buffer, p []byte, command byte, userUUID *uuid
binary.BigEndian.PutUint16(buffer.Extend(2), uint16(paddingLen)) binary.BigEndian.PutUint16(buffer.Extend(2), uint16(paddingLen))
buffer.Write(p) buffer.Write(p)
buffer.Extend(int(paddingLen)) buffer.Extend(int(paddingLen))
log.Debugln("XTLS Vision write padding1: command=%v, payloadLen=%v, paddingLen=%v", command, contentLen, paddingLen)
} }
func ApplyPadding(buffer *buf.Buffer, command byte, userUUID *uuid.UUID) { func ApplyPadding(buffer *buf.Buffer, command byte, userUUID *uuid.UUID) {
@ -50,6 +52,7 @@ func ApplyPadding(buffer *buf.Buffer, command byte, userUUID *uuid.UUID) {
copy(buffer.ExtendHeader(uuid.Size), userUUID.Bytes()) copy(buffer.ExtendHeader(uuid.Size), userUUID.Bytes())
} }
buffer.Extend(int(paddingLen)) buffer.Extend(int(paddingLen))
log.Debugln("XTLS Vision write padding2: command=%d, payloadLen=%d, paddingLen=%d", command, contentLen, paddingLen)
} }
func ReshapeBuffer(buffer *buf.Buffer) *buf.Buffer { func ReshapeBuffer(buffer *buf.Buffer) *buf.Buffer {