diff --git a/testing/scenarios/data/test_5_client.json b/testing/scenarios/data/test_5_client.json deleted file mode 100644 index 111e1e46b..000000000 --- a/testing/scenarios/data/test_5_client.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "port": 50040, - "inbound": { - "listen": "127.0.0.1", - "protocol": "http", - "settings": {} - }, - "outbound": { - "protocol": "vmess", - "settings": { - "vnext": [ - { - "address": "127.0.0.1", - "port": 50041, - "users": [ - { - "id": "d17a1af7-efa5-42ca-b7e9-6a35282d737f", - "alterId": 10 - } - ] - } - ] - } - } -} diff --git a/testing/scenarios/data/test_5_server.json b/testing/scenarios/data/test_5_server.json deleted file mode 100644 index 7838fec3a..000000000 --- a/testing/scenarios/data/test_5_server.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "port": 50041, - "inbound": { - "listen": "127.0.0.1", - "protocol": "vmess", - "settings": { - "clients": [ - { - "id": "d17a1af7-efa5-42ca-b7e9-6a35282d737f", - "level": 1, - "alterId": 10 - } - ] - } - }, - "outbound": { - "protocol": "freedom", - "settings": {} - }, - "outboundDetour": [{ - "protocol": "blackhole", - "settings": { - "response": { - "type": "http" - } - }, - "tag": "blocked" - }], - "routing": { - "strategy": "rules", - "settings": { - "rules": [{ - "type": "field", - "port": "50049", - "outboundTag": "blocked" - }] - } - } -} diff --git a/testing/scenarios/data/test_6_client.json b/testing/scenarios/data/test_6_client.json deleted file mode 100644 index ec599acfa..000000000 --- a/testing/scenarios/data/test_6_client.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "log": { - "loglevel": "debug" - }, - "inbound": { - "port": 50050, - "listen": "127.0.0.1", - "protocol": "dokodemo-door", - "settings": { - "address": "127.0.0.1", - "port": 50052, - "network": "tcp,udp", - "timeout": 0 - } - }, - "outbound": { - "protocol": "shadowsocks", - "streamSettings": { - "network": "tcp", - "tcpSettings": { - "header": { - "type": "http", - "request": {}, - "response": {} - } - } - }, - "settings": { - "servers": [ - { - "address": "127.0.0.1", - "port": 50051, - "method": "aes-256-cfb", - "password": "v2ray-password" - } - ] - } - } -} diff --git a/testing/scenarios/data/test_6_server.json b/testing/scenarios/data/test_6_server.json deleted file mode 100644 index 90168f5bf..000000000 --- a/testing/scenarios/data/test_6_server.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "log": { - "loglevel": "debug" - }, - "inbound": { - "port": 50051, - "listen": "127.0.0.1", - "protocol": "shadowsocks", - "settings": { - "method": "aes-256-cfb", - "password": "v2ray-password" - }, - "streamSettings": { - "network": "tcp", - "tcpSettings": { - "header": { - "type": "http", - "request": {}, - "response": {} - } - } - } - }, - "inboundDetour": [ - { - "protocol": "shadowsocks", - "port": 50055, - "listen": "127.0.0.1", - "settings": { - "method": "aes-128-cfb", - "password": "v2ray-another", - "udp": true - }, - "streamSettings": { - "network": "tcp", - "tcpSettings": { - "header": { - "type": "http", - "request": {}, - "response": {} - } - } - } - }, - { - "protocol": "shadowsocks", - "port": 50056, - "listen": "127.0.0.1", - "settings": { - "method": "chacha20", - "password": "new-password", - "udp": true - } - } - ], - "outbound": { - "protocol": "freedom", - "settings": {} - } -} diff --git a/testing/scenarios/http_test.go b/testing/scenarios/http_test.go index e39fc1aaa..7075ced01 100644 --- a/testing/scenarios/http_test.go +++ b/testing/scenarios/http_test.go @@ -6,71 +6,68 @@ import ( "net/url" "testing" - "v2ray.com/core/common/net" + "v2ray.com/core" + "v2ray.com/core/app/proxyman" + v2net "v2ray.com/core/common/net" + "v2ray.com/core/common/serial" + "v2ray.com/core/proxy/freedom" + v2http "v2ray.com/core/proxy/http" "v2ray.com/core/testing/assert" - v2http "v2ray.com/core/testing/servers/http" + v2httptest "v2ray.com/core/testing/servers/http" ) -func TestHttpProxy(t *testing.T) { +func TestHttpConformance(t *testing.T) { assert := assert.On(t) - httpServer := &v2http.Server{ - Port: net.Port(50042), + httpServerPort := pickPort() + httpServer := &v2httptest.Server{ + Port: httpServerPort, PathHandler: make(map[string]http.HandlerFunc), } _, err := httpServer.Start() assert.Error(err).IsNil() defer httpServer.Close() - assert.Error(InitializeServerSetOnce("test_5")).IsNil() - - transport := &http.Transport{ - Proxy: func(req *http.Request) (*url.URL, error) { - return url.Parse("http://127.0.0.1:50040/") + serverPort := pickPort() + serverConfig := &core.Config{ + Inbound: []*proxyman.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: v2net.SinglePortRange(serverPort), + Listen: v2net.NewIPOrDomain(v2net.LocalHostIP), + }), + ProxySettings: serial.ToTypedMessage(&v2http.ServerConfig{}), + }, + }, + Outbound: []*proxyman.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&freedom.Config{}), + }, }, } - client := &http.Client{ - Transport: transport, + assert.Error(InitializeServerConfig(serverConfig)).IsNil() + + { + transport := &http.Transport{ + Proxy: func(req *http.Request) (*url.URL, error) { + return url.Parse("http://127.0.0.1:" + serverPort.String()) + }, + } + + client := &http.Client{ + Transport: transport, + } + + resp, err := client.Get("http://127.0.0.1:" + httpServerPort.String()) + assert.Error(err).IsNil() + assert.Int(resp.StatusCode).Equals(200) + + content, err := ioutil.ReadAll(resp.Body) + assert.Error(err).IsNil() + assert.String(string(content)).Equals("Home") + } - resp, err := client.Get("http://127.0.0.1:50042/") - assert.Error(err).IsNil() - assert.Int(resp.StatusCode).Equals(200) - - content, err := ioutil.ReadAll(resp.Body) - assert.Error(err).IsNil() - assert.String(string(content)).Equals("Home") - - CloseAllServers() -} - -func TestBlockHTTP(t *testing.T) { - assert := assert.On(t) - - httpServer := &v2http.Server{ - Port: net.Port(50042), - PathHandler: make(map[string]http.HandlerFunc), - } - _, err := httpServer.Start() - assert.Error(err).IsNil() - defer httpServer.Close() - - assert.Error(InitializeServerSetOnce("test_5")).IsNil() - - transport := &http.Transport{ - Proxy: func(req *http.Request) (*url.URL, error) { - return url.Parse("http://127.0.0.1:50040/") - }, - } - - client := &http.Client{ - Transport: transport, - } - - resp, err := client.Get("http://127.0.0.1:50049/") - assert.Error(err).IsNil() - assert.Int(resp.StatusCode).Equals(403) - CloseAllServers() } diff --git a/testing/scenarios/shadowsocks_test.go b/testing/scenarios/shadowsocks_test.go index 6bd81f313..fbafa6cb5 100644 --- a/testing/scenarios/shadowsocks_test.go +++ b/testing/scenarios/shadowsocks_test.go @@ -1,51 +1,255 @@ package scenarios import ( + "crypto/rand" "net" + "sync" "testing" "time" + "v2ray.com/core" + "v2ray.com/core/app/log" + "v2ray.com/core/app/proxyman" v2net "v2ray.com/core/common/net" + "v2ray.com/core/common/protocol" + "v2ray.com/core/common/serial" + "v2ray.com/core/proxy/dokodemo" + "v2ray.com/core/proxy/freedom" + "v2ray.com/core/proxy/shadowsocks" "v2ray.com/core/testing/assert" "v2ray.com/core/testing/servers/tcp" ) -func TestShadowsocksTCP(t *testing.T) { +func TestShadowsocksAES256TCP(t *testing.T) { assert := assert.On(t) - tcpServer := &tcp.Server{ - Port: v2net.Port(50052), - MsgProcessor: func(data []byte) []byte { - buffer := make([]byte, 0, 2048) - buffer = append(buffer, []byte("Processed: ")...) - buffer = append(buffer, data...) - return buffer - }, + tcpServer := tcp.Server{ + MsgProcessor: xor, } - _, err := tcpServer.Start() + dest, err := tcpServer.Start() assert.Error(err).IsNil() defer tcpServer.Close() - assert.Error(InitializeServerSetOnce("test_6")).IsNil() + account := serial.ToTypedMessage(&shadowsocks.Account{ + Password: "shadowsocks-password", + CipherType: shadowsocks.CipherType_AES_256_CFB, + Ota: shadowsocks.Account_Enabled, + }) - for i := 0; i < 1; i++ { - conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ - IP: []byte{127, 0, 0, 1}, - Port: 50050, - }) - assert.Error(err).IsNil() - - payload := "dokodemo request." - nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) - - expectedResponse := "Processed: " + payload - response := readFrom(conn, time.Second, len(expectedResponse)) - assert.String(string(response)).Equals(expectedResponse) - - conn.Close() + serverPort := pickPort() + serverConfig := &core.Config{ + Inbound: []*proxyman.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: v2net.SinglePortRange(serverPort), + Listen: v2net.NewIPOrDomain(v2net.LocalHostIP), + }), + ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{ + User: &protocol.User{ + Account: account, + }, + }), + }, + }, + Outbound: []*proxyman.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&freedom.Config{}), + }, + }, + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, } + clientPort := pickPort() + clientConfig := &core.Config{ + Inbound: []*proxyman.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: v2net.SinglePortRange(clientPort), + Listen: v2net.NewIPOrDomain(v2net.LocalHostIP), + }), + ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ + Address: v2net.NewIPOrDomain(dest.Address), + Port: uint32(dest.Port), + NetworkList: &v2net.NetworkList{ + Network: []v2net.Network{v2net.Network_TCP}, + }, + }), + }, + }, + Outbound: []*proxyman.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{ + Server: []*protocol.ServerEndpoint{ + { + Address: v2net.NewIPOrDomain(v2net.LocalHostIP), + Port: uint32(serverPort), + User: []*protocol.User{ + { + Account: account, + }, + }, + }, + }, + }), + }, + }, + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, + } + + assert.Error(InitializeServerConfig(serverConfig)).IsNil() + assert.Error(InitializeServerConfig(clientConfig)).IsNil() + + var wg sync.WaitGroup + wg.Add(10) + for i := 0; i < 10; i++ { + go func() { + conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ + IP: []byte{127, 0, 0, 1}, + Port: int(clientPort), + }) + assert.Error(err).IsNil() + + payload := make([]byte, 10240*1024) + rand.Read(payload) + + nBytes, err := conn.Write([]byte(payload)) + assert.Error(err).IsNil() + assert.Int(nBytes).Equals(len(payload)) + + response := readFrom(conn, time.Second*10, 10240*1024) + assert.Bytes(response).Equals(xor([]byte(payload))) + assert.Error(conn.Close()).IsNil() + wg.Done() + }() + } + wg.Wait() + + CloseAllServers() +} + +func TestShadowsocksChacha20TCP(t *testing.T) { + assert := assert.On(t) + + tcpServer := tcp.Server{ + MsgProcessor: xor, + } + dest, err := tcpServer.Start() + assert.Error(err).IsNil() + defer tcpServer.Close() + + account := serial.ToTypedMessage(&shadowsocks.Account{ + Password: "shadowsocks-password", + CipherType: shadowsocks.CipherType_CHACHA20_IETF, + Ota: shadowsocks.Account_Enabled, + }) + + serverPort := pickPort() + serverConfig := &core.Config{ + Inbound: []*proxyman.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: v2net.SinglePortRange(serverPort), + Listen: v2net.NewIPOrDomain(v2net.LocalHostIP), + }), + ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{ + User: &protocol.User{ + Account: account, + }, + }), + }, + }, + Outbound: []*proxyman.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&freedom.Config{}), + }, + }, + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, + } + + clientPort := pickPort() + clientConfig := &core.Config{ + Inbound: []*proxyman.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: v2net.SinglePortRange(clientPort), + Listen: v2net.NewIPOrDomain(v2net.LocalHostIP), + }), + ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ + Address: v2net.NewIPOrDomain(dest.Address), + Port: uint32(dest.Port), + NetworkList: &v2net.NetworkList{ + Network: []v2net.Network{v2net.Network_TCP}, + }, + }), + }, + }, + Outbound: []*proxyman.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{ + Server: []*protocol.ServerEndpoint{ + { + Address: v2net.NewIPOrDomain(v2net.LocalHostIP), + Port: uint32(serverPort), + User: []*protocol.User{ + { + Account: account, + }, + }, + }, + }, + }), + }, + }, + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, + } + + assert.Error(InitializeServerConfig(serverConfig)).IsNil() + assert.Error(InitializeServerConfig(clientConfig)).IsNil() + + var wg sync.WaitGroup + wg.Add(10) + for i := 0; i < 10; i++ { + go func() { + conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ + IP: []byte{127, 0, 0, 1}, + Port: int(clientPort), + }) + assert.Error(err).IsNil() + + payload := make([]byte, 10240*1024) + rand.Read(payload) + + nBytes, err := conn.Write([]byte(payload)) + assert.Error(err).IsNil() + assert.Int(nBytes).Equals(len(payload)) + + response := readFrom(conn, time.Second*10, 10240*1024) + assert.Bytes(response).Equals(xor([]byte(payload))) + assert.Error(conn.Close()).IsNil() + wg.Done() + }() + } + wg.Wait() + CloseAllServers() } diff --git a/testing/scenarios/transport_test.go b/testing/scenarios/transport_test.go index ab517f599..bb19cbc37 100644 --- a/testing/scenarios/transport_test.go +++ b/testing/scenarios/transport_test.go @@ -23,7 +23,7 @@ import ( tcptransport "v2ray.com/core/transport/internet/tcp" ) -func TestNoOpConnectionHeader(t *testing.T) { +func TestHttpConnectionHeader(t *testing.T) { assert := assert.On(t) tcpServer := tcp.Server{