mirror of
https://github.com/p4gefau1t/trojan-go.git
synced 2024-04-21 12:21:34 +00:00
539 lines
13 KiB
Go
539 lines
13 KiB
Go
package scenario
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
_ "net/http/pprof"
|
|
"os"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
netproxy "golang.org/x/net/proxy"
|
|
|
|
_ "github.com/p4gefau1t/trojan-go/api"
|
|
_ "github.com/p4gefau1t/trojan-go/api/service"
|
|
"github.com/p4gefau1t/trojan-go/common"
|
|
_ "github.com/p4gefau1t/trojan-go/log/golog"
|
|
"github.com/p4gefau1t/trojan-go/proxy"
|
|
_ "github.com/p4gefau1t/trojan-go/proxy/client"
|
|
_ "github.com/p4gefau1t/trojan-go/proxy/forward"
|
|
_ "github.com/p4gefau1t/trojan-go/proxy/nat"
|
|
_ "github.com/p4gefau1t/trojan-go/proxy/server"
|
|
_ "github.com/p4gefau1t/trojan-go/statistic/memory"
|
|
"github.com/p4gefau1t/trojan-go/test/util"
|
|
)
|
|
|
|
// test key and cert
|
|
|
|
var cert = `
|
|
-----BEGIN CERTIFICATE-----
|
|
MIIC5TCCAc2gAwIBAgIJAJqNVe6g/10vMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
|
|
BAMMCWxvY2FsaG9zdDAeFw0yMTA5MTQwNjE1MTFaFw0yNjA5MTMwNjE1MTFaMBQx
|
|
EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
|
|
ggEBAK7bupJ8tmHM3shQ/7N730jzpRsXdNiBxq/Jxx8j+vB3AcxuP5bjXQZqS6YR
|
|
5W5vrfLlegtq1E/mmaI3Ht0RfIlzev04Dua9PWmIQJD801nEPknbfgCLXDh+pYr2
|
|
sfg8mUh3LjGtrxyH+nmbTjWg7iWSKohmZ8nUDcX94Llo5FxibMAz8OsAwOmUueCH
|
|
jP3XswZYHEy+OOP3K0ZEiJy0f5T6ZXk9OWYuPN4VQKJx1qrc9KzZtSPHwqVdkGUi
|
|
ase9tOPA4aMutzt0btgW7h7UrvG6C1c/Rr1BxdiYq1EQ+yypnAlyToVQSNbo67zz
|
|
wGQk4GeruIkOgJOLdooN/HjhbHMCAwEAAaM6MDgwFAYDVR0RBA0wC4IJbG9jYWxo
|
|
b3N0MAsGA1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0B
|
|
AQsFAAOCAQEASsBzHHYiWDDiBVWUEwVZAduTrslTLNOxG0QHBKsHWIlz/3QlhQil
|
|
ywb3OhfMTUR1dMGY5Iq5432QiCHO4IMCOv7tDIkgb4Bc3v/3CRlBlnurtAmUfNJ6
|
|
pTRSlK4AjWpGHAEEd/8aCaOE86hMP8WDht8MkJTRrQqpJ1HeDISoKt9nepHOIsj+
|
|
I2zLZZtw0pg7FuR4MzWuqOt071iRS46Pupryb3ZEGIWNz5iLrDQod5Iz2ZGSRGqE
|
|
rB8idX0mlj5AHRRanVR3PAes+eApsW9JvYG/ImuCOs+ZsukY614zQZdR+SyFm85G
|
|
4NICyeQsmiypNHHgw+xZmGqZg65bXNGoyg==
|
|
-----END CERTIFICATE-----
|
|
`
|
|
|
|
var key = `
|
|
-----BEGIN PRIVATE KEY-----
|
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCu27qSfLZhzN7I
|
|
UP+ze99I86UbF3TYgcavyccfI/rwdwHMbj+W410GakumEeVub63y5XoLatRP5pmi
|
|
Nx7dEXyJc3r9OA7mvT1piECQ/NNZxD5J234Ai1w4fqWK9rH4PJlIdy4xra8ch/p5
|
|
m041oO4lkiqIZmfJ1A3F/eC5aORcYmzAM/DrAMDplLngh4z917MGWBxMvjjj9ytG
|
|
RIictH+U+mV5PTlmLjzeFUCicdaq3PSs2bUjx8KlXZBlImrHvbTjwOGjLrc7dG7Y
|
|
Fu4e1K7xugtXP0a9QcXYmKtREPssqZwJck6FUEjW6Ou888BkJOBnq7iJDoCTi3aK
|
|
Dfx44WxzAgMBAAECggEBAKYhib/H0ZhWB4yWuHqUxG4RXtrAjHlvw5Acy5zgmHiC
|
|
+Sh7ztrTJf0EXN9pvWwRm1ldgXj7hMBtPaaLbD1pccM9/qo66p17Sq/LjlyyeTOe
|
|
affOHIbz4Sij2zCOdkR9fr0EztTQScF3yBhl4Aa/4cO8fcCeWxm86WEldq9x4xWJ
|
|
s5WMR4CnrOJhDINLNPQPKX92KyxEQ/RfuBWovx3M0nl3fcUWfESY134t5g/UBFId
|
|
In19tZ+pGIpCkxP0U1AZWrlZRA8Q/3sO2orUpoAOdCrGk/DcCTMh0c1pMzbYZ1/i
|
|
cYXn38MpUo8QeG4FElUhAv6kzeBIl2tRBMVzIigo+AECgYEA3No1rHdFu6Ox9vC8
|
|
E93PTZevYVcL5J5yx6x7khCaOLKKuRXpjOX/h3Ll+hlN2DVAg5Jli/JVGCco4GeK
|
|
kbFLSyxG1+E63JbgsVpaEOgvFT3bHHSPSRJDnIU+WkcNQ2u4Ky5ahZzbNdV+4fj2
|
|
NO2iMgkm7hoJANrm3IqqW8epenMCgYEAyq+qdNj5DiDzBcDvLwY+4/QmMOOgDqeh
|
|
/TzhbDRyr+m4xNT7LLS4s/3wcbkQC33zhMUI3YvOHnYq5Ze/iL/TSloj0QCp1I7L
|
|
J7sZeM1XimMBQIpCfOC7lf4tU76Fz0DTHAL+CmX1DgmRJdYO09843VsKkscC968R
|
|
4cwL5oGxxgECgYAM4TTsH/CTJtLEIfn19qOWVNhHhvoMlSkAeBCkzg8Qa2knrh12
|
|
uBsU3SCIW11s1H40rh758GICDJaXr7InGP3ZHnXrNRlnr+zeqvRBtCi6xma23B1X
|
|
F5eV0zd1sFsXqXqOGh/xVtp54z+JEinZoForLNl2XVJVGG8KQZP50kUR/QKBgH4O
|
|
8zzpFT0sUPlrHVdp0wODfZ06dPmoWJ9flfPuSsYN3tTMgcs0Owv3C+wu5UPAegxB
|
|
X1oq8W8Qn21cC8vJQmgj19LNTtLcXI3BV/5B+Aghu02gr+lq/EA1bYuAG0jjUGlD
|
|
kyx0bQzl9lhJ4b70PjGtxc2z6KyTPdPpTB143FABAoGAQDoIUdc77/IWcjzcaXeJ
|
|
8abak5rAZA7cu2g2NVfs+Km+njsB0pbTwMnV1zGoFABdaHLdqbthLWtX7WOb1PDD
|
|
MQ+kbiLw5uj8IY2HEqJhDGGEdXBqxbW7kyuIAN9Mw+mwKzkikNcFQdxgchWH1d1o
|
|
lVkr92iEX+IhIeYb4DN1vQw=
|
|
-----END PRIVATE KEY-----
|
|
`
|
|
|
|
func init() {
|
|
os.WriteFile("server.crt", []byte(cert), 0o777)
|
|
os.WriteFile("server.key", []byte(key), 0o777)
|
|
}
|
|
|
|
func CheckClientServer(clientData, serverData string, socksPort int) (ok bool) {
|
|
server, err := proxy.NewProxyFromConfigData([]byte(serverData), false)
|
|
common.Must(err)
|
|
go server.Run()
|
|
|
|
client, err := proxy.NewProxyFromConfigData([]byte(clientData), false)
|
|
common.Must(err)
|
|
go client.Run()
|
|
|
|
time.Sleep(time.Second * 2)
|
|
dialer, err := netproxy.SOCKS5("tcp", fmt.Sprintf("127.0.0.1:%d", socksPort), nil, netproxy.Direct)
|
|
common.Must(err)
|
|
|
|
ok = true
|
|
const num = 100
|
|
wg := sync.WaitGroup{}
|
|
wg.Add(num)
|
|
for i := 0; i < num; i++ {
|
|
go func() {
|
|
const payloadSize = 1024
|
|
payload := util.GeneratePayload(payloadSize)
|
|
buf := [payloadSize]byte{}
|
|
|
|
conn, err := dialer.Dial("tcp", util.EchoAddr)
|
|
common.Must(err)
|
|
|
|
common.Must2(conn.Write(payload))
|
|
common.Must2(conn.Read(buf[:]))
|
|
|
|
if !bytes.Equal(payload, buf[:]) {
|
|
ok = false
|
|
}
|
|
conn.Close()
|
|
wg.Done()
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
client.Close()
|
|
server.Close()
|
|
return
|
|
}
|
|
|
|
func TestClientServerWebsocketSubTree(t *testing.T) {
|
|
serverPort := common.PickPort("tcp", "127.0.0.1")
|
|
socksPort := common.PickPort("tcp", "127.0.0.1")
|
|
clientData := fmt.Sprintf(`
|
|
run-type: client
|
|
local-addr: 127.0.0.1
|
|
local-port: %d
|
|
remote-addr: 127.0.0.1
|
|
remote-port: %d
|
|
password:
|
|
- password
|
|
ssl:
|
|
verify: false
|
|
fingerprint: firefox
|
|
sni: localhost
|
|
websocket:
|
|
enabled: true
|
|
path: /ws
|
|
host: somedomainname.com
|
|
shadowsocks:
|
|
enabled: true
|
|
method: AEAD_CHACHA20_POLY1305
|
|
password: 12345678
|
|
mux:
|
|
enabled: true
|
|
`, socksPort, serverPort)
|
|
serverData := fmt.Sprintf(`
|
|
run-type: server
|
|
local-addr: 127.0.0.1
|
|
local-port: %d
|
|
remote-addr: 127.0.0.1
|
|
remote-port: %s
|
|
disable-http-check: true
|
|
password:
|
|
- password
|
|
ssl:
|
|
verify-hostname: false
|
|
key: server.key
|
|
cert: server.crt
|
|
sni: localhost
|
|
shadowsocks:
|
|
enabled: true
|
|
method: AEAD_CHACHA20_POLY1305
|
|
password: 12345678
|
|
websocket:
|
|
enabled: true
|
|
path: /ws
|
|
host: 127.0.0.1
|
|
`, serverPort, util.HTTPPort)
|
|
|
|
if !CheckClientServer(clientData, serverData, socksPort) {
|
|
t.Fail()
|
|
}
|
|
}
|
|
|
|
func TestClientServerTrojanSubTree(t *testing.T) {
|
|
serverPort := common.PickPort("tcp", "127.0.0.1")
|
|
socksPort := common.PickPort("tcp", "127.0.0.1")
|
|
clientData := fmt.Sprintf(`
|
|
run-type: client
|
|
local-addr: 127.0.0.1
|
|
local-port: %d
|
|
remote-addr: 127.0.0.1
|
|
remote-port: %d
|
|
password:
|
|
- password
|
|
ssl:
|
|
verify: false
|
|
fingerprint: firefox
|
|
sni: localhost
|
|
shadowsocks:
|
|
enabled: true
|
|
method: AEAD_CHACHA20_POLY1305
|
|
password: 12345678
|
|
mux:
|
|
enabled: true
|
|
`, socksPort, serverPort)
|
|
serverData := fmt.Sprintf(`
|
|
run-type: server
|
|
local-addr: 127.0.0.1
|
|
local-port: %d
|
|
remote-addr: 127.0.0.1
|
|
remote-port: %s
|
|
disable-http-check: true
|
|
password:
|
|
- password
|
|
ssl:
|
|
verify-hostname: false
|
|
key: server.key
|
|
cert: server.crt
|
|
sni: localhost
|
|
shadowsocks:
|
|
enabled: true
|
|
method: AEAD_CHACHA20_POLY1305
|
|
password: 12345678
|
|
`, serverPort, util.HTTPPort)
|
|
|
|
if !CheckClientServer(clientData, serverData, socksPort) {
|
|
t.Fail()
|
|
}
|
|
}
|
|
|
|
func TestWebsocketDetection(t *testing.T) {
|
|
serverPort := common.PickPort("tcp", "127.0.0.1")
|
|
socksPort := common.PickPort("tcp", "127.0.0.1")
|
|
|
|
clientData := fmt.Sprintf(`
|
|
run-type: client
|
|
local-addr: 127.0.0.1
|
|
local-port: %d
|
|
remote-addr: 127.0.0.1
|
|
remote-port: %d
|
|
password:
|
|
- password
|
|
ssl:
|
|
verify: false
|
|
fingerprint: firefox
|
|
sni: localhost
|
|
shadowsocks:
|
|
enabled: true
|
|
method: AEAD_CHACHA20_POLY1305
|
|
password: 12345678
|
|
mux:
|
|
enabled: true
|
|
`, socksPort, serverPort)
|
|
serverData := fmt.Sprintf(`
|
|
run-type: server
|
|
local-addr: 127.0.0.1
|
|
local-port: %d
|
|
remote-addr: 127.0.0.1
|
|
remote-port: %s
|
|
disable-http-check: true
|
|
password:
|
|
- password
|
|
ssl:
|
|
verify-hostname: false
|
|
key: server.key
|
|
cert: server.crt
|
|
sni: localhost
|
|
shadowsocks:
|
|
enabled: true
|
|
method: AEAD_CHACHA20_POLY1305
|
|
password: 12345678
|
|
websocket:
|
|
enabled: true
|
|
path: /ws
|
|
hostname: 127.0.0.1
|
|
`, serverPort, util.HTTPPort)
|
|
|
|
if !CheckClientServer(clientData, serverData, socksPort) {
|
|
t.Fail()
|
|
}
|
|
}
|
|
|
|
func TestPluginWebsocket(t *testing.T) {
|
|
serverPort := common.PickPort("tcp", "127.0.0.1")
|
|
socksPort := common.PickPort("tcp", "127.0.0.1")
|
|
|
|
clientData := fmt.Sprintf(`
|
|
run-type: client
|
|
local-addr: 127.0.0.1
|
|
local-port: %d
|
|
remote-addr: 127.0.0.1
|
|
remote-port: %d
|
|
password:
|
|
- password
|
|
transport-plugin:
|
|
enabled: true
|
|
type: plaintext
|
|
shadowsocks:
|
|
enabled: true
|
|
method: AEAD_CHACHA20_POLY1305
|
|
password: 12345678
|
|
mux:
|
|
enabled: true
|
|
websocket:
|
|
enabled: true
|
|
path: /ws
|
|
hostname: 127.0.0.1
|
|
`, socksPort, serverPort)
|
|
serverData := fmt.Sprintf(`
|
|
run-type: server
|
|
local-addr: 127.0.0.1
|
|
local-port: %d
|
|
remote-addr: 127.0.0.1
|
|
remote-port: %s
|
|
disable-http-check: true
|
|
password:
|
|
- password
|
|
transport-plugin:
|
|
enabled: true
|
|
type: plaintext
|
|
shadowsocks:
|
|
enabled: true
|
|
method: AEAD_CHACHA20_POLY1305
|
|
password: 12345678
|
|
websocket:
|
|
enabled: true
|
|
path: /ws
|
|
hostname: 127.0.0.1
|
|
`, serverPort, util.HTTPPort)
|
|
|
|
if !CheckClientServer(clientData, serverData, socksPort) {
|
|
t.Fail()
|
|
}
|
|
}
|
|
|
|
func TestForward(t *testing.T) {
|
|
serverPort := common.PickPort("tcp", "127.0.0.1")
|
|
clientPort := common.PickPort("tcp", "127.0.0.1")
|
|
_, targetPort, _ := net.SplitHostPort(util.EchoAddr)
|
|
clientData := fmt.Sprintf(`
|
|
run-type: forward
|
|
local-addr: 127.0.0.1
|
|
local-port: %d
|
|
remote-addr: 127.0.0.1
|
|
remote-port: %d
|
|
target-addr: 127.0.0.1
|
|
target-port: %s
|
|
password:
|
|
- password
|
|
ssl:
|
|
verify: false
|
|
fingerprint: firefox
|
|
sni: localhost
|
|
websocket:
|
|
enabled: true
|
|
path: /ws
|
|
hostname: 127.0.0.1
|
|
shadowsocks:
|
|
enabled: true
|
|
method: AEAD_CHACHA20_POLY1305
|
|
password: 12345678
|
|
mux:
|
|
enabled: true
|
|
`, clientPort, serverPort, targetPort)
|
|
go func() {
|
|
proxy, err := proxy.NewProxyFromConfigData([]byte(clientData), false)
|
|
common.Must(err)
|
|
common.Must(proxy.Run())
|
|
}()
|
|
|
|
serverData := fmt.Sprintf(`
|
|
run-type: server
|
|
local-addr: 127.0.0.1
|
|
local-port: %d
|
|
remote-addr: 127.0.0.1
|
|
remote-port: %s
|
|
disable-http-check: true
|
|
password:
|
|
- password
|
|
ssl:
|
|
verify-hostname: false
|
|
key: server.key
|
|
cert: server.crt
|
|
sni: "localhost"
|
|
websocket:
|
|
enabled: true
|
|
path: /ws
|
|
hostname: 127.0.0.1
|
|
shadowsocks:
|
|
enabled: true
|
|
method: AEAD_CHACHA20_POLY1305
|
|
password: 12345678
|
|
`, serverPort, util.HTTPPort)
|
|
go func() {
|
|
proxy, err := proxy.NewProxyFromConfigData([]byte(serverData), false)
|
|
common.Must(err)
|
|
common.Must(proxy.Run())
|
|
}()
|
|
|
|
time.Sleep(time.Second * 2)
|
|
|
|
payload := util.GeneratePayload(1024)
|
|
buf := [1024]byte{}
|
|
|
|
conn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", clientPort))
|
|
common.Must(err)
|
|
|
|
common.Must2(conn.Write(payload))
|
|
common.Must2(conn.Read(buf[:]))
|
|
|
|
if !bytes.Equal(payload, buf[:]) {
|
|
t.Fail()
|
|
}
|
|
|
|
packet, err := net.ListenPacket("udp", "")
|
|
common.Must(err)
|
|
common.Must2(packet.WriteTo(payload, &net.UDPAddr{
|
|
IP: net.ParseIP("127.0.0.1"),
|
|
Port: clientPort,
|
|
}))
|
|
_, _, err = packet.ReadFrom(buf[:])
|
|
common.Must(err)
|
|
if !bytes.Equal(payload, buf[:]) {
|
|
t.Fail()
|
|
}
|
|
}
|
|
|
|
func TestLeak(t *testing.T) {
|
|
serverPort := common.PickPort("tcp", "127.0.0.1")
|
|
socksPort := common.PickPort("tcp", "127.0.0.1")
|
|
clientData := fmt.Sprintf(`
|
|
run-type: client
|
|
local-addr: 127.0.0.1
|
|
local-port: %d
|
|
remote-addr: 127.0.0.1
|
|
remote-port: %d
|
|
log-level: 0
|
|
password:
|
|
- password
|
|
ssl:
|
|
verify: false
|
|
fingerprint: firefox
|
|
sni: localhost
|
|
shadowsocks:
|
|
enabled: true
|
|
method: AEAD_CHACHA20_POLY1305
|
|
password: 12345678
|
|
mux:
|
|
enabled: true
|
|
api:
|
|
enabled: true
|
|
api-port: 0
|
|
`, socksPort, serverPort)
|
|
client, err := proxy.NewProxyFromConfigData([]byte(clientData), false)
|
|
common.Must(err)
|
|
go client.Run()
|
|
time.Sleep(time.Second * 3)
|
|
client.Close()
|
|
time.Sleep(time.Second * 3)
|
|
// http.ListenAndServe("localhost:6060", nil)
|
|
}
|
|
|
|
func SingleThreadBenchmark(clientData, serverData string, socksPort int) {
|
|
server, err := proxy.NewProxyFromConfigData([]byte(clientData), false)
|
|
common.Must(err)
|
|
go server.Run()
|
|
|
|
client, err := proxy.NewProxyFromConfigData([]byte(serverData), false)
|
|
common.Must(err)
|
|
go client.Run()
|
|
|
|
time.Sleep(time.Second * 2)
|
|
dialer, err := netproxy.SOCKS5("tcp", fmt.Sprintf("127.0.0.1:%d", socksPort), nil, netproxy.Direct)
|
|
common.Must(err)
|
|
|
|
const num = 100
|
|
wg := sync.WaitGroup{}
|
|
wg.Add(num)
|
|
const payloadSize = 1024 * 1024 * 1024
|
|
payload := util.GeneratePayload(payloadSize)
|
|
|
|
for i := 0; i < 100; i++ {
|
|
conn, err := dialer.Dial("tcp", util.BlackHoleAddr)
|
|
common.Must(err)
|
|
|
|
t1 := time.Now()
|
|
common.Must2(conn.Write(payload))
|
|
t2 := time.Now()
|
|
|
|
speed := float64(payloadSize) / (float64(t2.Sub(t1).Nanoseconds()) / float64(time.Second))
|
|
fmt.Printf("speed: %f Gbps\n", speed/1024/1024/1024)
|
|
|
|
conn.Close()
|
|
}
|
|
client.Close()
|
|
server.Close()
|
|
}
|
|
|
|
func BenchmarkClientServer(b *testing.B) {
|
|
go func() {
|
|
fmt.Println(http.ListenAndServe("localhost:6060", nil))
|
|
}()
|
|
serverPort := common.PickPort("tcp", "127.0.0.1")
|
|
socksPort := common.PickPort("tcp", "127.0.0.1")
|
|
clientData := fmt.Sprintf(`
|
|
run-type: client
|
|
local-addr: 127.0.0.1
|
|
local-port: %d
|
|
remote-addr: 127.0.0.1
|
|
remote-port: %d
|
|
log-level: 0
|
|
password:
|
|
- password
|
|
ssl:
|
|
verify: false
|
|
fingerprint: firefox
|
|
sni: localhost
|
|
`, socksPort, serverPort)
|
|
serverData := fmt.Sprintf(`
|
|
run-type: server
|
|
local-addr: 127.0.0.1
|
|
local-port: %d
|
|
remote-addr: 127.0.0.1
|
|
remote-port: %s
|
|
log-level: 0
|
|
disable-http-check: true
|
|
password:
|
|
- password
|
|
ssl:
|
|
verify-hostname: false
|
|
key: server.key
|
|
cert: server.crt
|
|
sni: localhost
|
|
`, serverPort, util.HTTPPort)
|
|
|
|
SingleThreadBenchmark(clientData, serverData, socksPort)
|
|
}
|