Fix vision read

This commit is contained in:
世界 2023-03-05 14:56:09 +08:00
parent d24d3b26dc
commit 5b3b74bd0f
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
8 changed files with 224 additions and 23 deletions

2
go.mod
View file

@ -26,7 +26,7 @@ require (
github.com/sagernet/gomobile v0.0.0-20221130124640-349ebaa752ca github.com/sagernet/gomobile v0.0.0-20221130124640-349ebaa752ca
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32 github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32
github.com/sagernet/reality v0.0.0-20230228045158-d3e085a8e5d1 github.com/sagernet/reality v0.0.0-20230228045158-d3e085a8e5d1
github.com/sagernet/sing v0.1.8-0.20230303052048-c875a4ffab1a github.com/sagernet/sing v0.1.8-0.20230305055148-e16845727f76
github.com/sagernet/sing-dns v0.1.4 github.com/sagernet/sing-dns v0.1.4
github.com/sagernet/sing-shadowsocks v0.1.2-0.20230221080503-769c01d6bba9 github.com/sagernet/sing-shadowsocks v0.1.2-0.20230221080503-769c01d6bba9
github.com/sagernet/sing-shadowtls v0.1.0 github.com/sagernet/sing-shadowtls v0.1.0

4
go.sum
View file

@ -133,8 +133,8 @@ github.com/sagernet/reality v0.0.0-20230228045158-d3e085a8e5d1 h1:8mSzchN6DkM26J
github.com/sagernet/reality v0.0.0-20230228045158-d3e085a8e5d1/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU= github.com/sagernet/reality v0.0.0-20230228045158-d3e085a8e5d1/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY= github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY= github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
github.com/sagernet/sing v0.1.8-0.20230303052048-c875a4ffab1a h1:NvhI/8DMFt2yV3eoYhw6P/XyWzzIKkMiGvFglJbWHWg= github.com/sagernet/sing v0.1.8-0.20230305055148-e16845727f76 h1:JCZ4tpEuT6U6oC87EaDBMsPg7+NxesIwESs4dzAGgJo=
github.com/sagernet/sing v0.1.8-0.20230303052048-c875a4ffab1a/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk= github.com/sagernet/sing v0.1.8-0.20230305055148-e16845727f76/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
github.com/sagernet/sing-dns v0.1.4 h1:7VxgeoSCiiazDSaXXQVcvrTBxFpOePPq/4XdgnUDN+0= github.com/sagernet/sing-dns v0.1.4 h1:7VxgeoSCiiazDSaXXQVcvrTBxFpOePPq/4XdgnUDN+0=
github.com/sagernet/sing-dns v0.1.4/go.mod h1:1+6pCa48B1AI78lD+/i/dLgpw4MwfnsSpZo0Ds8wzzk= github.com/sagernet/sing-dns v0.1.4/go.mod h1:1+6pCa48B1AI78lD+/i/dLgpw4MwfnsSpZo0Ds8wzzk=
github.com/sagernet/sing-shadowsocks v0.1.2-0.20230221080503-769c01d6bba9 h1:qS39eA4C7x+zhEkySbASrtmb6ebdy5v0y2M6mgkmSO0= github.com/sagernet/sing-shadowsocks v0.1.2-0.20230221080503-769c01d6bba9 h1:qS39eA4C7x+zhEkySbASrtmb6ebdy5v0y2M6mgkmSO0=

View file

@ -0,0 +1,51 @@
{
"log": {
"loglevel": "debug"
},
"inbounds": [
{
"listen": "0.0.0.0",
"port": "1080",
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true,
"ip": "127.0.0.1"
}
}
],
"outbounds": [
{
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "host.docker.internal",
"port": 1234,
"users": [
{
"id": "",
"encryption": "none",
"flow": ""
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"serverName": "example.org",
"certificates": [
{
"certificateFile": "/path/to/certificate.crt",
"keyFile": "/path/to/private.key"
}
],
"fingerprint": "chrome"
}
}
}
]
}

