diff options
author | Sam Whited <sam@samwhited.com> | 2022-03-17 16:05:00 -0400 |
---|---|---|
committer | Sam Whited <sam@samwhited.com> | 2022-04-19 09:07:08 -0400 |
commit | 5e8594262f537efd02d1a3d7ad7d7e9013f1e76e (patch) | |
tree | d162d48de87beb1eb7744d6ae0e1d3ef91796b27 /obfsproxy/main_test.go | |
parent | 790d6f76ad24ec8153db9eb8dde21c1c6bc44d3f (diff) |
obfsproxy: add initial proxy implementation
Fixes #3
Updates #4
Signed-off-by: Sam Whited <sam@samwhited.com>
Diffstat (limited to 'obfsproxy/main_test.go')
-rw-r--r-- | obfsproxy/main_test.go | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/obfsproxy/main_test.go b/obfsproxy/main_test.go new file mode 100644 index 0000000..d22d3af --- /dev/null +++ b/obfsproxy/main_test.go @@ -0,0 +1,92 @@ +package main + +import ( + "context" + "flag" + "net" + "os" + "os/exec" + "testing" + "time" + + "golang.org/x/net/proxy" +) + +type testWriter struct { + t *testing.T + prefix string +} + +func (w testWriter) Write(p []byte) (int, error) { + w.t.Logf("%s%s", w.prefix, p) + return len(p), nil +} + +func TestMain(m *testing.M) { + runProxy := flag.Bool("runproxy", false, "Start the command instead of running the tests") + flag.Parse() + if *runProxy { + os.Args = append(os.Args[0:1], flag.Args()...) + main() + return + } + os.Exit(m.Run()) +} + +func TestRoundTrip(t *testing.T) { + // Setup and exec the proxy: + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + // Instead of passing a listener to the command or doing IPC to get the + // address of the listener created by the command back out, which would all + // require changes to the actual binary for something that has no use outside + // of tests and is just another potential source of errors, just start and + // stop a listener to get a random port and then pass that in (for the command + // to re-open) as a string. It's not ideal, but it's simple. + ln, err := net.Listen("tcp", "[::1]:0") + if err != nil { + t.Fatalf("error listening: %v", err) + } + addr := ln.Addr() + err = ln.Close() + if err != nil { + t.Fatalf("error closing listener: %v", err) + } + cmd := exec.CommandContext(ctx, os.Args[0], "-runproxy", "--", "-addr", addr.String(), "-proxy", "37.218.241.98:4430") + cmd.Stdout = testWriter{prefix: "stdout ", t: t} + cmd.Stderr = testWriter{prefix: "stderr ", t: t} + t.Logf("running proxy command %v", cmd.Args) + err = cmd.Start() + if err != nil { + t.Fatalf("error starting proxy: %v", err) + } + + // Once the proxy is running, try to connect: + ln, err = net.Listen("tcp", "[::1]:0") + if err != nil { + t.Fatalf("error listening for connection: %v", err) + } + go func() { + conn, err := ln.Accept() + if err != nil { + t.Logf("error accepting connection: %v", err) + } + t.Logf("got conn: %v", conn) + }() + dialer, err := proxy.SOCKS5("tcp", addr.String(), nil, proxy.Direct) + if err != nil { + t.Fatalf("error creating socks dialer: %v", err) + } + + // TODO: this is slow, flakey, and generally jank. Can we watch /proc for a + // new file descriptor or just poll until the listener is open? + t.Logf("waiting 3 seconds for command to start…") + time.Sleep(3 * time.Second) + + _, err = dialer.Dial("tcp", ln.Addr().String()) + if err != nil { + t.Fatalf("error dialing: %v", err) + } + + select {} +} |