github.com/p4gefau1t/trojan-go@v0.10.6/test/scenario/proxy_test.go (about)

     1  package scenario
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"net"
     7  	"net/http"
     8  	_ "net/http/pprof"
     9  	"os"
    10  	"sync"
    11  	"testing"
    12  	"time"
    13  
    14  	netproxy "golang.org/x/net/proxy"
    15  
    16  	_ "github.com/p4gefau1t/trojan-go/api"
    17  	_ "github.com/p4gefau1t/trojan-go/api/service"
    18  	"github.com/p4gefau1t/trojan-go/common"
    19  	_ "github.com/p4gefau1t/trojan-go/log/golog"
    20  	"github.com/p4gefau1t/trojan-go/proxy"
    21  	_ "github.com/p4gefau1t/trojan-go/proxy/client"
    22  	_ "github.com/p4gefau1t/trojan-go/proxy/forward"
    23  	_ "github.com/p4gefau1t/trojan-go/proxy/nat"
    24  	_ "github.com/p4gefau1t/trojan-go/proxy/server"
    25  	_ "github.com/p4gefau1t/trojan-go/statistic/memory"
    26  	"github.com/p4gefau1t/trojan-go/test/util"
    27  )
    28  
    29  // test key and cert
    30  
    31  var cert = `
    32  -----BEGIN CERTIFICATE-----
    33  MIIC5TCCAc2gAwIBAgIJAJqNVe6g/10vMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
    34  BAMMCWxvY2FsaG9zdDAeFw0yMTA5MTQwNjE1MTFaFw0yNjA5MTMwNjE1MTFaMBQx
    35  EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
    36  ggEBAK7bupJ8tmHM3shQ/7N730jzpRsXdNiBxq/Jxx8j+vB3AcxuP5bjXQZqS6YR
    37  5W5vrfLlegtq1E/mmaI3Ht0RfIlzev04Dua9PWmIQJD801nEPknbfgCLXDh+pYr2
    38  sfg8mUh3LjGtrxyH+nmbTjWg7iWSKohmZ8nUDcX94Llo5FxibMAz8OsAwOmUueCH
    39  jP3XswZYHEy+OOP3K0ZEiJy0f5T6ZXk9OWYuPN4VQKJx1qrc9KzZtSPHwqVdkGUi
    40  ase9tOPA4aMutzt0btgW7h7UrvG6C1c/Rr1BxdiYq1EQ+yypnAlyToVQSNbo67zz
    41  wGQk4GeruIkOgJOLdooN/HjhbHMCAwEAAaM6MDgwFAYDVR0RBA0wC4IJbG9jYWxo
    42  b3N0MAsGA1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0B
    43  AQsFAAOCAQEASsBzHHYiWDDiBVWUEwVZAduTrslTLNOxG0QHBKsHWIlz/3QlhQil
    44  ywb3OhfMTUR1dMGY5Iq5432QiCHO4IMCOv7tDIkgb4Bc3v/3CRlBlnurtAmUfNJ6
    45  pTRSlK4AjWpGHAEEd/8aCaOE86hMP8WDht8MkJTRrQqpJ1HeDISoKt9nepHOIsj+
    46  I2zLZZtw0pg7FuR4MzWuqOt071iRS46Pupryb3ZEGIWNz5iLrDQod5Iz2ZGSRGqE
    47  rB8idX0mlj5AHRRanVR3PAes+eApsW9JvYG/ImuCOs+ZsukY614zQZdR+SyFm85G
    48  4NICyeQsmiypNHHgw+xZmGqZg65bXNGoyg==
    49  -----END CERTIFICATE-----
    50  `
    51  
    52  var key = `
    53  -----BEGIN PRIVATE KEY-----
    54  MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCu27qSfLZhzN7I
    55  UP+ze99I86UbF3TYgcavyccfI/rwdwHMbj+W410GakumEeVub63y5XoLatRP5pmi
    56  Nx7dEXyJc3r9OA7mvT1piECQ/NNZxD5J234Ai1w4fqWK9rH4PJlIdy4xra8ch/p5
    57  m041oO4lkiqIZmfJ1A3F/eC5aORcYmzAM/DrAMDplLngh4z917MGWBxMvjjj9ytG
    58  RIictH+U+mV5PTlmLjzeFUCicdaq3PSs2bUjx8KlXZBlImrHvbTjwOGjLrc7dG7Y
    59  Fu4e1K7xugtXP0a9QcXYmKtREPssqZwJck6FUEjW6Ou888BkJOBnq7iJDoCTi3aK
    60  Dfx44WxzAgMBAAECggEBAKYhib/H0ZhWB4yWuHqUxG4RXtrAjHlvw5Acy5zgmHiC
    61  +Sh7ztrTJf0EXN9pvWwRm1ldgXj7hMBtPaaLbD1pccM9/qo66p17Sq/LjlyyeTOe
    62  affOHIbz4Sij2zCOdkR9fr0EztTQScF3yBhl4Aa/4cO8fcCeWxm86WEldq9x4xWJ
    63  s5WMR4CnrOJhDINLNPQPKX92KyxEQ/RfuBWovx3M0nl3fcUWfESY134t5g/UBFId
    64  In19tZ+pGIpCkxP0U1AZWrlZRA8Q/3sO2orUpoAOdCrGk/DcCTMh0c1pMzbYZ1/i
    65  cYXn38MpUo8QeG4FElUhAv6kzeBIl2tRBMVzIigo+AECgYEA3No1rHdFu6Ox9vC8
    66  E93PTZevYVcL5J5yx6x7khCaOLKKuRXpjOX/h3Ll+hlN2DVAg5Jli/JVGCco4GeK
    67  kbFLSyxG1+E63JbgsVpaEOgvFT3bHHSPSRJDnIU+WkcNQ2u4Ky5ahZzbNdV+4fj2
    68  NO2iMgkm7hoJANrm3IqqW8epenMCgYEAyq+qdNj5DiDzBcDvLwY+4/QmMOOgDqeh
    69  /TzhbDRyr+m4xNT7LLS4s/3wcbkQC33zhMUI3YvOHnYq5Ze/iL/TSloj0QCp1I7L
    70  J7sZeM1XimMBQIpCfOC7lf4tU76Fz0DTHAL+CmX1DgmRJdYO09843VsKkscC968R
    71  4cwL5oGxxgECgYAM4TTsH/CTJtLEIfn19qOWVNhHhvoMlSkAeBCkzg8Qa2knrh12
    72  uBsU3SCIW11s1H40rh758GICDJaXr7InGP3ZHnXrNRlnr+zeqvRBtCi6xma23B1X
    73  F5eV0zd1sFsXqXqOGh/xVtp54z+JEinZoForLNl2XVJVGG8KQZP50kUR/QKBgH4O
    74  8zzpFT0sUPlrHVdp0wODfZ06dPmoWJ9flfPuSsYN3tTMgcs0Owv3C+wu5UPAegxB
    75  X1oq8W8Qn21cC8vJQmgj19LNTtLcXI3BV/5B+Aghu02gr+lq/EA1bYuAG0jjUGlD
    76  kyx0bQzl9lhJ4b70PjGtxc2z6KyTPdPpTB143FABAoGAQDoIUdc77/IWcjzcaXeJ
    77  8abak5rAZA7cu2g2NVfs+Km+njsB0pbTwMnV1zGoFABdaHLdqbthLWtX7WOb1PDD
    78  MQ+kbiLw5uj8IY2HEqJhDGGEdXBqxbW7kyuIAN9Mw+mwKzkikNcFQdxgchWH1d1o
    79  lVkr92iEX+IhIeYb4DN1vQw=
    80  -----END PRIVATE KEY-----
    81  `
    82  
    83  func init() {
    84  	os.WriteFile("server.crt", []byte(cert), 0o777)
    85  	os.WriteFile("server.key", []byte(key), 0o777)
    86  }
    87  
    88  func CheckClientServer(clientData, serverData string, socksPort int) (ok bool) {
    89  	server, err := proxy.NewProxyFromConfigData([]byte(serverData), false)
    90  	common.Must(err)
    91  	go server.Run()
    92  
    93  	client, err := proxy.NewProxyFromConfigData([]byte(clientData), false)
    94  	common.Must(err)
    95  	go client.Run()
    96  
    97  	time.Sleep(time.Second * 2)
    98  	dialer, err := netproxy.SOCKS5("tcp", fmt.Sprintf("127.0.0.1:%d", socksPort), nil, netproxy.Direct)
    99  	common.Must(err)
   100  
   101  	ok = true
   102  	const num = 100
   103  	wg := sync.WaitGroup{}
   104  	wg.Add(num)
   105  	for i := 0; i < num; i++ {
   106  		go func() {
   107  			const payloadSize = 1024
   108  			payload := util.GeneratePayload(payloadSize)
   109  			buf := [payloadSize]byte{}
   110  
   111  			conn, err := dialer.Dial("tcp", util.EchoAddr)
   112  			common.Must(err)
   113  
   114  			common.Must2(conn.Write(payload))
   115  			common.Must2(conn.Read(buf[:]))
   116  
   117  			if !bytes.Equal(payload, buf[:]) {
   118  				ok = false
   119  			}
   120  			conn.Close()
   121  			wg.Done()
   122  		}()
   123  	}
   124  	wg.Wait()
   125  	client.Close()
   126  	server.Close()
   127  	return
   128  }
   129  
   130  func TestClientServerWebsocketSubTree(t *testing.T) {
   131  	serverPort := common.PickPort("tcp", "127.0.0.1")
   132  	socksPort := common.PickPort("tcp", "127.0.0.1")
   133  	clientData := fmt.Sprintf(`
   134  run-type: client
   135  local-addr: 127.0.0.1
   136  local-port: %d
   137  remote-addr: 127.0.0.1
   138  remote-port: %d
   139  password:
   140      - password
   141  ssl:
   142      verify: false
   143      fingerprint: firefox
   144      sni: localhost
   145  websocket:
   146      enabled: true
   147      path: /ws
   148      host: somedomainname.com
   149  shadowsocks:
   150      enabled: true
   151      method: AEAD_CHACHA20_POLY1305
   152      password: 12345678
   153  mux:
   154      enabled: true
   155  `, socksPort, serverPort)
   156  	serverData := fmt.Sprintf(`
   157  run-type: server
   158  local-addr: 127.0.0.1
   159  local-port: %d
   160  remote-addr: 127.0.0.1
   161  remote-port: %s
   162  disable-http-check: true
   163  password:
   164      - password
   165  ssl:
   166      verify-hostname: false
   167      key: server.key
   168      cert: server.crt
   169      sni: localhost
   170  shadowsocks:
   171      enabled: true
   172      method: AEAD_CHACHA20_POLY1305
   173      password: 12345678
   174  websocket:
   175      enabled: true
   176      path: /ws
   177      host: 127.0.0.1
   178  `, serverPort, util.HTTPPort)
   179  
   180  	if !CheckClientServer(clientData, serverData, socksPort) {
   181  		t.Fail()
   182  	}
   183  }
   184  
   185  func TestClientServerTrojanSubTree(t *testing.T) {
   186  	serverPort := common.PickPort("tcp", "127.0.0.1")
   187  	socksPort := common.PickPort("tcp", "127.0.0.1")
   188  	clientData := fmt.Sprintf(`
   189  run-type: client
   190  local-addr: 127.0.0.1
   191  local-port: %d
   192  remote-addr: 127.0.0.1
   193  remote-port: %d
   194  password:
   195      - password
   196  ssl:
   197      verify: false
   198      fingerprint: firefox
   199      sni: localhost
   200  shadowsocks:
   201      enabled: true
   202      method: AEAD_CHACHA20_POLY1305
   203      password: 12345678
   204  mux:
   205      enabled: true
   206  `, socksPort, serverPort)
   207  	serverData := fmt.Sprintf(`
   208  run-type: server
   209  local-addr: 127.0.0.1
   210  local-port: %d
   211  remote-addr: 127.0.0.1
   212  remote-port: %s
   213  disable-http-check: true
   214  password:
   215      - password
   216  ssl:
   217      verify-hostname: false
   218      key: server.key
   219      cert: server.crt
   220      sni: localhost
   221  shadowsocks:
   222      enabled: true
   223      method: AEAD_CHACHA20_POLY1305
   224      password: 12345678
   225  `, serverPort, util.HTTPPort)
   226  
   227  	if !CheckClientServer(clientData, serverData, socksPort) {
   228  		t.Fail()
   229  	}
   230  }
   231  
   232  func TestWebsocketDetection(t *testing.T) {
   233  	serverPort := common.PickPort("tcp", "127.0.0.1")
   234  	socksPort := common.PickPort("tcp", "127.0.0.1")
   235  
   236  	clientData := fmt.Sprintf(`
   237  run-type: client
   238  local-addr: 127.0.0.1
   239  local-port: %d
   240  remote-addr: 127.0.0.1
   241  remote-port: %d
   242  password:
   243      - password
   244  ssl:
   245      verify: false
   246      fingerprint: firefox
   247      sni: localhost
   248  shadowsocks:
   249      enabled: true
   250      method: AEAD_CHACHA20_POLY1305
   251      password: 12345678
   252  mux:
   253      enabled: true
   254  `, socksPort, serverPort)
   255  	serverData := fmt.Sprintf(`
   256  run-type: server
   257  local-addr: 127.0.0.1
   258  local-port: %d
   259  remote-addr: 127.0.0.1
   260  remote-port: %s
   261  disable-http-check: true
   262  password:
   263      - password
   264  ssl:
   265      verify-hostname: false
   266      key: server.key
   267      cert: server.crt
   268      sni: localhost
   269  shadowsocks:
   270      enabled: true
   271      method: AEAD_CHACHA20_POLY1305
   272      password: 12345678
   273  websocket:
   274      enabled: true
   275      path: /ws
   276      hostname: 127.0.0.1
   277  `, serverPort, util.HTTPPort)
   278  
   279  	if !CheckClientServer(clientData, serverData, socksPort) {
   280  		t.Fail()
   281  	}
   282  }
   283  
   284  func TestPluginWebsocket(t *testing.T) {
   285  	serverPort := common.PickPort("tcp", "127.0.0.1")
   286  	socksPort := common.PickPort("tcp", "127.0.0.1")
   287  
   288  	clientData := fmt.Sprintf(`
   289  run-type: client
   290  local-addr: 127.0.0.1
   291  local-port: %d
   292  remote-addr: 127.0.0.1
   293  remote-port: %d
   294  password:
   295      - password
   296  transport-plugin:
   297      enabled: true
   298      type: plaintext
   299  shadowsocks:
   300      enabled: true
   301      method: AEAD_CHACHA20_POLY1305
   302      password: 12345678
   303  mux:
   304      enabled: true
   305  websocket:
   306      enabled: true
   307      path: /ws
   308      hostname: 127.0.0.1
   309  `, socksPort, serverPort)
   310  	serverData := fmt.Sprintf(`
   311  run-type: server
   312  local-addr: 127.0.0.1
   313  local-port: %d
   314  remote-addr: 127.0.0.1
   315  remote-port: %s
   316  disable-http-check: true
   317  password:
   318      - password
   319  transport-plugin:
   320      enabled: true
   321      type: plaintext
   322  shadowsocks:
   323      enabled: true
   324      method: AEAD_CHACHA20_POLY1305
   325      password: 12345678
   326  websocket:
   327      enabled: true
   328      path: /ws
   329      hostname: 127.0.0.1
   330  `, serverPort, util.HTTPPort)
   331  
   332  	if !CheckClientServer(clientData, serverData, socksPort) {
   333  		t.Fail()
   334  	}
   335  }
   336  
   337  func TestForward(t *testing.T) {
   338  	serverPort := common.PickPort("tcp", "127.0.0.1")
   339  	clientPort := common.PickPort("tcp", "127.0.0.1")
   340  	_, targetPort, _ := net.SplitHostPort(util.EchoAddr)
   341  	clientData := fmt.Sprintf(`
   342  run-type: forward
   343  local-addr: 127.0.0.1
   344  local-port: %d
   345  remote-addr: 127.0.0.1
   346  remote-port: %d
   347  target-addr: 127.0.0.1
   348  target-port: %s
   349  password:
   350      - password
   351  ssl:
   352      verify: false
   353      fingerprint: firefox
   354      sni: localhost
   355  websocket:
   356      enabled: true
   357      path: /ws
   358      hostname: 127.0.0.1
   359  shadowsocks:
   360      enabled: true
   361      method: AEAD_CHACHA20_POLY1305
   362      password: 12345678
   363  mux:
   364      enabled: true
   365  `, clientPort, serverPort, targetPort)
   366  	go func() {
   367  		proxy, err := proxy.NewProxyFromConfigData([]byte(clientData), false)
   368  		common.Must(err)
   369  		common.Must(proxy.Run())
   370  	}()
   371  
   372  	serverData := fmt.Sprintf(`
   373  run-type: server
   374  local-addr: 127.0.0.1
   375  local-port: %d
   376  remote-addr: 127.0.0.1
   377  remote-port: %s
   378  disable-http-check: true
   379  password:
   380      - password
   381  ssl:
   382      verify-hostname: false
   383      key: server.key
   384      cert: server.crt
   385      sni: "localhost"
   386  websocket:
   387      enabled: true
   388      path: /ws
   389      hostname: 127.0.0.1
   390  shadowsocks:
   391      enabled: true
   392      method: AEAD_CHACHA20_POLY1305
   393      password: 12345678
   394  `, serverPort, util.HTTPPort)
   395  	go func() {
   396  		proxy, err := proxy.NewProxyFromConfigData([]byte(serverData), false)
   397  		common.Must(err)
   398  		common.Must(proxy.Run())
   399  	}()
   400  
   401  	time.Sleep(time.Second * 2)
   402  
   403  	payload := util.GeneratePayload(1024)
   404  	buf := [1024]byte{}
   405  
   406  	conn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", clientPort))
   407  	common.Must(err)
   408  
   409  	common.Must2(conn.Write(payload))
   410  	common.Must2(conn.Read(buf[:]))
   411  
   412  	if !bytes.Equal(payload, buf[:]) {
   413  		t.Fail()
   414  	}
   415  
   416  	packet, err := net.ListenPacket("udp", "")
   417  	common.Must(err)
   418  	common.Must2(packet.WriteTo(payload, &net.UDPAddr{
   419  		IP:   net.ParseIP("127.0.0.1"),
   420  		Port: clientPort,
   421  	}))
   422  	_, _, err = packet.ReadFrom(buf[:])
   423  	common.Must(err)
   424  	if !bytes.Equal(payload, buf[:]) {
   425  		t.Fail()
   426  	}
   427  }
   428  
   429  func TestLeak(t *testing.T) {
   430  	serverPort := common.PickPort("tcp", "127.0.0.1")
   431  	socksPort := common.PickPort("tcp", "127.0.0.1")
   432  	clientData := fmt.Sprintf(`
   433  run-type: client
   434  local-addr: 127.0.0.1
   435  local-port: %d
   436  remote-addr: 127.0.0.1
   437  remote-port: %d
   438  log-level: 0
   439  password:
   440      - password
   441  ssl:
   442      verify: false
   443      fingerprint: firefox
   444      sni: localhost
   445  shadowsocks:
   446      enabled: true
   447      method: AEAD_CHACHA20_POLY1305
   448      password: 12345678
   449  mux:
   450      enabled: true
   451  api:
   452      enabled: true
   453      api-port: 0
   454  `, socksPort, serverPort)
   455  	client, err := proxy.NewProxyFromConfigData([]byte(clientData), false)
   456  	common.Must(err)
   457  	go client.Run()
   458  	time.Sleep(time.Second * 3)
   459  	client.Close()
   460  	time.Sleep(time.Second * 3)
   461  	// http.ListenAndServe("localhost:6060", nil)
   462  }
   463  
   464  func SingleThreadBenchmark(clientData, serverData string, socksPort int) {
   465  	server, err := proxy.NewProxyFromConfigData([]byte(clientData), false)
   466  	common.Must(err)
   467  	go server.Run()
   468  
   469  	client, err := proxy.NewProxyFromConfigData([]byte(serverData), false)
   470  	common.Must(err)
   471  	go client.Run()
   472  
   473  	time.Sleep(time.Second * 2)
   474  	dialer, err := netproxy.SOCKS5("tcp", fmt.Sprintf("127.0.0.1:%d", socksPort), nil, netproxy.Direct)
   475  	common.Must(err)
   476  
   477  	const num = 100
   478  	wg := sync.WaitGroup{}
   479  	wg.Add(num)
   480  	const payloadSize = 1024 * 1024 * 1024
   481  	payload := util.GeneratePayload(payloadSize)
   482  
   483  	for i := 0; i < 100; i++ {
   484  		conn, err := dialer.Dial("tcp", util.BlackHoleAddr)
   485  		common.Must(err)
   486  
   487  		t1 := time.Now()
   488  		common.Must2(conn.Write(payload))
   489  		t2 := time.Now()
   490  
   491  		speed := float64(payloadSize) / (float64(t2.Sub(t1).Nanoseconds()) / float64(time.Second))
   492  		fmt.Printf("speed: %f Gbps\n", speed/1024/1024/1024)
   493  
   494  		conn.Close()
   495  	}
   496  	client.Close()
   497  	server.Close()
   498  }
   499  
   500  func BenchmarkClientServer(b *testing.B) {
   501  	go func() {
   502  		fmt.Println(http.ListenAndServe("localhost:6060", nil))
   503  	}()
   504  	serverPort := common.PickPort("tcp", "127.0.0.1")
   505  	socksPort := common.PickPort("tcp", "127.0.0.1")
   506  	clientData := fmt.Sprintf(`
   507  run-type: client
   508  local-addr: 127.0.0.1
   509  local-port: %d
   510  remote-addr: 127.0.0.1
   511  remote-port: %d
   512  log-level: 0
   513  password:
   514      - password
   515  ssl:
   516      verify: false
   517      fingerprint: firefox
   518      sni: localhost
   519  `, socksPort, serverPort)
   520  	serverData := fmt.Sprintf(`
   521  run-type: server
   522  local-addr: 127.0.0.1
   523  local-port: %d
   524  remote-addr: 127.0.0.1
   525  remote-port: %s
   526  log-level: 0
   527  disable-http-check: true
   528  password:
   529      - password
   530  ssl:
   531      verify-hostname: false
   532      key: server.key
   533      cert: server.crt
   534      sni: localhost
   535  `, serverPort, util.HTTPPort)
   536  
   537  	SingleThreadBenchmark(clientData, serverData, socksPort)
   538  }