From fc4bf82171d7337c9db1ce91e553a3b9a97beb02 Mon Sep 17 00:00:00 2001 From: Brandon Wiley Date: Wed, 16 Nov 2016 15:10:16 -0600 Subject: Added new command line flags and refactored ClientSetup to use them --- common/pt_extras/pt_extras.go | 10 ++- modes/pt_socks5/pt_socks5.go | 34 +-------- modes/stun_udp/stun_udp.go | 57 +++++--------- modes/transparent_tcp/transparent_tcp.go | 23 +----- modes/transparent_udp/transparent_udp.go | 61 ++++++--------- shapeshifter-dispatcher/shapeshifter-dispatcher.go | 89 +++++++++++++++++++--- 6 files changed, 135 insertions(+), 139 deletions(-) diff --git a/common/pt_extras/pt_extras.go b/common/pt_extras/pt_extras.go index 5f287e3..17314bf 100644 --- a/common/pt_extras/pt_extras.go +++ b/common/pt_extras/pt_extras.go @@ -71,8 +71,14 @@ func PtIsClient() (bool, error) { return false, errors.New("not launched as a managed transport") } -func PtGetProxy() (*url.URL, error) { - specString := os.Getenv("TOR_PT_PROXY") +func PtGetProxy(proxy *string) (*url.URL, error) { + var specString string + + if proxy != nil { + specString = *proxy + } else { + specString = os.Getenv("TOR_PT_PROXY") + } if specString == "" { return nil, nil } diff --git a/modes/pt_socks5/pt_socks5.go b/modes/pt_socks5/pt_socks5.go index e7a4cec..38b0e2c 100644 --- a/modes/pt_socks5/pt_socks5.go +++ b/modes/pt_socks5/pt_socks5.go @@ -41,7 +41,6 @@ import ( "git.torproject.org/pluggable-transports/goptlib.git" "github.com/OperatorFoundation/shapeshifter-dispatcher/common/log" - "github.com/OperatorFoundation/shapeshifter-dispatcher/common/pt_extras" "github.com/OperatorFoundation/shapeshifter-dispatcher/common/socks5" "github.com/OperatorFoundation/shapeshifter-dispatcher/common/termmon" "github.com/OperatorFoundation/shapeshifter-dispatcher/transports" @@ -49,41 +48,14 @@ import ( ) const ( - obfs4proxyVersion = "0.0.7-dev" - obfs4proxyLogFile = "obfs4proxy.log" - socksAddr = "127.0.0.1:0" + socksAddr = "127.0.0.1:0" ) var stateDir string -func ClientSetup(termMon *termmon.TermMonitor) (launched bool, listeners []net.Listener) { - ptClientInfo, err := pt.ClientSetup(transports.Transports()) - if err != nil { - golog.Fatal(err) - } - - ptClientProxy, err := pt_extras.PtGetProxy() - fmt.Println("ptclientproxy", ptClientProxy) - if err != nil { - golog.Fatal(err) - } else if ptClientProxy != nil { - pt_extras.PtProxyDone() - } - +func ClientSetup(termMon *termmon.TermMonitor, ptClientProxy *url.URL, factories map[string]base.ClientFactory) (launched bool, listeners []net.Listener) { // Launch each of the client listeners. - for _, name := range ptClientInfo.MethodNames { - t := transports.Get(name) - if t == nil { - pt.CmethodError(name, "no such transport is supported") - continue - } - - f, err := t.ClientFactory(stateDir) - if err != nil { - pt.CmethodError(name, "failed to get ClientFactory") - continue - } - + for name, f := range factories { ln, err := net.Listen("tcp", socksAddr) if err != nil { pt.CmethodError(name, err.Error()) diff --git a/modes/stun_udp/stun_udp.go b/modes/stun_udp/stun_udp.go index bf3045d..d636881 100644 --- a/modes/stun_udp/stun_udp.go +++ b/modes/stun_udp/stun_udp.go @@ -30,8 +30,8 @@ package stun_udp import ( - "io" "fmt" + "io" golog "log" "net" "net/url" @@ -52,15 +52,13 @@ import ( ) const ( - obfs4proxyVersion = "0.0.7-dev" - obfs4proxyLogFile = "obfs4proxy.log" - socksAddr = "127.0.0.1:1234" + socksAddr = "127.0.0.1:1234" ) var stateDir string type ConnState struct { - Conn *net.Conn + Conn *net.Conn Waiting bool } @@ -70,24 +68,9 @@ func NewConnState() ConnState { type ConnTracker map[string]ConnState -func ClientSetup(termMon *termmon.TermMonitor, target string) bool { - methodNames := [...]string{"obfs2"} - var ptClientProxy *url.URL = nil - +func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url.URL, factories map[string]base.ClientFactory) bool { // Launch each of the client listeners. - for _, name := range methodNames { - t := transports.Get(name) - if t == nil { - log.Errorf("no such transport is supported: %s", name) - continue - } - - f, err := t.ClientFactory(stateDir) - if err != nil { - log.Errorf("failed to get ClientFactory: %s", name) - continue - } - + for name, f := range factories { udpAddr, err := net.ResolveUDPAddr("udp", socksAddr) if err != nil { fmt.Println("Error resolving address", socksAddr) @@ -115,24 +98,24 @@ func clientHandler(target string, termMon *termmon.TermMonitor, f base.ClientFac fmt.Println("@@@ handling...") - tracker := make(ConnTracker) + tracker := make(ConnTracker) name := f.Transport().Name() fmt.Println("Transport is", name) - buf := make([]byte, 1024) + buf := make([]byte, 1024) - // Receive UDP packets and forward them over transport connections forever + // Receive UDP packets and forward them over transport connections forever for { n, addr, err := conn.ReadFromUDP(buf) - fmt.Println("Received ",string(buf[0:n]), " from ",addr) + fmt.Println("Received ", string(buf[0:n]), " from ", addr) if err != nil { - fmt.Println("Error: ",err) + fmt.Println("Error: ", err) } - fmt.Println(tracker) + fmt.Println(tracker) if state, ok := tracker[addr.String()]; ok { // There is an open transport connection, or a connection attempt is in progress. @@ -148,11 +131,11 @@ func clientHandler(target string, termMon *termmon.TermMonitor, f base.ClientFac fmt.Println("writing...") (*state.Conn).Write(buf) } - } else { + } else { // There is not an open transport connection and a connection attempt is not in progress. // Open a transport connection. - fmt.Println("Opening connection to ", target) + fmt.Println("Opening connection to ", target) openConnection(&tracker, addr.String(), target, termMon, f, proxyURI) @@ -166,7 +149,7 @@ func openConnection(tracker *ConnTracker, addr string, target string, termMon *t fmt.Println("Making dialer...") newConn := NewConnState() - (*tracker)[addr]=newConn + (*tracker)[addr] = newConn go dialConn(tracker, addr, target, f, proxyURI) } @@ -209,7 +192,7 @@ func dialConn(tracker *ConnTracker, addr string, target string, f base.ClientFac fmt.Println("Success") - (*tracker)[addr]=ConnState{&remote, false} + (*tracker)[addr] = ConnState{&remote, false} } func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, target string) bool { @@ -347,7 +330,7 @@ func serverHandler(termMon *termmon.TermMonitor, f base.ServerFactory, conn net. return } - serverAddr, err := net.ResolveUDPAddr("udp",target) + serverAddr, err := net.ResolveUDPAddr("udp", target) if err != nil { golog.Fatal(err) } @@ -362,7 +345,7 @@ func serverHandler(termMon *termmon.TermMonitor, f base.ServerFactory, conn net. golog.Fatal(err) } - fmt.Println("pumping") + fmt.Println("pumping") defer dest.Close() @@ -371,7 +354,7 @@ func serverHandler(termMon *termmon.TermMonitor, f base.ServerFactory, conn net. for { fmt.Println("reading...") // Read the incoming connection into the buffer. - _, err := io.ReadFull(remote, headerBuffer) + _, err := io.ReadFull(remote, headerBuffer) if err != nil { fmt.Println("read error") break @@ -394,8 +377,8 @@ func serverHandler(termMon *termmon.TermMonitor, f base.ServerFactory, conn net. break } - writeBuffer := append(headerBuffer, readBuffer...) + writeBuffer := append(headerBuffer, readBuffer...) dest.Write(writeBuffer) - } + } } diff --git a/modes/transparent_tcp/transparent_tcp.go b/modes/transparent_tcp/transparent_tcp.go index 30e04fc..119e797 100644 --- a/modes/transparent_tcp/transparent_tcp.go +++ b/modes/transparent_tcp/transparent_tcp.go @@ -49,31 +49,14 @@ import ( ) const ( - obfs4proxyVersion = "0.0.7-dev" - obfs4proxyLogFile = "obfs4proxy.log" - socksAddr = "127.0.0.1:1234" + socksAddr = "127.0.0.1:1234" ) var stateDir string -func ClientSetup(termMon *termmon.TermMonitor, target string) (launched bool, listeners []net.Listener) { - methodNames := [...]string{"obfs2"} - var ptClientProxy *url.URL = nil - +func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url.URL, factories map[string]base.ClientFactory) (launched bool, listeners []net.Listener) { // Launch each of the client listeners. - for _, name := range methodNames { - t := transports.Get(name) - if t == nil { - log.Errorf("no such transport is supported: %s", name) - continue - } - - f, err := t.ClientFactory(stateDir) - if err != nil { - log.Errorf("failed to get ClientFactory: %s", name) - continue - } - + for name, f := range factories { fmt.Println("Listening ", socksAddr) ln, err := net.Listen("tcp", socksAddr) if err != nil { diff --git a/modes/transparent_udp/transparent_udp.go b/modes/transparent_udp/transparent_udp.go index d7ee938..f9c2efc 100644 --- a/modes/transparent_udp/transparent_udp.go +++ b/modes/transparent_udp/transparent_udp.go @@ -30,15 +30,15 @@ package transparent_udp import ( - "io" + "bytes" + "encoding/binary" "fmt" + "io" golog "log" "net" "net/url" "strconv" "strings" - "bytes" - "encoding/binary" "golang.org/x/net/proxy" @@ -50,15 +50,13 @@ import ( ) const ( - obfs4proxyVersion = "0.0.7-dev" - obfs4proxyLogFile = "obfs4proxy.log" - socksAddr = "127.0.0.1:1234" + socksAddr = "127.0.0.1:1234" ) var stateDir string type ConnState struct { - Conn *net.Conn + Conn *net.Conn Waiting bool } @@ -68,24 +66,9 @@ func NewConnState() ConnState { type ConnTracker map[string]ConnState -func ClientSetup(termMon *termmon.TermMonitor, target string) bool { - methodNames := [...]string{"obfs2"} - var ptClientProxy *url.URL = nil - +func ClientSetup(termMon *termmon.TermMonitor, target string, ptClientProxy *url.URL, factories map[string]base.ClientFactory) bool { // Launch each of the client listeners. - for _, name := range methodNames { - t := transports.Get(name) - if t == nil { - log.Errorf("no such transport is supported: %s", name) - continue - } - - f, err := t.ClientFactory(stateDir) - if err != nil { - log.Errorf("failed to get ClientFactory: %s", name) - continue - } - + for name, f := range factories { udpAddr, err := net.ResolveUDPAddr("udp", socksAddr) if err != nil { fmt.Println("Error resolving address", socksAddr) @@ -107,7 +90,7 @@ func ClientSetup(termMon *termmon.TermMonitor, target string) bool { } func clientHandler(target string, termMon *termmon.TermMonitor, f base.ClientFactory, conn *net.UDPConn, proxyURI *url.URL) { - var length16 uint16 + var length16 uint16 defer conn.Close() termMon.OnHandlerStart() @@ -115,24 +98,24 @@ func clientHandler(target string, termMon *termmon.TermMonitor, f base.ClientFac fmt.Println("@@@ handling...") - tracker := make(ConnTracker) + tracker := make(ConnTracker) name := f.Transport().Name() fmt.Println("Transport is", name) - buf := make([]byte, 1024) + buf := make([]byte, 1024) - // Receive UDP packets and forward them over transport connections forever + // Receive UDP packets and forward them over transport connections forever for { n, addr, err := conn.ReadFromUDP(buf) - fmt.Println("Received ",string(buf[0:n]), " from ",addr) + fmt.Println("Received ", string(buf[0:n]), " from ", addr) if err != nil { - fmt.Println("Error: ",err) + fmt.Println("Error: ", err) } - fmt.Println(tracker) + fmt.Println(tracker) if state, ok := tracker[addr.String()]; ok { // There is an open transport connection, or a connection attempt is in progress. @@ -158,11 +141,11 @@ func clientHandler(target string, termMon *termmon.TermMonitor, f base.ClientFac (*state.Conn).Write(buf) } } - } else { + } else { // There is not an open transport connection and a connection attempt is not in progress. // Open a transport connection. - fmt.Println("Opening connection to ", target) + fmt.Println("Opening connection to ", target) openConnection(&tracker, addr.String(), target, termMon, f, proxyURI) @@ -176,7 +159,7 @@ func openConnection(tracker *ConnTracker, addr string, target string, termMon *t fmt.Println("Making dialer...") newConn := NewConnState() - (*tracker)[addr]=newConn + (*tracker)[addr] = newConn go dialConn(tracker, addr, target, f, proxyURI) } @@ -219,7 +202,7 @@ func dialConn(tracker *ConnTracker, addr string, target string, f base.ClientFac fmt.Println("Success") - (*tracker)[addr]=ConnState{&remote, false} + (*tracker)[addr] = ConnState{&remote, false} } func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, target string) bool { @@ -357,7 +340,7 @@ func serverHandler(termMon *termmon.TermMonitor, f base.ServerFactory, conn net. return } - serverAddr, err := net.ResolveUDPAddr("udp",target) + serverAddr, err := net.ResolveUDPAddr("udp", target) if err != nil { golog.Fatal(err) } @@ -372,7 +355,7 @@ func serverHandler(termMon *termmon.TermMonitor, f base.ServerFactory, conn net. golog.Fatal(err) } - fmt.Println("pumping") + fmt.Println("pumping") defer dest.Close() @@ -381,7 +364,7 @@ func serverHandler(termMon *termmon.TermMonitor, f base.ServerFactory, conn net. for { fmt.Println("reading...") // Read the incoming connection into the buffer. - readLen, err := io.ReadFull(remote, lengthBuffer) + readLen, err := io.ReadFull(remote, lengthBuffer) if err != nil { fmt.Println("read error") break @@ -405,5 +388,5 @@ func serverHandler(termMon *termmon.TermMonitor, f base.ServerFactory, conn net. } dest.Write(readBuffer) - } + } } diff --git a/shapeshifter-dispatcher/shapeshifter-dispatcher.go b/shapeshifter-dispatcher/shapeshifter-dispatcher.go index 7132bc2..c4a230d 100644 --- a/shapeshifter-dispatcher/shapeshifter-dispatcher.go +++ b/shapeshifter-dispatcher/shapeshifter-dispatcher.go @@ -34,23 +34,26 @@ import ( "fmt" golog "log" "net" + "net/url" "os" "path" + "strings" "syscall" "git.torproject.org/pluggable-transports/goptlib.git" "github.com/OperatorFoundation/shapeshifter-dispatcher/common/log" "github.com/OperatorFoundation/shapeshifter-dispatcher/common/pt_extras" "github.com/OperatorFoundation/shapeshifter-dispatcher/common/termmon" - "github.com/OperatorFoundation/shapeshifter-dispatcher/transports" "github.com/OperatorFoundation/shapeshifter-dispatcher/modes/pt_socks5" + "github.com/OperatorFoundation/shapeshifter-dispatcher/modes/stun_udp" "github.com/OperatorFoundation/shapeshifter-dispatcher/modes/transparent_tcp" "github.com/OperatorFoundation/shapeshifter-dispatcher/modes/transparent_udp" - "github.com/OperatorFoundation/shapeshifter-dispatcher/modes/stun_udp" - _ "github.com/OperatorFoundation/obfs4/proxy_dialers/proxy_socks4" _ "github.com/OperatorFoundation/obfs4/proxy_dialers/proxy_http" + _ "github.com/OperatorFoundation/obfs4/proxy_dialers/proxy_socks4" + "github.com/OperatorFoundation/shapeshifter-dispatcher/transports" + "github.com/OperatorFoundation/shapeshifter-transports/transports/base" ) const ( @@ -72,6 +75,15 @@ func main() { // Handle the command line arguments. _, execName := path.Split(os.Args[0]) + + flag.Usage = func() { + fmt.Fprintf(os.Stderr, "shapeshifter-dispatcher is a PT v2.0 proxy supporting multiple transports and proxy modes\n\n") + fmt.Fprintf(os.Stderr, "Usage:\n\t%s --client --state [statedir] --ptversion 2 --transports [transport1,transport2,...]\n\n", os.Args[0]) + fmt.Fprintf(os.Stderr, "Example:\n\t%s --client --state state --ptversion 2 --transports obfs2\n\n", os.Args[0]) + fmt.Fprintf(os.Stderr, "Flags:\n\n") + flag.PrintDefaults() + } + showVer := flag.Bool("version", false, "Print version and exit") logLevelStr := flag.String("logLevel", "ERROR", "Log level (ERROR/WARN/INFO/DEBUG)") enableLogging := flag.Bool("enableLogging", false, "Log to TOR_PT_STATE_LOCATION/"+dispatcherLogFile) @@ -83,6 +95,9 @@ func main() { serverMode := flag.Bool("server", false, "Enable server mode") statePath := flag.String("state", "", "Specify transport server destination address") bindAddr := flag.String("bindaddr", "", "Specify the bind address for transparent server") + ptversion := flag.String("ptversion", "", "Specify the Pluggable Transport protocol version to use") + proxy := flag.String("proxy", "", "Specify an HTTP or SOCKS4a proxy that the PT needs to use to reach the Internet") + transportsList := flag.String("transports", "", "Specify transports to enable") flag.Parse() if *showVer { @@ -99,10 +114,10 @@ func main() { launched := false isClient, err := checkIsClient(*clientMode, *serverMode) if err != nil { - golog.Fatalf("[ERROR]: %s - must be run as a managed transport", execName) + golog.Fatalf("[ERROR]: %s - either --client or --server is required, or configure using PT 2.0 environment variables", execName) } if stateDir, err = makeStateDir(*statePath); err != nil { - golog.Fatalf("[ERROR]: %s - No state directory: %s", execName, err) + golog.Fatalf("[ERROR]: %s - No state directory: Use --state or TOR_PT_STATE_LOCATION environment variable", execName) } if err = log.Init(*enableLogging, path.Join(stateDir, dispatcherLogFile), *unsafeLogging); err != nil { golog.Fatalf("[ERROR]: %s - failed to initialize logging", execName) @@ -126,7 +141,8 @@ func main() { log.Errorf("%s - transparent mode requires a target", execName) } else { fmt.Println("transparent udp client") - launched = transparent_udp.ClientSetup(termMon, *target) + factories, ptClientProxy := getClientFactories(ptversion, transportsList, proxy) + launched = transparent_udp.ClientSetup(termMon, *target, factories, ptClientProxy) } } else { log.Infof("%s - initializing server transport listeners", execName) @@ -145,7 +161,8 @@ func main() { if *target == "" { log.Errorf("%s - transparent mode requires a target", execName) } else { - launched, ptListeners = transparent_tcp.ClientSetup(termMon, *target) + factories, ptClientProxy := getClientFactories(ptversion, transportsList, proxy) + launched, ptListeners = transparent_tcp.ClientSetup(termMon, *target, factories, ptClientProxy) } } else { log.Infof("%s - initializing server transport listeners", execName) @@ -166,7 +183,8 @@ func main() { log.Errorf("%s - STUN mode requires a target", execName) } else { fmt.Println("STUN udp client") - launched = stun_udp.ClientSetup(termMon, *target) + factories, ptClientProxy := getClientFactories(ptversion, transportsList, proxy) + launched = stun_udp.ClientSetup(termMon, *target, factories, ptClientProxy) } } else { log.Infof("%s - initializing server transport listeners", execName) @@ -183,7 +201,8 @@ func main() { log.Infof("%s - initializing PT 1.0 proxy", execName) if isClient { log.Infof("%s - initializing client transport listeners", execName) - launched, ptListeners = pt_socks5.ClientSetup(termMon) + factories, ptClientProxy := getClientFactories(ptversion, transportsList, proxy) + launched, ptListeners = pt_socks5.ClientSetup(termMon, factories, ptClientProxy) } else { log.Infof("%s - initializing server transport listeners", execName) launched, ptListeners = pt_socks5.ServerSetup(termMon) @@ -221,7 +240,7 @@ func main() { termMon.Wait(true) - fmt.Println("waiting") + fmt.Println("waiting") for { // FIXME - block because termMon.Wait is not blocking } @@ -245,3 +264,53 @@ func makeStateDir(statePath string) (string, error) { return pt.MakeStateDir() } } + +func getClientFactories(ptversion *string, transportsList *string, proxy *string) (clientProxy *url.URL, factories map[string]base.ClientFactory) { + var ptClientInfo pt.ClientInfo + var err error + + // FIXME - instead of this, goptlib should be modified to accept command line flag override of EITHER ptversion or transports (or both) + if ptversion == nil || transportsList == nil { + fmt.Println("Falling back to environment variables for ptversion/transports", ptversion, transportsList) + ptClientInfo, err = pt.ClientSetup(transports.Transports()) + if err != nil { + // FIXME - print a more useful error, specifying --ptversion and --transports flags + golog.Fatal(err) + } + } else { + if *transportsList == "*" { + ptClientInfo = pt.ClientInfo{MethodNames: transports.Transports()} + } else { + ptClientInfo = pt.ClientInfo{MethodNames: strings.Split(*transportsList, ",")} + } + } + + ptClientProxy, err := pt_extras.PtGetProxy(proxy) + fmt.Println("ptclientproxy", ptClientProxy) + if err != nil { + golog.Fatal(err) + } else if ptClientProxy != nil { + pt_extras.PtProxyDone() + } + + factories = make(map[string]base.ClientFactory) + + // Launch each of the client listeners. + for _, name := range ptClientInfo.MethodNames { + t := transports.Get(name) + if t == nil { + pt.CmethodError(name, "no such transport is supported") + continue + } + + f, err := t.ClientFactory(stateDir) + if err != nil { + pt.CmethodError(name, "failed to get ClientFactory") + continue + } + + factories[name] = f + } + + return ptClientProxy, factories +} -- cgit v1.2.3