github.com/xtls/xray-core@v1.8.12-0.20240518155711-3168d27b0bdb/testing/scenarios/socks_test.go (about)

     1  package scenarios
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/xtls/xray-core/app/proxyman"
     8  	"github.com/xtls/xray-core/app/router"
     9  	"github.com/xtls/xray-core/common"
    10  	"github.com/xtls/xray-core/common/net"
    11  	"github.com/xtls/xray-core/common/protocol"
    12  	"github.com/xtls/xray-core/common/serial"
    13  	"github.com/xtls/xray-core/core"
    14  	"github.com/xtls/xray-core/proxy/blackhole"
    15  	"github.com/xtls/xray-core/proxy/dokodemo"
    16  	"github.com/xtls/xray-core/proxy/freedom"
    17  	"github.com/xtls/xray-core/proxy/socks"
    18  	"github.com/xtls/xray-core/testing/servers/tcp"
    19  	"github.com/xtls/xray-core/testing/servers/udp"
    20  	xproxy "golang.org/x/net/proxy"
    21  	socks4 "h12.io/socks"
    22  )
    23  
    24  func TestSocksBridgeTCP(t *testing.T) {
    25  	tcpServer := tcp.Server{
    26  		MsgProcessor: xor,
    27  	}
    28  	dest, err := tcpServer.Start()
    29  	common.Must(err)
    30  	defer tcpServer.Close()
    31  
    32  	serverPort := tcp.PickPort()
    33  	serverConfig := &core.Config{
    34  		Inbound: []*core.InboundHandlerConfig{
    35  			{
    36  				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
    37  					PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
    38  					Listen:   net.NewIPOrDomain(net.LocalHostIP),
    39  				}),
    40  				ProxySettings: serial.ToTypedMessage(&socks.ServerConfig{
    41  					AuthType: socks.AuthType_PASSWORD,
    42  					Accounts: map[string]string{
    43  						"Test Account": "Test Password",
    44  					},
    45  					Address:    net.NewIPOrDomain(net.LocalHostIP),
    46  					UdpEnabled: false,
    47  				}),
    48  			},
    49  		},
    50  		Outbound: []*core.OutboundHandlerConfig{
    51  			{
    52  				ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
    53  			},
    54  		},
    55  	}
    56  
    57  	clientPort := tcp.PickPort()
    58  	clientConfig := &core.Config{
    59  		Inbound: []*core.InboundHandlerConfig{
    60  			{
    61  				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
    62  					PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(clientPort)}},
    63  					Listen:   net.NewIPOrDomain(net.LocalHostIP),
    64  				}),
    65  				ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
    66  					Address: net.NewIPOrDomain(dest.Address),
    67  					Port:    uint32(dest.Port),
    68  					NetworkList: &net.NetworkList{
    69  						Network: []net.Network{net.Network_TCP},
    70  					},
    71  				}),
    72  			},
    73  		},
    74  		Outbound: []*core.OutboundHandlerConfig{
    75  			{
    76  				ProxySettings: serial.ToTypedMessage(&socks.ClientConfig{
    77  					Server: []*protocol.ServerEndpoint{
    78  						{
    79  							Address: net.NewIPOrDomain(net.LocalHostIP),
    80  							Port:    uint32(serverPort),
    81  							User: []*protocol.User{
    82  								{
    83  									Account: serial.ToTypedMessage(&socks.Account{
    84  										Username: "Test Account",
    85  										Password: "Test Password",
    86  									}),
    87  								},
    88  							},
    89  						},
    90  					},
    91  				}),
    92  			},
    93  		},
    94  	}
    95  
    96  	servers, err := InitializeServerConfigs(serverConfig, clientConfig)
    97  	common.Must(err)
    98  	defer CloseAllServers(servers)
    99  
   100  	if err := testTCPConn(clientPort, 1024, time.Second*2)(); err != nil {
   101  		t.Error(err)
   102  	}
   103  }
   104  
   105  func TestSocksBridageUDP(t *testing.T) {
   106  	udpServer := udp.Server{
   107  		MsgProcessor: xor,
   108  	}
   109  	dest, err := udpServer.Start()
   110  	common.Must(err)
   111  	defer udpServer.Close()
   112  
   113  	retry := 1
   114  	serverPort := tcp.PickPort()
   115  	for {
   116  		serverConfig := &core.Config{
   117  			Inbound: []*core.InboundHandlerConfig{
   118  				{
   119  					ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
   120  						PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
   121  						Listen:   net.NewIPOrDomain(net.LocalHostIP),
   122  					}),
   123  					ProxySettings: serial.ToTypedMessage(&socks.ServerConfig{
   124  						AuthType: socks.AuthType_PASSWORD,
   125  						Accounts: map[string]string{
   126  							"Test Account": "Test Password",
   127  						},
   128  						Address:    net.NewIPOrDomain(net.LocalHostIP),
   129  						UdpEnabled: true,
   130  					}),
   131  				},
   132  				{
   133  					ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
   134  						PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort + 1)}},
   135  						Listen:   net.NewIPOrDomain(net.LocalHostIP),
   136  					}),
   137  					ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
   138  						Address: net.NewIPOrDomain(dest.Address),
   139  						Port:    uint32(dest.Port),
   140  						NetworkList: &net.NetworkList{
   141  							Network: []net.Network{net.Network_UDP},
   142  						},
   143  					}),
   144  				},
   145  			},
   146  			Outbound: []*core.OutboundHandlerConfig{
   147  				{
   148  					ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
   149  				},
   150  			},
   151  		}
   152  
   153  		server, _ := InitializeServerConfig(serverConfig)
   154  		if server != nil && WaitConnAvailableWithTest(t, testUDPConn(serverPort+1, 1024, time.Second*2)) {
   155  			defer CloseServer(server)
   156  			break
   157  		}
   158  		retry++
   159  		if retry > 5 {
   160  			t.Fatal("All attempts failed to start server")
   161  		}
   162  		serverPort = tcp.PickPort()
   163  	}
   164  
   165  	clientPort := udp.PickPort()
   166  	clientConfig := &core.Config{
   167  		Inbound: []*core.InboundHandlerConfig{
   168  			{
   169  				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
   170  					PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(clientPort)}},
   171  					Listen:   net.NewIPOrDomain(net.LocalHostIP),
   172  				}),
   173  				ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
   174  					Address: net.NewIPOrDomain(dest.Address),
   175  					Port:    uint32(dest.Port),
   176  					NetworkList: &net.NetworkList{
   177  						Network: []net.Network{net.Network_UDP},
   178  					},
   179  				}),
   180  			},
   181  		},
   182  		Outbound: []*core.OutboundHandlerConfig{
   183  			{
   184  				ProxySettings: serial.ToTypedMessage(&socks.ClientConfig{
   185  					Server: []*protocol.ServerEndpoint{
   186  						{
   187  							Address: net.NewIPOrDomain(net.LocalHostIP),
   188  							Port:    uint32(serverPort),
   189  							User: []*protocol.User{
   190  								{
   191  									Account: serial.ToTypedMessage(&socks.Account{
   192  										Username: "Test Account",
   193  										Password: "Test Password",
   194  									}),
   195  								},
   196  							},
   197  						},
   198  					},
   199  				}),
   200  			},
   201  		},
   202  	}
   203  
   204  	server, err := InitializeServerConfig(clientConfig)
   205  	common.Must(err)
   206  	defer CloseServer(server)
   207  
   208  	if !WaitConnAvailableWithTest(t, testUDPConn(clientPort, 1024, time.Second*2)) {
   209  		t.Fail()
   210  	}
   211  }
   212  
   213  func TestSocksBridageUDPWithRouting(t *testing.T) {
   214  	udpServer := udp.Server{
   215  		MsgProcessor: xor,
   216  	}
   217  	dest, err := udpServer.Start()
   218  	common.Must(err)
   219  	defer udpServer.Close()
   220  
   221  	retry := 1
   222  	serverPort := tcp.PickPort()
   223  	for {
   224  		serverConfig := &core.Config{
   225  			App: []*serial.TypedMessage{
   226  				serial.ToTypedMessage(&router.Config{
   227  					Rule: []*router.RoutingRule{
   228  						{
   229  							TargetTag: &router.RoutingRule_Tag{
   230  								Tag: "out",
   231  							},
   232  							InboundTag: []string{"socks", "dokodemo"},
   233  						},
   234  					},
   235  				}),
   236  			},
   237  			Inbound: []*core.InboundHandlerConfig{
   238  				{
   239  					Tag: "socks",
   240  					ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
   241  						PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
   242  						Listen:   net.NewIPOrDomain(net.LocalHostIP),
   243  					}),
   244  					ProxySettings: serial.ToTypedMessage(&socks.ServerConfig{
   245  						AuthType:   socks.AuthType_NO_AUTH,
   246  						Address:    net.NewIPOrDomain(net.LocalHostIP),
   247  						UdpEnabled: true,
   248  					}),
   249  				},
   250  				{
   251  					Tag: "dokodemo",
   252  					ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
   253  						PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort + 1)}},
   254  						Listen:   net.NewIPOrDomain(net.LocalHostIP),
   255  					}),
   256  					ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
   257  						Address: net.NewIPOrDomain(dest.Address),
   258  						Port:    uint32(dest.Port),
   259  						NetworkList: &net.NetworkList{
   260  							Network: []net.Network{net.Network_UDP},
   261  						},
   262  					}),
   263  				},
   264  			},
   265  			Outbound: []*core.OutboundHandlerConfig{
   266  				{
   267  					ProxySettings: serial.ToTypedMessage(&blackhole.Config{}),
   268  				},
   269  				{
   270  					Tag:           "out",
   271  					ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
   272  				},
   273  			},
   274  		}
   275  
   276  		server, _ := InitializeServerConfig(serverConfig)
   277  		if server != nil && WaitConnAvailableWithTest(t, testUDPConn(serverPort+1, 1024, time.Second*2)) {
   278  			defer CloseServer(server)
   279  			break
   280  		}
   281  		retry++
   282  		if retry > 5 {
   283  			t.Fatal("All attempts failed to start server")
   284  		}
   285  		serverPort = tcp.PickPort()
   286  	}
   287  
   288  	clientPort := udp.PickPort()
   289  	clientConfig := &core.Config{
   290  		Inbound: []*core.InboundHandlerConfig{
   291  			{
   292  				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
   293  					PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(clientPort)}},
   294  					Listen:   net.NewIPOrDomain(net.LocalHostIP),
   295  				}),
   296  				ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
   297  					Address: net.NewIPOrDomain(dest.Address),
   298  					Port:    uint32(dest.Port),
   299  					NetworkList: &net.NetworkList{
   300  						Network: []net.Network{net.Network_UDP},
   301  					},
   302  				}),
   303  			},
   304  		},
   305  		Outbound: []*core.OutboundHandlerConfig{
   306  			{
   307  				ProxySettings: serial.ToTypedMessage(&socks.ClientConfig{
   308  					Server: []*protocol.ServerEndpoint{
   309  						{
   310  							Address: net.NewIPOrDomain(net.LocalHostIP),
   311  							Port:    uint32(serverPort),
   312  						},
   313  					},
   314  				}),
   315  			},
   316  		},
   317  	}
   318  
   319  	server, err := InitializeServerConfig(clientConfig)
   320  	common.Must(err)
   321  	defer CloseServer(server)
   322  
   323  	if !WaitConnAvailableWithTest(t, testUDPConn(clientPort, 1024, time.Second*2)) {
   324  		t.Fail()
   325  	}
   326  }
   327  
   328  func TestSocksConformanceMod(t *testing.T) {
   329  	tcpServer := tcp.Server{
   330  		MsgProcessor: xor,
   331  	}
   332  	dest, err := tcpServer.Start()
   333  	common.Must(err)
   334  	defer tcpServer.Close()
   335  
   336  	authPort := tcp.PickPort()
   337  	noAuthPort := tcp.PickPort()
   338  	serverConfig := &core.Config{
   339  		Inbound: []*core.InboundHandlerConfig{
   340  			{
   341  				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
   342  					PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(authPort)}},
   343  					Listen:   net.NewIPOrDomain(net.LocalHostIP),
   344  				}),
   345  				ProxySettings: serial.ToTypedMessage(&socks.ServerConfig{
   346  					AuthType: socks.AuthType_PASSWORD,
   347  					Accounts: map[string]string{
   348  						"Test Account": "Test Password",
   349  					},
   350  					Address:    net.NewIPOrDomain(net.LocalHostIP),
   351  					UdpEnabled: false,
   352  				}),
   353  			},
   354  			{
   355  				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
   356  					PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(noAuthPort)}},
   357  					Listen:   net.NewIPOrDomain(net.LocalHostIP),
   358  				}),
   359  				ProxySettings: serial.ToTypedMessage(&socks.ServerConfig{
   360  					AuthType: socks.AuthType_NO_AUTH,
   361  					Accounts: map[string]string{
   362  						"Test Account": "Test Password",
   363  					},
   364  					Address:    net.NewIPOrDomain(net.LocalHostIP),
   365  					UdpEnabled: false,
   366  				}),
   367  			},
   368  		},
   369  		Outbound: []*core.OutboundHandlerConfig{
   370  			{
   371  				ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
   372  			},
   373  		},
   374  	}
   375  
   376  	servers, err := InitializeServerConfigs(serverConfig)
   377  	common.Must(err)
   378  	defer CloseAllServers(servers)
   379  
   380  	{
   381  		noAuthDialer, err := xproxy.SOCKS5("tcp", net.TCPDestination(net.LocalHostIP, noAuthPort).NetAddr(), nil, xproxy.Direct)
   382  		common.Must(err)
   383  		conn, err := noAuthDialer.Dial("tcp", dest.NetAddr())
   384  		common.Must(err)
   385  		defer conn.Close()
   386  
   387  		if err := testTCPConn2(conn, 1024, time.Second*5)(); err != nil {
   388  			t.Error(err)
   389  		}
   390  	}
   391  
   392  	{
   393  		authDialer, err := xproxy.SOCKS5("tcp", net.TCPDestination(net.LocalHostIP, authPort).NetAddr(), &xproxy.Auth{User: "Test Account", Password: "Test Password"}, xproxy.Direct)
   394  		common.Must(err)
   395  		conn, err := authDialer.Dial("tcp", dest.NetAddr())
   396  		common.Must(err)
   397  		defer conn.Close()
   398  
   399  		if err := testTCPConn2(conn, 1024, time.Second*5)(); err != nil {
   400  			t.Error(err)
   401  		}
   402  	}
   403  
   404  	{
   405  		dialer := socks4.Dial("socks4://" + net.TCPDestination(net.LocalHostIP, noAuthPort).NetAddr())
   406  		conn, err := dialer("tcp", dest.NetAddr())
   407  		common.Must(err)
   408  		defer conn.Close()
   409  
   410  		if err := testTCPConn2(conn, 1024, time.Second*5)(); err != nil {
   411  			t.Error(err)
   412  		}
   413  	}
   414  
   415  	{
   416  		dialer := socks4.Dial("socks4://" + net.TCPDestination(net.LocalHostIP, noAuthPort).NetAddr())
   417  		conn, err := dialer("tcp", net.TCPDestination(net.LocalHostIP, tcpServer.Port).NetAddr())
   418  		common.Must(err)
   419  		defer conn.Close()
   420  
   421  		if err := testTCPConn2(conn, 1024, time.Second*5)(); err != nil {
   422  			t.Error(err)
   423  		}
   424  	}
   425  }