summaryrefslogtreecommitdiff
path: root/obfsproxy/main_test.go
diff options
context:
space:
mode:
authorSam Whited <sam@samwhited.com>2022-03-17 16:05:00 -0400
committerSam Whited <sam@samwhited.com>2022-04-19 09:07:08 -0400
commit5e8594262f537efd02d1a3d7ad7d7e9013f1e76e (patch)
treed162d48de87beb1eb7744d6ae0e1d3ef91796b27 /obfsproxy/main_test.go
parent790d6f76ad24ec8153db9eb8dde21c1c6bc44d3f (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.go92
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 {}
+}