(t *testing.T)
| 34 | } |
| 35 | |
| 36 | func TestTerminating_DecryptsAndForwards(t *testing.T) { |
| 37 | // 模拟两个 xray 明文后端 |
| 38 | backendA := startEchoPlaintext(t) |
| 39 | backendB := startEchoPlaintext(t) |
| 40 | |
| 41 | // 一张自签证书服务所有 SNI(测试用) |
| 42 | cert := genSelfSigned(t) |
| 43 | tlsCfg := &tls.Config{ |
| 44 | Certificates: []tls.Certificate{cert}, |
| 45 | } |
| 46 | |
| 47 | proxy := &TerminatingProxy{ |
| 48 | Addr: "127.0.0.1:0", |
| 49 | TLSConfig: tlsCfg, |
| 50 | } |
| 51 | proxy.SetRoutes([]TerminatingRoute{ |
| 52 | {SNI: "a.example.com", Backend: backendA}, |
| 53 | {SNI: "b.example.com", Backend: backendB}, |
| 54 | }) |
| 55 | |
| 56 | // 提前分配端口 |
| 57 | ln, _ := net.Listen("tcp", "127.0.0.1:0") |
| 58 | addr := ln.Addr().String() |
| 59 | _ = ln.Close() |
| 60 | proxy.Addr = addr |
| 61 | |
| 62 | ctx, cancel := context.WithCancel(context.Background()) |
| 63 | defer cancel() |
| 64 | var wg sync.WaitGroup |
| 65 | wg.Add(1) |
| 66 | go func() { defer wg.Done(); _ = proxy.Serve(ctx) }() |
| 67 | t.Cleanup(func() { cancel(); wg.Wait() }) |
| 68 | |
| 69 | waitForListen(t, addr) |
| 70 | |
| 71 | for _, sni := range []string{"a.example.com", "b.example.com"} { |
| 72 | t.Run(sni, func(t *testing.T) { |
| 73 | conn, err := net.Dial("tcp", addr) |
| 74 | if err != nil { |
| 75 | t.Fatal(err) |
| 76 | } |
| 77 | defer conn.Close() |
| 78 | tc := tls.Client(conn, &tls.Config{ServerName: sni, InsecureSkipVerify: true}) |
| 79 | _ = tc.SetDeadline(time.Now().Add(3 * time.Second)) |
| 80 | if err := tc.Handshake(); err != nil { |
| 81 | t.Fatalf("handshake: %v", err) |
| 82 | } |
| 83 | want := []byte("hello-" + sni) |
| 84 | if _, err := tc.Write(want); err != nil { |
| 85 | t.Fatal(err) |
| 86 | } |
| 87 | got := make([]byte, len(want)) |
| 88 | if _, err := io.ReadFull(tc, got); err != nil { |
| 89 | t.Fatal(err) |
| 90 | } |
| 91 | if string(got) != string(want) { |
| 92 | t.Errorf("echo = %q, want %q", got, want) |
| 93 | } |
nothing calls this directly
no test coverage detected