From 4a0df713aa0a1fb0c6732541252ea9dfb515f1e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Thu, 1 Sep 2022 20:04:04 +0800 Subject: [PATCH] Add ws compatibility test --- test/config/vmess-ws-client.json | 52 ++++++++ test/config/vmess-ws-server.json | 41 +++++++ test/direct_test.go | 3 - test/go.mod | 8 +- test/go.sum | 16 +-- test/hysteria_test.go | 9 -- test/inbound_detour_test.go | 3 - test/mux_test.go | 6 - test/naive_test.go | 9 -- test/shadowsocks_test.go | 12 -- test/trojan_test.go | 6 - test/v2ray_grpc_test.go | 6 - test/v2ray_transport_test.go | 37 ------ test/v2ray_ws_test.go | 197 +++++++++++++++++++++++++++++++ test/vmess_test.go | 9 -- test/wireguard_test.go | 3 - transport/v2raywebsocket/conn.go | 3 + 17 files changed, 305 insertions(+), 115 deletions(-) create mode 100644 test/config/vmess-ws-client.json create mode 100644 test/config/vmess-ws-server.json create mode 100644 test/v2ray_ws_test.go diff --git a/test/config/vmess-ws-client.json b/test/config/vmess-ws-client.json new file mode 100644 index 00000000..532ef134 --- /dev/null +++ b/test/config/vmess-ws-client.json @@ -0,0 +1,52 @@ +{ + "log": { + "loglevel": "debug" + }, + "inbounds": [ + { + "listen": "127.0.0.1", + "port": "1080", + "protocol": "socks", + "settings": { + "auth": "noauth", + "udp": true, + "ip": "127.0.0.1" + } + } + ], + "outbounds": [ + { + "protocol": "vmess", + "settings": { + "vnext": [ + { + "address": "127.0.0.1", + "port": 1234, + "users": [ + { + "id": "" + } + ] + } + ] + }, + "streamSettings": { + "network": "ws", + "security": "tls", + "tlsSettings": { + "serverName": "example.org", + "certificates": [ + { + "certificateFile": "/path/to/certificate.crt", + "keyFile": "/path/to/private.key" + } + ] + }, + "wsSettings": { + "maxEarlyData": 2048, + "earlyDataHeaderName": "" + } + } + } + ] +} \ No newline at end of file diff --git a/test/config/vmess-ws-server.json b/test/config/vmess-ws-server.json new file mode 100644 index 00000000..7eaef4ff --- /dev/null +++ b/test/config/vmess-ws-server.json @@ -0,0 +1,41 @@ +{ + "log": { + "loglevel": "debug" + }, + "inbounds": [ + { + "listen": "0.0.0.0", + "port": 1234, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "b831381d-6324-4d53-ad4f-8cda48b30811" + } + ] + }, + "streamSettings": { + "network": "ws", + "security": "tls", + "tlsSettings": { + "serverName": "example.org", + "certificates": [ + { + "certificateFile": "/path/to/certificate.crt", + "keyFile": "/path/to/private.key" + } + ] + }, + "wsSettings": { + "maxEarlyData": 2048, + "earlyDataHeaderName": "" + } + } + } + ], + "outbounds": [ + { + "protocol": "freedom" + } + ] +} \ No newline at end of file diff --git a/test/direct_test.go b/test/direct_test.go index c03b39fe..ad48ae98 100644 --- a/test/direct_test.go +++ b/test/direct_test.go @@ -10,9 +10,6 @@ import ( func TestProxyProtocol(t *testing.T) { startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, diff --git a/test/go.mod b/test/go.mod index 67bff758..4378f682 100644 --- a/test/go.mod +++ b/test/go.mod @@ -62,22 +62,22 @@ require ( github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666 // indirect github.com/sagernet/sing-tun v0.0.0-20220828031750-185b6c880a83 // indirect github.com/sagernet/sing-vmess v0.0.0-20220829020559-33915075430c // indirect - github.com/sagernet/smux v0.0.0-20220812084127-e2d085ee3939 // indirect + github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 // indirect github.com/sirupsen/logrus v1.8.1 // indirect github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.22.0 // indirect go4.org/netipx v0.0.0-20220812043211-3cc044ffd68d // indirect - golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d // indirect + golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 // indirect + golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect golang.org/x/tools v0.1.11-0.20220513221640-090b14e8501f // indirect golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect - golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478 // indirect + golang.zx2c4.com/wireguard v0.0.0-20220829161405-d1d08426b27b // indirect google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f // indirect google.golang.org/grpc v1.49.0 // indirect google.golang.org/protobuf v1.28.1 // indirect diff --git a/test/go.sum b/test/go.sum index afb1c1ec..484663b5 100644 --- a/test/go.sum +++ b/test/go.sum @@ -165,8 +165,8 @@ github.com/sagernet/sing-tun v0.0.0-20220828031750-185b6c880a83 h1:SoWiHYuOCVedq github.com/sagernet/sing-tun v0.0.0-20220828031750-185b6c880a83/go.mod h1:76r07HS1WRcEI4mE9pFsohfTBUt1j/G9Avz6DaOP3VU= github.com/sagernet/sing-vmess v0.0.0-20220829020559-33915075430c h1:92Gn78/z/t6CkzZ4XWG/uPiCxhUmjPULFEHFMDY6K8k= github.com/sagernet/sing-vmess v0.0.0-20220829020559-33915075430c/go.mod h1:82O6gzbxLha/W/jxSVQbsqf2lVdRTjMIgyLug0lpJps= -github.com/sagernet/smux v0.0.0-20220812084127-e2d085ee3939 h1:pB1Dh1NbwVrLhQhotr4O4Hs3yhiBzmg3AvnUyYjL4x4= -github.com/sagernet/smux v0.0.0-20220812084127-e2d085ee3939/go.mod h1:yedWtra8nyGJ+SyI+ziwuaGMzBatbB10P1IOOZbbSK8= +github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 h1:5VBIbVw9q7aKbrFdT83mjkyvQ+VaRsQ6yflTepfln38= +github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195/go.mod h1:yedWtra8nyGJ+SyI+ziwuaGMzBatbB10P1IOOZbbSK8= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= @@ -205,8 +205,8 @@ golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaE golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d h1:3qF+Z8Hkrw9sOhrFHti9TlB1Hkac1x+DNRkv0XQiFjo= -golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM= +golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= @@ -275,8 +275,8 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 h1:UiNENfZ8gDvpiWw7IpOMQ27spWmThO1RwwdQVbJahJM= -golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY= +golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -311,8 +311,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY= golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= -golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478 h1:vDy//hdR+GnROE3OdYbQKt9rdtNdHkDtONvpRwmls/0= -golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U= +golang.zx2c4.com/wireguard v0.0.0-20220829161405-d1d08426b27b h1:qgrKnOfe1zyURRNdmDlGbN32i38Zjmw0B1+TMdHcOvg= +golang.zx2c4.com/wireguard v0.0.0-20220829161405-d1d08426b27b/go.mod h1:6y4CqPAy54NwiN4nC8K+R1eMpQDB1P2d25qmunh2RSA= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= diff --git a/test/hysteria_test.go b/test/hysteria_test.go index 9afe8c81..cb21bc3f 100644 --- a/test/hysteria_test.go +++ b/test/hysteria_test.go @@ -14,9 +14,6 @@ func TestHysteriaSelf(t *testing.T) { } _, certPem, keyPem := createSelfSignedCertificate(t, "example.org") startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, @@ -92,9 +89,6 @@ func TestHysteriaInbound(t *testing.T) { } caPem, certPem, keyPem := createSelfSignedCertificate(t, "example.org") startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeHysteria, @@ -145,9 +139,6 @@ func TestHysteriaOutbound(t *testing.T) { }, }) startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, diff --git a/test/inbound_detour_test.go b/test/inbound_detour_test.go index 406f1f03..d21514b1 100644 --- a/test/inbound_detour_test.go +++ b/test/inbound_detour_test.go @@ -13,9 +13,6 @@ func TestChainedInbound(t *testing.T) { method := shadowaead_2022.List[0] password := mkBase64(t, 16) startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, diff --git a/test/mux_test.go b/test/mux_test.go index 836d3837..36caace1 100644 --- a/test/mux_test.go +++ b/test/mux_test.go @@ -37,9 +37,6 @@ func testShadowsocksMux(t *testing.T, protocol string) { method := shadowaead_2022.List[0] password := mkBase64(t, 16) startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, @@ -101,9 +98,6 @@ func testShadowsocksMux(t *testing.T, protocol string) { func testVMessMux(t *testing.T, protocol string) { user, _ := uuid.NewV4() startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, diff --git a/test/naive_test.go b/test/naive_test.go index 83e15017..25bb4c38 100644 --- a/test/naive_test.go +++ b/test/naive_test.go @@ -13,9 +13,6 @@ import ( func TestNaiveInboundWithNginx(t *testing.T) { caPem, certPem, keyPem := createSelfSignedCertificate(t, "example.org") startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeNaive, @@ -62,9 +59,6 @@ func TestNaiveInboundWithNginx(t *testing.T) { func TestNaiveInbound(t *testing.T) { caPem, certPem, keyPem := createSelfSignedCertificate(t, "example.org") startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeNaive, @@ -110,9 +104,6 @@ func TestNaiveHTTP3Inbound(t *testing.T) { } caPem, certPem, keyPem := createSelfSignedCertificate(t, "example.org") startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeNaive, diff --git a/test/shadowsocks_test.go b/test/shadowsocks_test.go index 2e7173c0..ec2114d5 100644 --- a/test/shadowsocks_test.go +++ b/test/shadowsocks_test.go @@ -77,9 +77,6 @@ func testShadowsocksInboundWithShadowsocksRust(t *testing.T, method string, pass Cmd: []string{"-s", F.ToString("127.0.0.1:", serverPort), "-b", F.ToString("0.0.0.0:", clientPort), "-m", method, "-k", password, "-U"}, }) startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeShadowsocks, @@ -105,9 +102,6 @@ func testShadowsocksOutboundWithShadowsocksRust(t *testing.T, method string, pas Cmd: []string{"-s", F.ToString("0.0.0.0:", serverPort), "-m", method, "-k", password, "-U"}, }) startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, @@ -138,9 +132,6 @@ func testShadowsocksOutboundWithShadowsocksRust(t *testing.T, method string, pas func testShadowsocksSelf(t *testing.T, method string, password string) { startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, @@ -199,9 +190,6 @@ func TestShadowsocksUoT(t *testing.T) { method := shadowaead_2022.List[0] password := mkBase64(t, 16) startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, diff --git a/test/trojan_test.go b/test/trojan_test.go index 9fe833c3..b24d5e3d 100644 --- a/test/trojan_test.go +++ b/test/trojan_test.go @@ -20,9 +20,6 @@ func TestTrojanOutbound(t *testing.T) { }, }) startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, @@ -58,9 +55,6 @@ func TestTrojanOutbound(t *testing.T) { func TestTrojanSelf(t *testing.T) { _, certPem, keyPem := createSelfSignedCertificate(t, "example.org") startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, diff --git a/test/v2ray_grpc_test.go b/test/v2ray_grpc_test.go index 641ddc39..3569e0d8 100644 --- a/test/v2ray_grpc_test.go +++ b/test/v2ray_grpc_test.go @@ -27,9 +27,6 @@ func testV2RayGRPCInbound(t *testing.T, forceLite bool) { require.NoError(t, err) _, certPem, keyPem := createSelfSignedCertificate(t, "example.org") startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeVMess, @@ -125,9 +122,6 @@ func testV2RayGRPCOutbound(t *testing.T, forceLite bool) { }, }) startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, diff --git a/test/v2ray_transport_test.go b/test/v2ray_transport_test.go index 3f1caae0..d17cc890 100644 --- a/test/v2ray_transport_test.go +++ b/test/v2ray_transport_test.go @@ -11,31 +11,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestV2RayWebscoketSelf(t *testing.T) { - t.Run("basic", func(t *testing.T) { - testV2RayTransportSelf(t, &option.V2RayTransportOptions{ - Type: C.V2RayTransportTypeWebsocket, - }) - }) - t.Run("v2ray early data", func(t *testing.T) { - testV2RayTransportSelf(t, &option.V2RayTransportOptions{ - Type: C.V2RayTransportTypeWebsocket, - WebsocketOptions: option.V2RayWebsocketOptions{ - MaxEarlyData: 2048, - }, - }) - }) - t.Run("xray early data", func(t *testing.T) { - testV2RayTransportSelf(t, &option.V2RayTransportOptions{ - Type: C.V2RayTransportTypeWebsocket, - WebsocketOptions: option.V2RayWebsocketOptions{ - MaxEarlyData: 2048, - EarlyDataHeaderName: "Sec-WebSocket-Protocol", - }, - }) - }) -} - func TestV2RayHTTPSelf(t *testing.T) { testV2RayTransportSelf(t, &option.V2RayTransportOptions{ Type: C.V2RayTransportTypeHTTP, @@ -69,9 +44,6 @@ func testVMessTransportSelf(t *testing.T, server *option.V2RayTransportOptions, require.NoError(t, err) _, certPem, keyPem := createSelfSignedCertificate(t, "example.org") startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, @@ -148,9 +120,6 @@ func testTrojanTransportSelf(t *testing.T, server *option.V2RayTransportOptions, require.NoError(t, err) _, certPem, keyPem := createSelfSignedCertificate(t, "example.org") startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, @@ -229,9 +198,6 @@ func TestVMessQUICSelf(t *testing.T) { require.NoError(t, err) _, certPem, keyPem := createSelfSignedCertificate(t, "example.org") startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, @@ -307,9 +273,6 @@ func testV2RayTransportNOTLSSelf(t *testing.T, transport *option.V2RayTransportO user, err := uuid.DefaultGenerator.NewV4() require.NoError(t, err) startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, diff --git a/test/v2ray_ws_test.go b/test/v2ray_ws_test.go new file mode 100644 index 00000000..4d6d03c1 --- /dev/null +++ b/test/v2ray_ws_test.go @@ -0,0 +1,197 @@ +package main + +import ( + "net/netip" + "os" + "testing" + + C "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-box/option" + + "github.com/gofrs/uuid" + "github.com/spyzhov/ajson" + "github.com/stretchr/testify/require" +) + +func TestV2RayWebsocket(t *testing.T) { + t.Run("self", func(t *testing.T) { + testV2RayTransportSelf(t, &option.V2RayTransportOptions{ + Type: C.V2RayTransportTypeWebsocket, + }) + }) + t.Run("self-early-data", func(t *testing.T) { + testV2RayTransportSelf(t, &option.V2RayTransportOptions{ + Type: C.V2RayTransportTypeWebsocket, + WebsocketOptions: option.V2RayWebsocketOptions{ + MaxEarlyData: 2048, + }, + }) + }) + t.Run("self-xray-early-data", func(t *testing.T) { + testV2RayTransportSelf(t, &option.V2RayTransportOptions{ + Type: C.V2RayTransportTypeWebsocket, + WebsocketOptions: option.V2RayWebsocketOptions{ + MaxEarlyData: 2048, + EarlyDataHeaderName: "Sec-WebSocket-Protocol", + }, + }) + }) + t.Run("inbound", func(t *testing.T) { + testV2RayWebsocketInbound(t, 0, "") + }) + t.Run("inbound-early-data", func(t *testing.T) { + testV2RayWebsocketInbound(t, 2048, "") + }) + t.Run("inbound-xray-early-data", func(t *testing.T) { + testV2RayWebsocketInbound(t, 2048, "Sec-WebSocket-Protocol") + }) + t.Run("outbound", func(t *testing.T) { + testV2RayWebsocketOutbound(t, 0, "") + }) + t.Run("outbound-early-data", func(t *testing.T) { + testV2RayWebsocketOutbound(t, 2048, "") + }) + t.Run("outbound-xray-early-data", func(t *testing.T) { + testV2RayWebsocketOutbound(t, 2048, "Sec-WebSocket-Protocol") + }) +} + +func testV2RayWebsocketInbound(t *testing.T, maxEarlyData uint32, earlyDataHeaderName 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.TypeVMess, + VMessOptions: option.VMessInboundOptions{ + ListenOptions: option.ListenOptions{ + Listen: option.ListenAddress(netip.IPv4Unspecified()), + ListenPort: serverPort, + }, + Users: []option.VMessUser{ + { + Name: "sekai", + UUID: userId.String(), + }, + }, + TLS: &option.InboundTLSOptions{ + Enabled: true, + ServerName: "example.org", + CertificatePath: certPem, + KeyPath: keyPem, + }, + Transport: &option.V2RayTransportOptions{ + Type: C.V2RayTransportTypeWebsocket, + WebsocketOptions: option.V2RayWebsocketOptions{ + MaxEarlyData: maxEarlyData, + EarlyDataHeaderName: earlyDataHeaderName, + }, + }, + }, + }, + }, + }) + content, err := os.ReadFile("config/vmess-ws-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()) + wsSettings := outbound.MustKey("streamSettings").MustKey("wsSettings") + wsSettings.MustKey("maxEarlyData").SetNumeric(float64(maxEarlyData)) + wsSettings.MustKey("earlyDataHeaderName").SetString(earlyDataHeaderName) + content, err = ajson.Marshal(config) + require.NoError(t, err) + + startDockerContainer(t, DockerOptions{ + Image: ImageV2RayCore, + Ports: []uint16{serverPort, testPort}, + EntryPoint: "v2ray", + Stdin: content, + Bind: map[string]string{ + certPem: "/path/to/certificate.crt", + keyPem: "/path/to/private.key", + }, + }) + + testSuitSimple(t, clientPort, testPort) +} + +func testV2RayWebsocketOutbound(t *testing.T, maxEarlyData uint32, earlyDataHeaderName string) { + userId, err := uuid.DefaultGenerator.NewV4() + require.NoError(t, err) + _, certPem, keyPem := createSelfSignedCertificate(t, "example.org") + + content, err := os.ReadFile("config/vmess-ws-server.json") + require.NoError(t, err) + config, err := ajson.Unmarshal(content) + require.NoError(t, err) + + inbound := config.MustKey("inbounds").MustIndex(0) + inbound.MustKey("port").SetNumeric(float64(serverPort)) + inbound.MustKey("settings").MustKey("clients").MustIndex(0).MustKey("id").SetString(userId.String()) + wsSettings := inbound.MustKey("streamSettings").MustKey("wsSettings") + wsSettings.MustKey("maxEarlyData").SetNumeric(float64(maxEarlyData)) + wsSettings.MustKey("earlyDataHeaderName").SetString(earlyDataHeaderName) + content, err = ajson.Marshal(config) + require.NoError(t, err) + + startDockerContainer(t, DockerOptions{ + Image: ImageV2RayCore, + Ports: []uint16{serverPort, testPort}, + EntryPoint: "v2ray", + Stdin: content, + Env: []string{"V2RAY_VMESS_AEAD_FORCED=false"}, + Bind: map[string]string{ + certPem: "/path/to/certificate.crt", + keyPem: "/path/to/private.key", + }, + }) + 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: clientPort, + }, + }, + }, + }, + Outbounds: []option.Outbound{ + { + Type: C.TypeVMess, + Tag: "vmess-out", + VMessOptions: option.VMessOutboundOptions{ + ServerOptions: option.ServerOptions{ + Server: "127.0.0.1", + ServerPort: serverPort, + }, + UUID: userId.String(), + Security: "zero", + TLS: &option.OutboundTLSOptions{ + Enabled: true, + ServerName: "example.org", + CertificatePath: certPem, + }, + Transport: &option.V2RayTransportOptions{ + Type: C.V2RayTransportTypeWebsocket, + WebsocketOptions: option.V2RayWebsocketOptions{ + MaxEarlyData: maxEarlyData, + EarlyDataHeaderName: earlyDataHeaderName, + }, + }, + }, + }, + }, + }) + testSuitSimple(t, clientPort, testPort) +} diff --git a/test/vmess_test.go b/test/vmess_test.go index 386e8420..dd89b2ab 100644 --- a/test/vmess_test.go +++ b/test/vmess_test.go @@ -182,9 +182,6 @@ func testVMessInboundWithV2Ray(t *testing.T, security string, uuid uuid.UUID, al }) startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeVMess, @@ -231,9 +228,6 @@ func testVMessOutboundWithV2Ray(t *testing.T, security string, uuid uuid.UUID, g }) startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, @@ -267,9 +261,6 @@ func testVMessOutboundWithV2Ray(t *testing.T, security string, uuid uuid.UUID, g func testVMessSelf(t *testing.T, security string, uuid uuid.UUID, alterId int, globalPadding bool, authenticatedLength bool, packetAddr bool) { startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, diff --git a/test/wireguard_test.go b/test/wireguard_test.go index 9e04b96a..05b0d120 100644 --- a/test/wireguard_test.go +++ b/test/wireguard_test.go @@ -21,9 +21,6 @@ func TestWireGuard(t *testing.T) { }) time.Sleep(5 * time.Second) startInstance(t, option.Options{ - Log: &option.LogOptions{ - Level: "error", - }, Inbounds: []option.Inbound{ { Type: C.TypeMixed, diff --git a/transport/v2raywebsocket/conn.go b/transport/v2raywebsocket/conn.go index 68fdc8e8..fa8ea04a 100644 --- a/transport/v2raywebsocket/conn.go +++ b/transport/v2raywebsocket/conn.go @@ -167,6 +167,9 @@ func (c *EarlyWebsocketConn) SetWriteDeadline(t time.Time) error { func wrapError(err error) error { if websocket.IsCloseError(err, websocket.CloseNormalClosure) { + return io.EOF + } + if websocket.IsCloseError(err, websocket.CloseAbnormalClosure) { return net.ErrClosed } return err