From 664d8e4d3af0337cd0c6392f9f3f01b6315e9b84 Mon Sep 17 00:00:00 2001 From: Brandon Wiley Date: Wed, 22 Feb 2017 11:39:25 -0600 Subject: Implemented use of transports that require parameters --- modes/pt_socks5/pt_socks5.go | 135 ++++++++++++++++++++++++++----- modes/stun_udp/stun_udp.go | 125 +++++++++++++++++++++++----- modes/transparent_tcp/transparent_tcp.go | 124 +++++++++++++++++++++++----- modes/transparent_udp/transparent_udp.go | 124 +++++++++++++++++++++++----- 4 files changed, 430 insertions(+), 78 deletions(-) diff --git a/modes/pt_socks5/pt_socks5.go b/modes/pt_socks5/pt_socks5.go index b6bda12..9243f31 100644 --- a/modes/pt_socks5/pt_socks5.go +++ b/modes/pt_socks5/pt_socks5.go @@ -30,10 +30,10 @@ package pt_socks5 import ( - "fmt" "io" "net" "net/url" + "strconv" "sync" "github.com/OperatorFoundation/shapeshifter-dispatcher/common/log" @@ -41,6 +41,9 @@ import ( "github.com/OperatorFoundation/shapeshifter-dispatcher/common/termmon" "github.com/OperatorFoundation/shapeshifter-ipc" "github.com/OperatorFoundation/shapeshifter-transports/transports/base" + "github.com/OperatorFoundation/shapeshifter-transports/transports/meeklite" + "github.com/OperatorFoundation/shapeshifter-transports/transports/obfs2" + "github.com/OperatorFoundation/shapeshifter-transports/transports/obfs4" ) const ( @@ -49,16 +52,16 @@ const ( var stateDir string -func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url.URL, factories map[string]base.ClientFactory) (launched bool, listeners []net.Listener) { +func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url.URL, names []string, options string) (launched bool, listeners []net.Listener) { // Launch each of the client listeners. - for name, f := range factories { + for _, name := range names { ln, err := net.Listen("tcp", socksAddr) if err != nil { pt.CmethodError(name, err.Error()) continue } - go clientAcceptLoop(target, termMon, name, f, ln, ptClientProxy) + go clientAcceptLoop(target, termMon, name, ln, ptClientProxy, options) pt.Cmethod(name, socks5.Version(), ln.Addr()) log.Infof("%s - registered listener: %s", name, ln.Addr()) @@ -71,7 +74,7 @@ func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url return } -func clientAcceptLoop(target string, termMon *termmon.TermMonitor, name string, f base.ClientFactory, ln net.Listener, proxyURI *url.URL) error { +func clientAcceptLoop(target string, termMon *termmon.TermMonitor, name string, ln net.Listener, proxyURI *url.URL, options string) error { defer ln.Close() for { conn, err := ln.Accept() @@ -81,30 +84,79 @@ func clientAcceptLoop(target string, termMon *termmon.TermMonitor, name string, } continue } - go clientHandler(target, termMon, name, f, conn, proxyURI) + go clientHandler(target, termMon, name, conn, proxyURI, options) } } -func clientHandler(target string, termMon *termmon.TermMonitor, name string, f base.ClientFactory, conn net.Conn, proxyURI *url.URL) { +func clientHandler(target string, termMon *termmon.TermMonitor, name string, conn net.Conn, proxyURI *url.URL, options string) { defer conn.Close() termMon.OnHandlerStart() defer termMon.OnHandlerFinish() + var needOptions bool = options == "" + // Read the client's SOCKS handshake. - socksReq, err := socks5.Handshake(conn) + socksReq, err := socks5.Handshake(conn, needOptions) if err != nil { log.Errorf("%s - client failed socks handshake: %s", name, err) return } addrStr := log.ElideAddr(socksReq.Target) + var args pt.Args + if needOptions { + args = socksReq.Args + } else { + args, err = pt.ParsePT2ClientParameters(options) + if err != nil { + return + } + } + + var transport base.Transport + // Deal with arguments. - // args, err := f.ParseArgs(&socksReq.Args) - // if err != nil { - // log.Errorf("%s(%s) - invalid arguments: %s", name, addrStr, err) - // socksReq.Reply(socks5.ReplyGeneralFailure) - // return - // } + switch name { + case "obfs2": + transport = obfs2.NewObfs2Transport() + case "meeklite": + if url, ok := args.Get("url"); ok { + if front, ok2 := args.Get("front"); ok2 { + transport = meeklite.NewMeekTransportWithFront(url, front) + } else { + transport = meeklite.NewMeekTransport(url) + } + } else { + log.Errorf("meeklite transport missing URL argument: %s", args) + socksReq.Reply(socks5.ReplyGeneralFailure) + return + } + case "obfs4": + if cert, ok := args.Get("cert"); ok { + if iatModeStr, ok2 := args.Get("iatMode"); ok2 { + iatMode, err := strconv.Atoi(iatModeStr) + if err != nil { + transport = obfs4.NewObfs4Client(cert, iatMode) + } else { + log.Errorf("obfs4 transport bad iatMode value: %s", iatModeStr) + socksReq.Reply(socks5.ReplyGeneralFailure) + return + } + } else { + log.Errorf("obfs4 transport missing cert argument: %s", args) + socksReq.Reply(socks5.ReplyGeneralFailure) + return + } + } else { + log.Errorf("obfs4 transport missing cert argument: %s", args) + socksReq.Reply(socks5.ReplyGeneralFailure) + return + } + default: + log.Errorf("Unknown transport: %s", name) + socksReq.Reply(socks5.ReplyGeneralFailure) + return + } // Obtain the proxy dialer if any, and create the outgoing TCP connection. // dialFn := proxy.Direct.Dial @@ -122,6 +174,8 @@ func clientHandler(target string, termMon *termmon.TermMonitor, name string, f b // // fmt.Println("Got dialer", dialFn, proxyURI, proxy.Direct) + f := transport.Dial + remote := f(socksReq.Target) if err != nil { log.Errorf("%s(%s) - outgoing connection failed: %s", name, addrStr, log.ElideError(err)) @@ -144,15 +198,58 @@ func clientHandler(target string, termMon *termmon.TermMonitor, name string, f b return } -func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, factories map[string]base.ServerFactory, ptServerInfo pt.ServerInfo) (launched bool, listeners []base.TransportListener) { +func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, ptServerInfo pt.ServerInfo, options string) (launched bool, listeners []base.TransportListener) { for _, bindaddr := range ptServerInfo.Bindaddrs { name := bindaddr.MethodName - f := factories[name] - if f == nil { - fmt.Println(name, "no such transport is supported") - continue + + var transport base.Transport + + args, argsErr := pt.ParsePT2ClientParameters(options) + if argsErr != nil { + log.Errorf("Error parsing transport options: %s", options) + return } + // Deal with arguments. + switch name { + case "obfs2": + transport = obfs2.NewObfs2Transport() + case "meeklite": + if url, ok := args["url"]; ok { + if front, ok2 := args["front"]; ok2 { + transport = meeklite.NewMeekTransportWithFront(url[0], front[0]) + } else { + transport = meeklite.NewMeekTransport(url[0]) + } + } else { + log.Errorf("meeklite transport missing URL argument: %s", args) + return + } + case "obfs4": + if cert, ok := args["cert"]; ok { + if iatModeStr, ok2 := args["iatMode"]; ok2 { + iatMode, err := strconv.Atoi(iatModeStr[0]) + if err != nil { + transport = obfs4.NewObfs4Client(cert[0], iatMode) + } else { + log.Errorf("obfs4 transport bad iatMode value: %s", iatModeStr) + return + } + } else { + log.Errorf("obfs4 transport missing cert argument: %s", args) + return + } + } else { + log.Errorf("obfs4 transport missing cert argument: %s", args) + return + } + default: + log.Errorf("Unknown transport: %s", name) + return + } + + f := transport.Listen + transportLn := f(bindaddr.Addr.String()) go serverAcceptLoop(termMon, name, transportLn, &ptServerInfo) diff --git a/modes/stun_udp/stun_udp.go b/modes/stun_udp/stun_udp.go index d1cff6f..81ef6d8 100644 --- a/modes/stun_udp/stun_udp.go +++ b/modes/stun_udp/stun_udp.go @@ -46,6 +46,9 @@ import ( "github.com/OperatorFoundation/shapeshifter-dispatcher/common/termmon" "github.com/OperatorFoundation/shapeshifter-ipc" "github.com/OperatorFoundation/shapeshifter-transports/transports/base" + "github.com/OperatorFoundation/shapeshifter-transports/transports/meeklite" + "github.com/OperatorFoundation/shapeshifter-transports/transports/obfs2" + "github.com/OperatorFoundation/shapeshifter-transports/transports/obfs4" ) const ( @@ -65,9 +68,9 @@ func NewConnState() ConnState { type ConnTracker map[string]ConnState -func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url.URL, factories map[string]base.ClientFactory) bool { +func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url.URL, names []string, options string) bool { // Launch each of the client listeners. - for name, f := range factories { + for _, name := range names { udpAddr, err := net.ResolveUDPAddr("udp", socksAddr) if err != nil { fmt.Println("Error resolving address", socksAddr) @@ -80,7 +83,7 @@ func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url continue } - go clientHandler(target, termMon, name, f, ln, ptClientProxy) + go clientHandler(target, termMon, name, options, ln, ptClientProxy) log.Infof("%s - registered listener: %s", name, ln) } @@ -88,7 +91,7 @@ func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url return true } -func clientHandler(target string, termMon *termmon.TermMonitor, name string, f base.ClientFactory, conn *net.UDPConn, proxyURI *url.URL) { +func clientHandler(target string, termMon *termmon.TermMonitor, name string, options string, conn *net.UDPConn, proxyURI *url.URL) { defer conn.Close() termMon.OnHandlerStart() defer termMon.OnHandlerFinish() @@ -131,7 +134,7 @@ func clientHandler(target string, termMon *termmon.TermMonitor, name string, f b fmt.Println("Opening connection to ", target) - openConnection(&tracker, addr.String(), target, termMon, f, proxyURI) + openConnection(&tracker, addr.String(), target, termMon, name, options, proxyURI) // Drop the packet. fmt.Println("recv: Open") @@ -139,16 +142,16 @@ func clientHandler(target string, termMon *termmon.TermMonitor, name string, f b } } -func openConnection(tracker *ConnTracker, addr string, target string, termMon *termmon.TermMonitor, f base.ClientFactory, proxyURI *url.URL) { +func openConnection(tracker *ConnTracker, addr string, target string, termMon *termmon.TermMonitor, name string, options string, proxyURI *url.URL) { fmt.Println("Making dialer...") newConn := NewConnState() (*tracker)[addr] = newConn - go dialConn(tracker, addr, target, f, proxyURI) + go dialConn(tracker, addr, target, name, options, proxyURI) } -func dialConn(tracker *ConnTracker, addr string, target string, f base.ClientFactory, proxyURI *url.URL) { +func dialConn(tracker *ConnTracker, addr string, target string, name string, options string, proxyURI *url.URL) { // Obtain the proxy dialer if any, and create the outgoing TCP connection. // dialFn := proxy.Direct.Dial // if proxyURI != nil { @@ -165,14 +168,53 @@ func dialConn(tracker *ConnTracker, addr string, target string, f base.ClientFac fmt.Println("Dialing....") + var transport base.Transport + + args, argsErr := pt.ParsePT2ClientParameters(options) + if argsErr != nil { + log.Errorf("Error parsing transport options: %s", options) + return + } + // Deal with arguments. - // args, err := f.ParseArgs(&pt.Args{}) - // if err != nil { - // fmt.Println("Invalid arguments") - // log.Errorf("(%s) - invalid arguments: %s", target, err) - // delete(*tracker, addr) - // return - // } + switch name { + case "obfs2": + transport = obfs2.NewObfs2Transport() + case "meeklite": + if url, ok := args["url"]; ok { + if front, ok2 := args["front"]; ok2 { + transport = meeklite.NewMeekTransportWithFront(url[0], front[0]) + } else { + transport = meeklite.NewMeekTransport(url[0]) + } + } else { + log.Errorf("meeklite transport missing URL argument: %s", args) + return + } + case "obfs4": + if cert, ok := args["cert"]; ok { + if iatModeStr, ok2 := args["iatMode"]; ok2 { + iatMode, err := strconv.Atoi(iatModeStr[0]) + if err != nil { + transport = obfs4.NewObfs4Client(cert[0], iatMode) + } else { + log.Errorf("obfs4 transport bad iatMode value: %s", iatModeStr) + return + } + } else { + log.Errorf("obfs4 transport missing cert argument: %s", args) + return + } + } else { + log.Errorf("obfs4 transport missing cert argument: %s", args) + return + } + default: + log.Errorf("Unknown transport: %s", name) + return + } + + f := transport.Dial fmt.Println("Dialing ", target) remote := f(target) @@ -189,19 +231,62 @@ func dialConn(tracker *ConnTracker, addr string, target string, f base.ClientFac (*tracker)[addr] = ConnState{remote, false} } -func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, factories map[string]base.ServerFactory, ptServerInfo pt.ServerInfo) (launched bool, listeners []base.TransportListener) { +func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, ptServerInfo pt.ServerInfo, options string) (launched bool, listeners []base.TransportListener) { fmt.Println("ServerSetup") // Launch each of the server listeners. for _, bindaddr := range ptServerInfo.Bindaddrs { name := bindaddr.MethodName fmt.Println("bindaddr", bindaddr) - f := factories[name] - if f == nil { - fmt.Println(name, "no such transport is supported") - continue + + var transport base.Transport + + args, argsErr := pt.ParsePT2ClientParameters(options) + if argsErr != nil { + log.Errorf("Error parsing transport options: %s", options) + return } + // Deal with arguments. + switch name { + case "obfs2": + transport = obfs2.NewObfs2Transport() + case "meeklite": + if url, ok := args["url"]; ok { + if front, ok2 := args["front"]; ok2 { + transport = meeklite.NewMeekTransportWithFront(url[0], front[0]) + } else { + transport = meeklite.NewMeekTransport(url[0]) + } + } else { + log.Errorf("meeklite transport missing URL argument: %s", args) + return + } + case "obfs4": + if cert, ok := args["cert"]; ok { + if iatModeStr, ok2 := args["iatMode"]; ok2 { + iatMode, err := strconv.Atoi(iatModeStr[0]) + if err != nil { + transport = obfs4.NewObfs4Client(cert[0], iatMode) + } else { + log.Errorf("obfs4 transport bad iatMode value: %s", iatModeStr) + return + } + } else { + log.Errorf("obfs4 transport missing cert argument: %s", args) + return + } + } else { + log.Errorf("obfs4 transport missing cert argument: %s", args) + return + } + default: + log.Errorf("Unknown transport: %s", name) + return + } + + f := transport.Listen + transportLn := f(bindaddr.Addr.String()) go serverAcceptLoop(termMon, name, transportLn, &ptServerInfo) diff --git a/modes/transparent_tcp/transparent_tcp.go b/modes/transparent_tcp/transparent_tcp.go index bbc0c7f..61d6c6e 100644 --- a/modes/transparent_tcp/transparent_tcp.go +++ b/modes/transparent_tcp/transparent_tcp.go @@ -34,6 +34,7 @@ import ( "io" "net" "net/url" + "strconv" "strings" "sync" @@ -41,6 +42,9 @@ import ( "github.com/OperatorFoundation/shapeshifter-dispatcher/common/termmon" "github.com/OperatorFoundation/shapeshifter-ipc" "github.com/OperatorFoundation/shapeshifter-transports/transports/base" + "github.com/OperatorFoundation/shapeshifter-transports/transports/meeklite" + "github.com/OperatorFoundation/shapeshifter-transports/transports/obfs2" + "github.com/OperatorFoundation/shapeshifter-transports/transports/obfs4" ) const ( @@ -49,9 +53,9 @@ const ( var stateDir string -func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url.URL, factories map[string]base.ClientFactory) (launched bool, listeners []net.Listener) { +func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url.URL, names []string, options string) (launched bool, listeners []net.Listener) { // Launch each of the client listeners. - for name, f := range factories { + for _, name := range names { fmt.Println("Listening ", socksAddr) ln, err := net.Listen("tcp", socksAddr) if err != nil { @@ -59,7 +63,7 @@ func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url continue } - go clientAcceptLoop(target, termMon, name, f, ln, ptClientProxy) + go clientAcceptLoop(target, termMon, name, options, ln, ptClientProxy) log.Infof("%s - registered listener: %s", name, ln.Addr()) @@ -70,7 +74,7 @@ func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url return } -func clientAcceptLoop(target string, termMon *termmon.TermMonitor, name string, f base.ClientFactory, ln net.Listener, proxyURI *url.URL) error { +func clientAcceptLoop(target string, termMon *termmon.TermMonitor, name string, options string, ln net.Listener, proxyURI *url.URL) error { defer ln.Close() for { conn, err := ln.Accept() @@ -81,11 +85,11 @@ func clientAcceptLoop(target string, termMon *termmon.TermMonitor, name string, } continue } - go clientHandler(target, termMon, name, f, conn, proxyURI) + go clientHandler(target, termMon, name, options, conn, proxyURI) } } -func clientHandler(target string, termMon *termmon.TermMonitor, name string, f base.ClientFactory, conn net.Conn, proxyURI *url.URL) { +func clientHandler(target string, termMon *termmon.TermMonitor, name string, options string, conn net.Conn, proxyURI *url.URL) { defer conn.Close() termMon.OnHandlerStart() defer termMon.OnHandlerFinish() @@ -94,14 +98,53 @@ func clientHandler(target string, termMon *termmon.TermMonitor, name string, f b fmt.Println("Transport is", name) + var transport base.Transport + + args, argsErr := pt.ParsePT2ClientParameters(options) + if argsErr != nil { + log.Errorf("Error parsing transport options: %s", options) + return + } + // Deal with arguments. - // FIXME - deal with args for transports that have args - // args, err := f.ParseArgs(&pt.Args{}) - // if err != nil { - // fmt.Println("Invalid arguments") - // log.Errorf("%s(%s) - invalid arguments: %s", name, target, err) - // return - // } + switch name { + case "obfs2": + transport = obfs2.NewObfs2Transport() + case "meeklite": + if url, ok := args["url"]; ok { + if front, ok2 := args["front"]; ok2 { + transport = meeklite.NewMeekTransportWithFront(url[0], front[0]) + } else { + transport = meeklite.NewMeekTransport(url[0]) + } + } else { + log.Errorf("meeklite transport missing URL argument: %s", args) + return + } + case "obfs4": + if cert, ok := args["cert"]; ok { + if iatModeStr, ok2 := args["iatMode"]; ok2 { + iatMode, err := strconv.Atoi(iatModeStr[0]) + if err != nil { + transport = obfs4.NewObfs4Client(cert[0], iatMode) + } else { + log.Errorf("obfs4 transport bad iatMode value: %s", iatModeStr) + return + } + } else { + log.Errorf("obfs4 transport missing cert argument: %s", args) + return + } + } else { + log.Errorf("obfs4 transport missing cert argument: %s", args) + return + } + default: + log.Errorf("Unknown transport: %s", name) + return + } + + f := transport.Dial fmt.Println("Making dialer...") @@ -143,19 +186,62 @@ func clientHandler(target string, termMon *termmon.TermMonitor, name string, f b return } -func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, factories map[string]base.ServerFactory, ptServerInfo pt.ServerInfo) (launched bool, listeners []base.TransportListener) { - fmt.Println("ServerSetup", bindaddrString, factories, ptServerInfo) +func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, ptServerInfo pt.ServerInfo, options string) (launched bool, listeners []base.TransportListener) { + fmt.Println("ServerSetup", bindaddrString, ptServerInfo, options) // Launch each of the server listeners. for _, bindaddr := range ptServerInfo.Bindaddrs { name := bindaddr.MethodName fmt.Println("bindaddr", bindaddr) - f := factories[name] - if f == nil { - fmt.Println(name, "no such transport is supported") - continue + + var transport base.Transport + + args, argsErr := pt.ParsePT2ClientParameters(options) + if argsErr != nil { + log.Errorf("Error parsing transport options: %s", options) + return } + // Deal with arguments. + switch name { + case "obfs2": + transport = obfs2.NewObfs2Transport() + case "meeklite": + if url, ok := args["url"]; ok { + if front, ok2 := args["front"]; ok2 { + transport = meeklite.NewMeekTransportWithFront(url[0], front[0]) + } else { + transport = meeklite.NewMeekTransport(url[0]) + } + } else { + log.Errorf("meeklite transport missing URL argument: %s", args) + return + } + case "obfs4": + if cert, ok := args["cert"]; ok { + if iatModeStr, ok2 := args["iatMode"]; ok2 { + iatMode, err := strconv.Atoi(iatModeStr[0]) + if err != nil { + transport = obfs4.NewObfs4Client(cert[0], iatMode) + } else { + log.Errorf("obfs4 transport bad iatMode value: %s", iatModeStr) + return + } + } else { + log.Errorf("obfs4 transport missing cert argument: %s", args) + return + } + } else { + log.Errorf("obfs4 transport missing cert argument: %s", args) + return + } + default: + log.Errorf("Unknown transport: %s", name) + return + } + + f := transport.Listen + transportLn := f(bindaddr.Addr.String()) go serverAcceptLoop(termMon, name, transportLn, &ptServerInfo) diff --git a/modes/transparent_udp/transparent_udp.go b/modes/transparent_udp/transparent_udp.go index f993b5e..63591a7 100644 --- a/modes/transparent_udp/transparent_udp.go +++ b/modes/transparent_udp/transparent_udp.go @@ -44,6 +44,9 @@ import ( "github.com/OperatorFoundation/shapeshifter-dispatcher/common/termmon" "github.com/OperatorFoundation/shapeshifter-ipc" "github.com/OperatorFoundation/shapeshifter-transports/transports/base" + "github.com/OperatorFoundation/shapeshifter-transports/transports/meeklite" + "github.com/OperatorFoundation/shapeshifter-transports/transports/obfs2" + "github.com/OperatorFoundation/shapeshifter-transports/transports/obfs4" ) const ( @@ -63,9 +66,9 @@ func NewConnState() ConnState { type ConnTracker map[string]ConnState -func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url.URL, factories map[string]base.ClientFactory) bool { +func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url.URL, names []string, options string) bool { // Launch each of the client listeners. - for name, f := range factories { + for _, name := range names { udpAddr, err := net.ResolveUDPAddr("udp", socksAddr) if err != nil { fmt.Println("Error resolving address", socksAddr) @@ -78,7 +81,7 @@ func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url continue } - go clientHandler(target, termMon, name, f, ln, ptClientProxy) + go clientHandler(target, termMon, name, options, ln, ptClientProxy) log.Infof("%s - registered listener: %s", name, ln) } @@ -86,7 +89,7 @@ func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url return true } -func clientHandler(target string, termMon *termmon.TermMonitor, name string, f base.ClientFactory, conn *net.UDPConn, proxyURI *url.URL) { +func clientHandler(target string, termMon *termmon.TermMonitor, name string, options string, conn *net.UDPConn, proxyURI *url.URL) { var length16 uint16 defer conn.Close() @@ -142,7 +145,7 @@ func clientHandler(target string, termMon *termmon.TermMonitor, name string, f b fmt.Println("Opening connection to ", target) - openConnection(&tracker, addr.String(), target, termMon, f, proxyURI) + openConnection(&tracker, addr.String(), target, termMon, name, options, proxyURI) // Drop the packet. fmt.Println("recv: Open") @@ -150,16 +153,16 @@ func clientHandler(target string, termMon *termmon.TermMonitor, name string, f b } } -func openConnection(tracker *ConnTracker, addr string, target string, termMon *termmon.TermMonitor, f base.ClientFactory, proxyURI *url.URL) { +func openConnection(tracker *ConnTracker, addr string, target string, termMon *termmon.TermMonitor, name string, options string, proxyURI *url.URL) { fmt.Println("Making dialer...") newConn := NewConnState() (*tracker)[addr] = newConn - go dialConn(tracker, addr, target, f, proxyURI) + go dialConn(tracker, addr, target, name, options, proxyURI) } -func dialConn(tracker *ConnTracker, addr string, target string, f base.ClientFactory, proxyURI *url.URL) { +func dialConn(tracker *ConnTracker, addr string, target string, name string, options string, proxyURI *url.URL) { // Obtain the proxy dialer if any, and create the outgoing TCP connection. // dialFn := proxy.Direct.Dial // if proxyURI != nil { @@ -176,15 +179,53 @@ func dialConn(tracker *ConnTracker, addr string, target string, f base.ClientFac fmt.Println("Dialing....") + var transport base.Transport + + args, argsErr := pt.ParsePT2ClientParameters(options) + if argsErr != nil { + log.Errorf("Error parsing transport options: %s", options) + return + } + // Deal with arguments. - // args, err := f.ParseArgs(&pt.Args{}) - // if err != nil { - // fmt.Println("Invalid arguments") - // log.Errorf("(%s) - invalid arguments: %s", target, err) - // delete(*tracker, addr) - // return - // } + switch name { + case "obfs2": + transport = obfs2.NewObfs2Transport() + case "meeklite": + if url, ok := args["url"]; ok { + if front, ok2 := args["front"]; ok2 { + transport = meeklite.NewMeekTransportWithFront(url[0], front[0]) + } else { + transport = meeklite.NewMeekTransport(url[0]) + } + } else { + log.Errorf("meeklite transport missing URL argument: %s", args) + return + } + case "obfs4": + if cert, ok := args["cert"]; ok { + if iatModeStr, ok2 := args["iatMode"]; ok2 { + iatMode, err := strconv.Atoi(iatModeStr[0]) + if err != nil { + transport = obfs4.NewObfs4Client(cert[0], iatMode) + } else { + log.Errorf("obfs4 transport bad iatMode value: %s", iatModeStr) + return + } + } else { + log.Errorf("obfs4 transport missing cert argument: %s", args) + return + } + } else { + log.Errorf("obfs4 transport missing cert argument: %s", args) + return + } + default: + log.Errorf("Unknown transport: %s", name) + return + } + f := transport.Dial fmt.Println("Dialing ", target) remote := f(target) // if err != nil { @@ -200,19 +241,62 @@ func dialConn(tracker *ConnTracker, addr string, target string, f base.ClientFac (*tracker)[addr] = ConnState{remote, false} } -func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, factories map[string]base.ServerFactory, ptServerInfo pt.ServerInfo) (launched bool, listeners []base.TransportListener) { +func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, ptServerInfo pt.ServerInfo, options string) (launched bool, listeners []base.TransportListener) { fmt.Println("ServerSetup") // Launch each of the server listeners. for _, bindaddr := range ptServerInfo.Bindaddrs { name := bindaddr.MethodName fmt.Println("bindaddr", bindaddr) - f := factories[name] - if f == nil { - fmt.Println(name, "no such transport is supported") - continue + + var transport base.Transport + + args, argsErr := pt.ParsePT2ClientParameters(options) + if argsErr != nil { + log.Errorf("Error parsing transport options: %s", options) + return + } + + // Deal with arguments. + switch name { + case "obfs2": + transport = obfs2.NewObfs2Transport() + case "meeklite": + if url, ok := args["url"]; ok { + if front, ok2 := args["front"]; ok2 { + transport = meeklite.NewMeekTransportWithFront(url[0], front[0]) + } else { + transport = meeklite.NewMeekTransport(url[0]) + } + } else { + log.Errorf("meeklite transport missing URL argument: %s", args) + return + } + case "obfs4": + if cert, ok := args["cert"]; ok { + if iatModeStr, ok2 := args["iatMode"]; ok2 { + iatMode, err := strconv.Atoi(iatModeStr[0]) + if err != nil { + transport = obfs4.NewObfs4Client(cert[0], iatMode) + } else { + log.Errorf("obfs4 transport bad iatMode value: %s", iatModeStr) + return + } + } else { + log.Errorf("obfs4 transport missing cert argument: %s", args) + return + } + } else { + log.Errorf("obfs4 transport missing cert argument: %s", args) + return + } + default: + log.Errorf("Unknown transport: %s", name) + return } + f := transport.Listen + transportLn := f(bindaddr.Addr.String()) go serverAcceptLoop(termMon, name, transportLn, &ptServerInfo) -- cgit v1.2.3