View file

@ -10,7 +10,7 @@ require (
github.com/docker/docker v20.10.18+incompatible github.com/docker/docker v20.10.18+incompatible
github.com/docker/go-connections v0.4.0 github.com/docker/go-connections v0.4.0
github.com/gofrs/uuid v4.4.0+incompatible github.com/gofrs/uuid v4.4.0+incompatible
github.com/sagernet/sing v0.1.8-0.20230303052048-c875a4ffab1a github.com/sagernet/sing v0.1.8-0.20230305055148-e16845727f76
github.com/sagernet/sing-shadowsocks v0.1.2-0.20230221080503-769c01d6bba9 github.com/sagernet/sing-shadowsocks v0.1.2-0.20230221080503-769c01d6bba9
github.com/spyzhov/ajson v0.7.1 github.com/spyzhov/ajson v0.7.1
github.com/stretchr/testify v1.8.1 github.com/stretchr/testify v1.8.1
@ -71,7 +71,7 @@ require (
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32 // indirect github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32 // indirect
github.com/sagernet/reality v0.0.0-20230228045158-d3e085a8e5d1 // indirect github.com/sagernet/reality v0.0.0-20230228045158-d3e085a8e5d1 // indirect
github.com/sagernet/sing-dns v0.1.4 // indirect github.com/sagernet/sing-dns v0.1.4 // indirect
github.com/sagernet/sing-shadowtls v0.0.0-20230221123345-78e50cd7b587 // indirect github.com/sagernet/sing-shadowtls v0.1.0 // indirect
github.com/sagernet/sing-tun v0.1.2-0.20230226091124-0cdb0eed74d9 // indirect github.com/sagernet/sing-tun v0.1.2-0.20230226091124-0cdb0eed74d9 // indirect
github.com/sagernet/sing-vmess v0.1.3-0.20230303082804-627cc46ae68b // indirect github.com/sagernet/sing-vmess v0.1.3-0.20230303082804-627cc46ae68b // indirect
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 // indirect github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 // indirect

View file

@ -146,14 +146,14 @@ github.com/sagernet/reality v0.0.0-20230228045158-d3e085a8e5d1 h1:8mSzchN6DkM26J
github.com/sagernet/reality v0.0.0-20230228045158-d3e085a8e5d1/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU= github.com/sagernet/reality v0.0.0-20230228045158-d3e085a8e5d1/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY= github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY= github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
github.com/sagernet/sing v0.1.8-0.20230303052048-c875a4ffab1a h1:NvhI/8DMFt2yV3eoYhw6P/XyWzzIKkMiGvFglJbWHWg= github.com/sagernet/sing v0.1.8-0.20230305055148-e16845727f76 h1:JCZ4tpEuT6U6oC87EaDBMsPg7+NxesIwESs4dzAGgJo=
github.com/sagernet/sing v0.1.8-0.20230303052048-c875a4ffab1a/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk= github.com/sagernet/sing v0.1.8-0.20230305055148-e16845727f76/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
github.com/sagernet/sing-dns v0.1.4 h1:7VxgeoSCiiazDSaXXQVcvrTBxFpOePPq/4XdgnUDN+0= github.com/sagernet/sing-dns v0.1.4 h1:7VxgeoSCiiazDSaXXQVcvrTBxFpOePPq/4XdgnUDN+0=
github.com/sagernet/sing-dns v0.1.4/go.mod h1:1+6pCa48B1AI78lD+/i/dLgpw4MwfnsSpZo0Ds8wzzk= github.com/sagernet/sing-dns v0.1.4/go.mod h1:1+6pCa48B1AI78lD+/i/dLgpw4MwfnsSpZo0Ds8wzzk=
github.com/sagernet/sing-shadowsocks v0.1.2-0.20230221080503-769c01d6bba9 h1:qS39eA4C7x+zhEkySbASrtmb6ebdy5v0y2M6mgkmSO0= github.com/sagernet/sing-shadowsocks v0.1.2-0.20230221080503-769c01d6bba9 h1:qS39eA4C7x+zhEkySbASrtmb6ebdy5v0y2M6mgkmSO0=
github.com/sagernet/sing-shadowsocks v0.1.2-0.20230221080503-769c01d6bba9/go.mod h1:f3mHTy5shnVM9l8UocMlJgC/1G/zdj5FuEuVXhDinGU= github.com/sagernet/sing-shadowsocks v0.1.2-0.20230221080503-769c01d6bba9/go.mod h1:f3mHTy5shnVM9l8UocMlJgC/1G/zdj5FuEuVXhDinGU=
github.com/sagernet/sing-shadowtls v0.0.0-20230221123345-78e50cd7b587 h1:OjIXlHT2bblZfp+ciupM4xY9+Ccpj9FsuHRtKRBv+Pg= github.com/sagernet/sing-shadowtls v0.1.0 h1:05MYce8aR5xfKIn+y7xRFsdKhKt44QZTSEQW+lG5IWQ=
github.com/sagernet/sing-shadowtls v0.0.0-20230221123345-78e50cd7b587/go.mod h1:Kn1VUIprdkwCgkS6SXYaLmIpKzQbqBIKJBMY+RvBhYc= github.com/sagernet/sing-shadowtls v0.1.0/go.mod h1:Kn1VUIprdkwCgkS6SXYaLmIpKzQbqBIKJBMY+RvBhYc=
github.com/sagernet/sing-tun v0.1.2-0.20230226091124-0cdb0eed74d9 h1:tq1kc0HFj/jfhLfVC1NJI6lex2g6w2W+gVsFu6H2Kis= github.com/sagernet/sing-tun v0.1.2-0.20230226091124-0cdb0eed74d9 h1:tq1kc0HFj/jfhLfVC1NJI6lex2g6w2W+gVsFu6H2Kis=
github.com/sagernet/sing-tun v0.1.2-0.20230226091124-0cdb0eed74d9/go.mod h1:KnRkwaDHbb06zgeNPu0LQ8A+vA9myMxKEgHN1brCPHg= github.com/sagernet/sing-tun v0.1.2-0.20230226091124-0cdb0eed74d9/go.mod h1:KnRkwaDHbb06zgeNPu0LQ8A+vA9myMxKEgHN1brCPHg=
github.com/sagernet/sing-vmess v0.1.3-0.20230303082804-627cc46ae68b h1:NZeF0ATeJwe4W3gTJNeIfTB6yBxai665q1HvDOaWmmU= github.com/sagernet/sing-vmess v0.1.3-0.20230303082804-627cc46ae68b h1:NZeF0ATeJwe4W3gTJNeIfTB6yBxai665q1HvDOaWmmU=

View file

@ -19,6 +19,7 @@ const (
clientPort clientPort
testPort testPort
otherPort otherPort
otherClientPort
) )
func TestShadowsocks(t *testing.T) { func TestShadowsocks(t *testing.T) {

View file

@ -9,6 +9,7 @@ import (
"github.com/sagernet/sing-box/option" "github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/transport/vless" "github.com/sagernet/sing-box/transport/vless"
"github.com/gofrs/uuid"
"github.com/spyzhov/ajson" "github.com/spyzhov/ajson"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -65,17 +66,17 @@ func TestVLESS(t *testing.T) {
func TestVLESSXRay(t *testing.T) { func TestVLESSXRay(t *testing.T) {
t.Run("origin", func(t *testing.T) { t.Run("origin", func(t *testing.T) {
testVLESSXray(t, "", "") testVLESSXrayOutbound(t, "", "")
}) })
t.Run("xudp", func(t *testing.T) { t.Run("xudp", func(t *testing.T) {
testVLESSXray(t, "xudp", "") testVLESSXrayOutbound(t, "xudp", "")
}) })
t.Run("vision", func(t *testing.T) { t.Run("vision", func(t *testing.T) {
testVLESSXray(t, "", vless.FlowVision) testVLESSXrayOutbound(t, "xudp", vless.FlowVision)
}) })
} }
func testVLESSXray(t *testing.T, packetEncoding string, flow string) { func testVLESSXrayOutbound(t *testing.T, packetEncoding string, flow string) {
_, certPem, keyPem := createSelfSignedCertificate(t, "example.org") _, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
content, err := os.ReadFile("config/vless-tls-server.json") content, err := os.ReadFile("config/vless-tls-server.json")
@ -397,3 +398,138 @@ func testVLESSSelfTLS(t *testing.T, flow string) {
}) })
testSuit(t, clientPort, testPort) testSuit(t, clientPort, testPort)
} }
func TestVLESSXrayInbound(t *testing.T) {
testVLESSXrayInbound(t, vless.FlowVision)
}
func testVLESSXrayInbound(t *testing.T, flow string) {
userId, err := uuid.DefaultGenerator.NewV4()
require.NoError(t, err)
_, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
startInstance(t, option.Options{
Inbounds: []option.Inbound{
{
Type: C.TypeVLESS,
VLESSOptions: option.VLESSInboundOptions{
ListenOptions: option.ListenOptions{
Listen: option.ListenAddress(netip.IPv4Unspecified()),
ListenPort: serverPort,
},
Users: []option.VLESSUser{
{
Name: "sekai",
UUID: userId.String(),
Flow: flow,
},
},
TLS: &option.InboundTLSOptions{
Enabled: true,
ServerName: "example.org",
CertificatePath: certPem,
KeyPath: keyPem,
},
},
},
{
Type: C.TypeTrojan,
Tag: "trojan",
TrojanOptions: option.TrojanInboundOptions{
ListenOptions: option.ListenOptions{
Listen: option.ListenAddress(netip.IPv4Unspecified()),
ListenPort: otherPort,
},
Users: []option.TrojanUser{
{
Name: "sekai",
Password: userId.String(),
},
},
TLS: &option.InboundTLSOptions{
Enabled: true,
ServerName: "example.org",
CertificatePath: certPem,
KeyPath: keyPem,
},
},
},
},
})
startInstance(t, option.Options{
Inbounds: []option.Inbound{
{
Type: C.TypeMixed,
Tag: "mixed-in",
MixedOptions: option.HTTPMixedInboundOptions{
ListenOptions: option.ListenOptions{
Listen: option.ListenAddress(netip.IPv4Unspecified()),
ListenPort: otherClientPort,
},
},
},
},
Outbounds: []option.Outbound{
{
Type: C.TypeTrojan,
Tag: "trojan-out",
TrojanOptions: option.TrojanOutboundOptions{
ServerOptions: option.ServerOptions{
Server: "127.0.0.1",
ServerPort: otherPort,
},
Password: userId.String(),
TLS: &option.OutboundTLSOptions{
Enabled: true,
ServerName: "example.org",
CertificatePath: certPem,
},
DialerOptions: option.DialerOptions{
Detour: "vless-out",
},
},
},
{
Type: C.TypeSocks,
Tag: "vless-out",
SocksOptions: option.SocksOutboundOptions{
ServerOptions: option.ServerOptions{
Server: "127.0.0.1",
ServerPort: clientPort,
},
},
},
},
})
content, err := os.ReadFile("config/vless-tls-client.json")
require.NoError(t, err)
config, err := ajson.Unmarshal(content)
require.NoError(t, err)
config.MustKey("inbounds").MustIndex(0).MustKey("port").SetNumeric(float64(clientPort))
outbound := config.MustKey("outbounds").MustIndex(0)
settings := outbound.MustKey("settings").MustKey("vnext").MustIndex(0)
settings.MustKey("port").SetNumeric(float64(serverPort))
user := settings.MustKey("users").MustIndex(0)
user.MustKey("id").SetString(userId.String())
user.MustKey("flow").SetString(flow)
content, err = ajson.Marshal(config)
require.NoError(t, err)
content, err = ajson.Marshal(config)
require.NoError(t, err)
startDockerContainer(t, DockerOptions{
Image: ImageXRayCore,
Ports: []uint16{clientPort},
EntryPoint: "xray",
Stdin: content,
Bind: map[string]string{
certPem: "/path/to/certificate.crt",
keyPem: "/path/to/private.key",
},
})
testTCP(t, otherClientPort, testPort)
}

View file

@ -32,8 +32,11 @@ func init() {
}) })
} }
const xrayChunkSize = 8192
type VisionConn struct { type VisionConn struct {
net.Conn net.Conn
reader *bufio.ChunkReader
writer N.VectorisedWriter writer N.VectorisedWriter
input *bytes.Reader input *bytes.Reader
rawInput *bytes.Buffer rawInput *bytes.Buffer
@ -78,6 +81,7 @@ func NewVisionConn(conn net.Conn, userUUID [16]byte, logger logger.Logger) (*Vis
rawInput, _ := reflectType.FieldByName("rawInput") rawInput, _ := reflectType.FieldByName("rawInput")
return &VisionConn{ return &VisionConn{
Conn: conn, Conn: conn,
reader: bufio.NewChunkReader(conn, xrayChunkSize),
writer: bufio.NewVectorisedWriter(conn), writer: bufio.NewVectorisedWriter(conn),
input: (*bytes.Reader)(unsafe.Pointer(reflectPointer + input.Offset)), input: (*bytes.Reader)(unsafe.Pointer(reflectPointer + input.Offset)),
rawInput: (*bytes.Buffer)(unsafe.Pointer(reflectPointer + rawInput.Offset)), rawInput: (*bytes.Buffer)(unsafe.Pointer(reflectPointer + rawInput.Offset)),
@ -100,22 +104,31 @@ func (c *VisionConn) Read(p []byte) (n int, err error) {
n, err = c.remainingReader.Read(p) n, err = c.remainingReader.Read(p)
if err == io.EOF { if err == io.EOF {
c.remainingReader = nil c.remainingReader = nil
if n > 0 {
err = nil
return
} }
if n > 0 {
return
} }
} }
if c.directRead { if c.directRead {
return c.netConn.Read(p) return c.netConn.Read(p)
} }
var bufferBytes []byte
if len(p) > xrayChunkSize {
n, err = c.Conn.Read(p) n, err = c.Conn.Read(p)
if err != nil { if err != nil {
return return
} }
buffer := p[:n] bufferBytes = p[:n]
} else {
buffer, err := c.reader.ReadChunk()
if err != nil {
return 0, err
}
defer buffer.FullReset()
bufferBytes = buffer.Bytes()
}
if c.withinPaddingBuffers || c.numberOfPacketToFilter > 0 { if c.withinPaddingBuffers || c.numberOfPacketToFilter > 0 {
buffers := c.unPadding(buffer) buffers := c.unPadding(bufferBytes)
if c.remainingContent == 0 && c.remainingPadding == 0 { if c.remainingContent == 0 && c.remainingPadding == 0 {
if c.currentCommand == 1 { if c.currentCommand == 1 {
c.withinPaddingBuffers = false c.withinPaddingBuffers = false
@ -156,7 +169,7 @@ func (c *VisionConn) Read(p []byte) (n int, err error) {
return c.remainingReader.Read(p) return c.remainingReader.Read(p)
} else { } else {
if c.numberOfPacketToFilter > 0 { if c.numberOfPacketToFilter > 0 {
c.filterTLS([][]byte{buffer}) c.filterTLS([][]byte{bufferBytes})
} }
return return
} }