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 }