From 770bc14548a6a48ccbc8be0f0583122cf1dc6f6e Mon Sep 17 00:00:00 2001 From: Bluesaxorcist Date: Mon, 21 Oct 2019 15:16:49 -0500 Subject: added dialer to the modes and removed unneccessary code --- .gitignore | 2 + .idea/inspectionProfiles/Project_Default.xml | 20 ++ common/options.go | 39 +++- common/pt_extras/pt_extras.go | 13 +- modes/pt_socks5/pt_socks5.go | 68 +++--- modes/stun_udp/stun_udp.go | 241 ++++++++++----------- modes/transparent_tcp/transparent_tcp.go | 167 +++++++------- modes/transparent_udp/transparent_udp.go | 135 ++++++------ shapeshifter-dispatcher/shapeshifter-dispatcher.go | 12 +- state/dispatcher.log | 14 ++ transports/transports.go | 19 +- 11 files changed, 394 insertions(+), 336 deletions(-) create mode 100644 .idea/inspectionProfiles/Project_Default.xml diff --git a/.gitignore b/.gitignore index f194d88..3b8075e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ state/dispatcher.log state/dispatcher.log .idea/dictionaries/bluesaxorcist.xml state/dispatcher.log +state/dispatcher.log +.idea/inspectionProfiles/Project_Default.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..02cc456 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,20 @@ + + + + \ No newline at end of file diff --git a/common/options.go b/common/options.go index 9c73616..f0ededf 100644 --- a/common/options.go +++ b/common/options.go @@ -3,7 +3,8 @@ package options import ( "encoding/json" "errors" - "fmt" + "github.com/OperatorFoundation/shapeshifter-dispatcher/common/log" + interconv "github.com/mufti1/interconv/package" "strings" ) @@ -11,14 +12,46 @@ func ParseOptions(s string) (map[string]interface{}, error) { var result map[string]interface{} if len(s) == 0 { - return nil, errors.New("Empty options") + return map[string]interface{}{}, nil } decoder := json.NewDecoder(strings.NewReader(s)) if err := decoder.Decode(&result); err != nil { - fmt.Errorf("Error decoding JSON %q", err) + log.Errorf("Error decoding JSON %q", err) return nil, err } return result, nil } + +func ParseServerOptions(s string) (params map[string]map[string]interface{}, err error) { + result := make(map[string]map[string]interface{}) + + if len(s) == 0 { + return result, nil + } + + decoder := json.NewDecoder(strings.NewReader(s)) + if err := decoder.Decode(&result); err != nil { + log.Errorf("Error decoding JSON %q", err) + return nil, err + } + + return result, nil +} + +func CoerceToString(futureString interface{}) (*string, error) { + var result string + + switch futureString.(type) { + case string: + var icerr error + result, icerr = interconv.ParseString(futureString) + if icerr != nil { + return nil, icerr + } + return &result, nil + default: + return nil, errors.New("unable to coerce empty interface to string") + } +} \ No newline at end of file diff --git a/common/pt_extras/pt_extras.go b/common/pt_extras/pt_extras.go index a41f4f7..a04859e 100644 --- a/common/pt_extras/pt_extras.go +++ b/common/pt_extras/pt_extras.go @@ -33,6 +33,7 @@ import ( "github.com/OperatorFoundation/shapeshifter-dispatcher/common/log" "github.com/OperatorFoundation/shapeshifter-dispatcher/transports" "github.com/OperatorFoundation/shapeshifter-transports/transports/Optimizer" + "golang.org/x/net/proxy" "net" "net/url" "os" @@ -46,19 +47,19 @@ import ( func ptEnvError(msg string) error { line := []byte(fmt.Sprintf("ENV-ERROR %s\n", msg)) - pt.Stdout.Write(line) + _, _ = pt.Stdout.Write(line) return errors.New(msg) } func ptProxyError(msg string) error { line := []byte(fmt.Sprintf("PROXY-ERROR %s\n", msg)) - pt.Stdout.Write(line) + _, _ = pt.Stdout.Write(line) return errors.New(msg) } func PtProxyDone() { line := []byte("PROXY DONE\n") - pt.Stdout.Write(line) + _, _ = pt.Stdout.Write(line) } func PtIsClient() (bool, error) { @@ -174,7 +175,7 @@ func PtShouldExitOnStdinClose() bool { return os.Getenv("TOR_PT_EXIT_ON_STDIN_CLOSE") == "1" } -func ArgsToDialer(target string, name string, args map[string]interface{}) (Optimizer.Transport, error) { +func ArgsToDialer(target string, name string, args map[string]interface{}, dialer proxy.Dialer) (Optimizer.Transport, error) { switch name { //case "obfs2": // transport := obfs2.NewObfs2Transport() @@ -182,7 +183,7 @@ func ArgsToDialer(target string, name string, args map[string]interface{}) (Opti // return dialer, nil case "obfs4": //refactor starts here - transport, err := transports.ParseArgsObfs4(args, target) + transport, err := transports.ParseArgsObfs4(args, target, dialer) if err != nil { log.Errorf("Could not parse options %s", err.Error()) return nil, err @@ -198,7 +199,7 @@ func ArgsToDialer(target string, name string, args map[string]interface{}) (Opti return transport, nil } case "Optimizer": - transport, err := transports.ParseArgsOptimizer(args) + transport, err := transports.ParseArgsOptimizer(args, dialer) if err != nil { log.Errorf("Could not parse options %s", err.Error()) return nil, err diff --git a/modes/pt_socks5/pt_socks5.go b/modes/pt_socks5/pt_socks5.go index 90bf7fc..c3a8c45 100644 --- a/modes/pt_socks5/pt_socks5.go +++ b/modes/pt_socks5/pt_socks5.go @@ -37,6 +37,7 @@ import ( replicant "github.com/OperatorFoundation/shapeshifter-transports/transports/Replicant" "github.com/OperatorFoundation/shapeshifter-transports/transports/meeklite" "github.com/OperatorFoundation/shapeshifter-transports/transports/shadow" + "golang.org/x/net/proxy" "io" "net" "net/url" @@ -51,8 +52,6 @@ import ( "github.com/OperatorFoundation/shapeshifter-transports/transports/obfs4" ) -var stateDir string - func ClientSetup(termMon *termmon.TermMonitor, socksAddr string, target string, ptClientProxy *url.URL, names []string, options string) (launched bool, listeners []net.Listener) { // Launch each of the client listeners. for _, name := range names { @@ -74,14 +73,15 @@ func ClientSetup(termMon *termmon.TermMonitor, socksAddr string, target string, return } - -func clientAcceptLoop(target string, termMon *termmon.TermMonitor, name string, ln net.Listener, proxyURI *url.URL, options string) error { - defer ln.Close() +//FIXME figure out how to make this function match the other modes +func clientAcceptLoop(target string, termMon *termmon.TermMonitor, name string, ln net.Listener, proxyURI *url.URL, options string){ for { conn, err := ln.Accept() if err != nil { if e, ok := err.(net.Error); ok && !e.Temporary() { - return err + log.Errorf("serverAcceptLoop failed") + _ = ln.Close() + return } continue } @@ -90,7 +90,6 @@ func clientAcceptLoop(target string, termMon *termmon.TermMonitor, name string, } 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() @@ -120,36 +119,33 @@ func clientHandler(target string, termMon *termmon.TermMonitor, name string, con return } - var dialer func() (net.Conn, error) + var dialer proxy.Dialer // Deal with arguments. - transport, _ := pt_extras.ArgsToDialer(socksReq.Target, name, args) - dialer = transport.Dial - f := dialer + transport, _ := pt_extras.ArgsToDialer(socksReq.Target, name, args,dialer) // Obtain the proxy dialer if any, and create the outgoing TCP connection. - // dialFn := proxy.Direct.Dial - // if proxyURI != nil { - // dialer, err := proxy.FromURL(proxyURI, proxy.Direct) - // if err != nil { - // // This should basically never happen, since config protocol - // // verifies this. - // log.Errorf("%s(%s) - failed to obtain proxy dialer: %s", name, addrStr, log.ElideError(err)) - // socksReq.Reply(socks5.ReplyGeneralFailure) - // return - // } - // dialFn = dialer.Dial - // } - // - // fmt.Println("Got dialer", dialFn, proxyURI, proxy.Direct) - - remote, _ := f() + dialFn := proxy.Direct.Dial + if proxyURI != nil { + dialer, err := proxy.FromURL(proxyURI, proxy.Direct) + if err != nil { + // This should basically never happen, since config protocol + // verifies this. + log.Errorf("%s(%s) - failed to obtain proxy dialer: %s", name, addrStr, log.ElideError(err)) + socksReq.Reply(socks5.ReplyGeneralFailure) + return + } + dialFn = dialer.Dial + } + + fmt.Println("Got dialer", dialFn, proxyURI, proxy.Direct) + + remote, _ := transport.Dial() if err != nil { log.Errorf("%s(%s) - outgoing connection failed: %s", name, addrStr, log.ElideError(err)) socksReq.Reply(socks5.ErrorToReplyCode(err)) return } - defer remote.Close() err = socksReq.Reply(socks5.ReplySucceeded) if err != nil { log.Errorf("%s(%s) - SOCKS reply failed: %s", name, addrStr, log.ElideError(err)) @@ -165,7 +161,7 @@ func clientHandler(target string, termMon *termmon.TermMonitor, name string, con return } -func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, ptServerInfo pt.ServerInfo, options string) (launched bool, listeners []net.Listener) { +func ServerSetup(termMon *termmon.TermMonitor, ptServerInfo pt.ServerInfo, options string) (launched bool, listeners []net.Listener) { for _, bindaddr := range ptServerInfo.Bindaddrs { name := bindaddr.MethodName @@ -183,11 +179,12 @@ func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, ptServerIn transport := obfs2.NewObfs2Transport() listen = transport.Listen case "obfs4": + var dialer proxy.Dialer if cert, ok := args["cert"]; ok { if iatModeStr, ok2 := args["iat-mode"]; ok2 { iatMode, err := strconv.Atoi(iatModeStr[0]) if err != nil { - transport := obfs4.NewObfs4Client(cert[0], iatMode) + transport := obfs4.NewObfs4Client(cert[0], iatMode, dialer) listen = transport.Listen } else { log.Errorf("obfs4 transport bad iat-mode value: %s", iatModeStr) @@ -271,13 +268,12 @@ func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, ptServerIn return } -func serverAcceptLoop(termMon *termmon.TermMonitor, name string, ln net.Listener, info *pt.ServerInfo) error { - defer ln.Close() +func serverAcceptLoop(termMon *termmon.TermMonitor, name string, ln net.Listener, info *pt.ServerInfo){ for { conn, err := ln.Accept() if err != nil { if e, ok := err.(net.Error); ok && !e.Temporary() { - return err + return } continue } @@ -286,7 +282,6 @@ func serverAcceptLoop(termMon *termmon.TermMonitor, name string, ln net.Listener } func serverHandler(termMon *termmon.TermMonitor, name string, remote net.Conn, info *pt.ServerInfo) { - defer remote.Close() termMon.OnHandlerStart() defer termMon.OnHandlerFinish() @@ -299,7 +294,6 @@ func serverHandler(termMon *termmon.TermMonitor, name string, remote net.Conn, i log.Errorf("%s(%s) - failed to connect to ORPort: %s", name, addrStr, log.ElideError(err)) return } - defer orConn.Close() if err = copyLoop(orConn, remote); err != nil { log.Warnf("%s(%s) - closed connection: %s", name, addrStr, log.ElideError(err)) @@ -319,15 +313,11 @@ func copyLoop(a net.Conn, b net.Conn) error { go func() { defer wg.Done() - defer b.Close() - defer a.Close() _, err := io.Copy(b, a) errChan <- err }() go func() { defer wg.Done() - defer a.Close() - defer b.Close() _, err := io.Copy(a, b) errChan <- err }() diff --git a/modes/stun_udp/stun_udp.go b/modes/stun_udp/stun_udp.go index cba7132..4abe433 100644 --- a/modes/stun_udp/stun_udp.go +++ b/modes/stun_udp/stun_udp.go @@ -37,14 +37,12 @@ import ( replicant "github.com/OperatorFoundation/shapeshifter-transports/transports/Replicant" "github.com/OperatorFoundation/shapeshifter-transports/transports/meeklite" "github.com/OperatorFoundation/shapeshifter-transports/transports/shadow" + common "github.com/willscott/goturn/common" + "golang.org/x/net/proxy" "io" golog "log" "net" "net/url" - "strconv" - "strings" - - common "github.com/willscott/goturn/common" "github.com/willscott/goturn" @@ -55,8 +53,6 @@ import ( "github.com/OperatorFoundation/shapeshifter-transports/transports/obfs4" ) -var stateDir string - type ConnState struct { Conn net.Conn Waiting bool @@ -92,9 +88,11 @@ func ClientSetup(termMon *termmon.TermMonitor, socksAddr string, target string, } 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() + //defers are never called due to infinite loop + //defer termMon.OnHandlerFinish() + //defer conn.Close() fmt.Println("@@@ handling...") @@ -126,7 +124,8 @@ func clientHandler(target string, termMon *termmon.TermMonitor, name string, opt // There is an open transport connection. // Send the packet through the transport. fmt.Println("recv: write") - state.Conn.Write(buf) + //ignoring failed writes because packets can be dropped + _, _ = state.Conn.Write(buf) } } else { // There is not an open transport connection and a connection attempt is not in progress. @@ -152,19 +151,21 @@ func openConnection(tracker *ConnTracker, addr string, target string, termMon *t } 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 { - // dialer, err := proxy.FromURL(proxyURI, proxy.Direct) - // if err != nil { - // // This should basically never happen, since config protocol - // // verifies this. - // fmt.Println("failed to obtain dialer", proxyURI, proxy.Direct) - // log.Errorf("(%s) - failed to obtain proxy dialer: %s", target, log.ElideError(err)) - // return - // } - // dialFn = dialer.Dial - // } + //Obtain the proxy dialer if any, and create the outgoing TCP connection. + var dialer proxy.Dialer + dialer = proxy.Direct + if proxyURI != nil { + var err error + dialer, err = proxy.FromURL(proxyURI, proxy.Direct) + if err != nil { + // This should basically never happen, since config protocol + // verifies this. + fmt.Println("failed to obtain dialer", proxyURI, proxy.Direct) + log.Errorf("(%s) - failed to obtain proxy dialer: %s", target, log.ElideError(err)) + return + } + + } fmt.Println("Dialing....") @@ -175,7 +176,7 @@ func dialConn(tracker *ConnTracker, addr string, target string, name string, opt } // Deal with arguments. - transport, _ := pt_extras.ArgsToDialer(target, name, args) + transport, _ := pt_extras.ArgsToDialer(target, name, args, dialer) fmt.Println("Dialing ", target) remote, _ := transport.Dial() @@ -192,7 +193,7 @@ func dialConn(tracker *ConnTracker, addr string, target string, name string, opt (*tracker)[addr] = ConnState{remote, false} } -func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, ptServerInfo pt.ServerInfo, options string) (launched bool, listeners []net.Listener) { +func ServerSetup(termMon *termmon.TermMonitor, ptServerInfo pt.ServerInfo, options string, stateDir string) (launched bool, listeners []net.Listener) { fmt.Println("ServerSetup") // Launch each of the server listeners. @@ -212,26 +213,10 @@ func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, ptServerIn switch name { case "obfs2": transport := obfs2.NewObfs2Transport() - listen=transport.Listen + listen = transport.Listen case "obfs4": - if cert, ok := args["cert"]; ok { - if iatModeStr, ok2 := args["iat-mode"]; ok2 { - iatMode, err := strconv.Atoi(iatModeStr[0]) - if err != nil { - transport := obfs4.NewObfs4Client(cert[0], iatMode) - listen=transport.Listen - } else { - log.Errorf("obfs4 transport bad iat-mode 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 - } + transport := obfs4.NewObfs4Server(stateDir) + listen = transport.Listen case "meeklite": if Url, ok := args["Url"]; ok { if Front, ok2 := args["Front"]; ok2 { @@ -256,25 +241,25 @@ func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, ptServerIn } case "Dust": if idPath, ok := args["idPath"]; ok { - transport := Dust.NewDustServer(idPath[0]) - listen = transport.Listen + transport := Dust.NewDustServer(idPath[0]) + listen = transport.Listen } else { log.Errorf("Dust transport missing idPath argument: %s", args) return } - case "shadow": - if password, ok := args["password"]; ok { - if cipher, ok2 := args["cipherName"]; ok2 { - transport := shadow.NewShadowClient(password[0], cipher[0]) - listen = transport.Listen + case "shadow": + if password, ok := args["password"]; ok { + if cipher, ok2 := args["cipherName"]; ok2 { + transport := shadow.NewShadowClient(password[0], cipher[0]) + listen = transport.Listen + } else { + log.Errorf("shadow transport missing cipher argument: %s", args) + return + } } else { - log.Errorf("shadow transport missing cipher argument: %s", args) + log.Errorf("shadow transport missing password argument: %s", args) return } - } else { - log.Errorf("shadow transport missing password argument: %s", args) - return - } default: log.Errorf("Unknown transport: %s", name) @@ -294,80 +279,81 @@ func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, ptServerIn return } -func getServerBindaddrs(serverBindaddr string) ([]pt.Bindaddr, error) { - var result []pt.Bindaddr - - for _, spec := range strings.Split(serverBindaddr, ",") { - var bindaddr pt.Bindaddr - - parts := strings.SplitN(spec, "-", 2) - if len(parts) != 2 { - fmt.Println("TOR_PT_SERVER_BINDADDR: doesn't contain \"-\"", spec) - return nil, nil - } - bindaddr.MethodName = parts[0] - addr, err := resolveAddr(parts[1]) - if err != nil { - fmt.Println("TOR_PT_SERVER_BINDADDR: ", spec, err.Error()) - return nil, nil - } - bindaddr.Addr = addr - // bindaddr.Options = optionsMap[bindaddr.MethodName] - result = append(result, bindaddr) - } - - return result, nil -} +//func getServerBindaddrs(serverBindaddr string) ([]pt.Bindaddr, error) { +// var result []pt.Bindaddr +// +// for _, spec := range strings.Split(serverBindaddr, ",") { +// var bindaddr pt.Bindaddr +// +// parts := strings.SplitN(spec, "-", 2) +// if len(parts) != 2 { +// fmt.Println("TOR_PT_SERVER_BINDADDR: doesn't contain \"-\"", spec) +// return nil, nil +// } +// bindaddr.MethodName = parts[0] +// addr, err := resolveAddr(parts[1]) +// if err != nil { +// fmt.Println("TOR_PT_SERVER_BINDADDR: ", spec, err.Error()) +// return nil, nil +// } +// bindaddr.Addr = addr +// // bindaddr.Options = optionsMap[bindaddr.MethodName] +// result = append(result, bindaddr) +// } +// +// return result, nil +//} // Resolve an address string into a net.TCPAddr. We are a bit more strict than // net.ResolveTCPAddr; we don't allow an empty host or port, and the host part // must be a literal IP address. -func resolveAddr(addrStr string) (*net.TCPAddr, error) { - ipStr, portStr, err := net.SplitHostPort(addrStr) - if err != nil { - // Before the fixing of bug #7011, tor doesn't put brackets around IPv6 - // addresses. Split after the last colon, assuming it is a port - // separator, and try adding the brackets. - parts := strings.Split(addrStr, ":") - if len(parts) <= 2 { - return nil, err - } - addrStr := "[" + strings.Join(parts[:len(parts)-1], ":") + "]:" + parts[len(parts)-1] - ipStr, portStr, err = net.SplitHostPort(addrStr) - } - if err != nil { - return nil, err - } - if ipStr == "" { - return nil, net.InvalidAddrError(fmt.Sprintf("address string %q lacks a host part", addrStr)) - } - if portStr == "" { - return nil, net.InvalidAddrError(fmt.Sprintf("address string %q lacks a port part", addrStr)) - } - ip := net.ParseIP(ipStr) - if ip == nil { - return nil, net.InvalidAddrError(fmt.Sprintf("not an IP string: %q", ipStr)) - } - port, err := parsePort(portStr) - if err != nil { - return nil, err - } - return &net.TCPAddr{IP: ip, Port: port}, nil -} - -func parsePort(portStr string) (int, error) { - port, err := strconv.ParseUint(portStr, 10, 16) - return int(port), err -} - -func serverAcceptLoop(termMon *termmon.TermMonitor, name string, ln net.Listener, info *pt.ServerInfo) error { - defer ln.Close() +////func resolveAddr(addrStr string) (*net.TCPAddr, error) { +//// ipStr, portStr, err := net.SplitHostPort(addrStr) +//// if err != nil { +//// // Before the fixing of bug #7011, tor doesn't put brackets around IPv6 +//// // addresses. Split after the last colon, assuming it is a port +//// // separator, and try adding the brackets. +//// parts := strings.Split(addrStr, ":") +//// if len(parts) <= 2 { +//// return nil, err +//// } +//// addrStr := "[" + strings.Join(parts[:len(parts)-1], ":") + "]:" + parts[len(parts)-1] +//// ipStr, portStr, err = net.SplitHostPort(addrStr) +//// } +//// if err != nil { +//// return nil, err +//// } +//// if ipStr == "" { +//// return nil, net.InvalidAddrError(fmt.Sprintf("address string %q lacks a host part", addrStr)) +//// } +//// if portStr == "" { +//// return nil, net.InvalidAddrError(fmt.Sprintf("address string %q lacks a port part", addrStr)) +//// } +//// ip := net.ParseIP(ipStr) +//// if ip == nil { +//// return nil, net.InvalidAddrError(fmt.Sprintf("not an IP string: %q", ipStr)) +//// } +//// port, err := parsePort(portStr) +//// if err != nil { +//// return nil, err +//// } +//// return &net.TCPAddr{IP: ip, Port: port}, nil +////} +// +//func parsePort(portStr string) (int, error) { +// port, err := strconv.ParseUint(portStr, 10, 16) +// return int(port), err +//} + +func serverAcceptLoop(termMon *termmon.TermMonitor, name string, ln net.Listener, info *pt.ServerInfo){ for { conn, err := ln.Accept() fmt.Println("accepted") if err != nil { if e, ok := err.(net.Error); ok && !e.Temporary() { - return err + log.Errorf("serverAcceptLoop failed") + _ = ln.Close() + return } continue } @@ -378,9 +364,7 @@ func serverAcceptLoop(termMon *termmon.TermMonitor, name string, ln net.Listener func serverHandler(termMon *termmon.TermMonitor, name string, remote net.Conn, info *pt.ServerInfo) { var header *common.Message - defer remote.Close() termMon.OnHandlerStart() - defer termMon.OnHandlerFinish() addrStr := log.ElideAddr(remote.RemoteAddr().String()) fmt.Println("### handling", name) @@ -388,16 +372,22 @@ func serverHandler(termMon *termmon.TermMonitor, name string, remote net.Conn, i serverAddr, err := net.ResolveUDPAddr("udp", info.OrAddr.String()) if err != nil { + _ = remote.Close() + termMon.OnHandlerFinish() golog.Fatal(err) } localAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0") if err != nil { + _ = remote.Close() + termMon.OnHandlerFinish() golog.Fatal(err) } dest, err := net.DialUDP("udp", localAddr, serverAddr) if err != nil { + _ = remote.Close() + termMon.OnHandlerFinish() golog.Fatal(err) } @@ -435,6 +425,9 @@ func serverHandler(termMon *termmon.TermMonitor, name string, remote net.Conn, i writeBuffer := append(headerBuffer, readBuffer...) - dest.Write(writeBuffer) + _, _ = dest.Write(writeBuffer) } -} \ No newline at end of file + + _ = remote.Close() + termMon.OnHandlerFinish() +} diff --git a/modes/transparent_tcp/transparent_tcp.go b/modes/transparent_tcp/transparent_tcp.go index 8fc2f08..0bdfe75 100644 --- a/modes/transparent_tcp/transparent_tcp.go +++ b/modes/transparent_tcp/transparent_tcp.go @@ -30,16 +30,16 @@ package transparent_tcp import ( + "fmt" options2 "github.com/OperatorFoundation/shapeshifter-dispatcher/common" - "github.com/OperatorFoundation/shapeshifter-dispatcher/common/pt_extras" "github.com/OperatorFoundation/shapeshifter-transports/transports/Dust" "github.com/OperatorFoundation/shapeshifter-transports/transports/meeklite" "github.com/OperatorFoundation/shapeshifter-transports/transports/obfs2" + "golang.org/x/net/proxy" "io" "net" "net/url" - "strings" "sync" "github.com/OperatorFoundation/shapeshifter-dispatcher/common/log" @@ -50,8 +50,6 @@ import ( "github.com/OperatorFoundation/shapeshifter-transports/transports/shadow" ) -var stateDir string - func ClientSetup(termMon *termmon.TermMonitor, socksAddr string, target string, ptClientProxy *url.URL, names []string, options string) (launched bool, listeners []net.Listener) { // Launch each of the client listeners. for _, name := range names { @@ -73,7 +71,6 @@ func ClientSetup(termMon *termmon.TermMonitor, socksAddr string, target string, } func clientAcceptLoop(target string, termMon *termmon.TermMonitor, name string, options string, ln net.Listener, proxyURI *url.URL) { - defer ln.Close() for { conn, err := ln.Accept() if err != nil { @@ -89,11 +86,23 @@ func clientAcceptLoop(target string, termMon *termmon.TermMonitor, name string, } 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() - var dialer func() (net.Conn, error) + var dialer proxy.Dialer + dialer = proxy.Direct + if proxyURI != nil { + var err error + dialer, err = proxy.FromURL(proxyURI, proxy.Direct) + if err != nil { + // This should basically never happen, since config protocol + // verifies this. + fmt.Println("failed to obtain dialer", proxyURI, proxy.Direct) + log.Errorf("(%s) - failed to obtain proxy dialer: %s", target, log.ElideError(err)) + return + } + + } //this is where the refactoring begins args, argsErr := options2.ParseOptions(options) if argsErr != nil { @@ -103,39 +112,10 @@ func clientHandler(target string, termMon *termmon.TermMonitor, name string, opt // Deal with arguments. - transport, dialerErr := pt_extras.ArgsToDialer(target, name, args) - if dialerErr != nil { - log.Errorf("Error parsing transport-specific options: %s (%s)", args, dialerErr) - return - } - dialer = transport.Dial - f := dialer - - // Obtain the proxy dialer if any, and create the outgoing TCP connection. - // dialFn := proxy.Direct.Dial - // if proxyURI != nil { - // dialer, err := proxy.FromURL(proxyURI, proxy.Direct) - // if err != nil { - // // This should basically never happen, since config protocol - // // verifies this. - // log.Errorf("%s(%s) - failed to obtain proxy dialer: %s", name, target, log.ElideError(err)) - // return - // } - // dialFn = dialer.Dial - // } - - // FIXME - use dialFn if a proxy is needed to connect to the network - remote, err := f() - // if err != nil { - // log.Errorf("%s(%s) - outgoing connection failed: %s", name, target, log.ElideError(err)) - // return - // } - if err != nil { - log.Errorf("outgoing connection failed %q", target) - return - } + transport, _ := pt_extras.ArgsToDialer(target, name, args, dialer) - defer remote.Close() + fmt.Println("Dialing ", target) + remote, _ := transport.Dial() if err := copyLoop(conn, remote); err != nil { log.Warnf("%s(%s) - closed connection: %s", name, target, log.ElideError(err)) @@ -144,14 +124,14 @@ func clientHandler(target string, termMon *termmon.TermMonitor, name string, opt } } -func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, ptServerInfo pt.ServerInfo, statedir string, options string) (launched bool, listeners []net.Listener) { +func ServerSetup(termMon *termmon.TermMonitor, ptServerInfo pt.ServerInfo, statedir string, options string) (launched bool, listeners []net.Listener) { // Launch each of the server listeners. for _, bindaddr := range ptServerInfo.Bindaddrs { name := bindaddr.MethodName var listen func(address string) net.Listener - args, argsErr := pt.ParsePT2ServerParameters(options) + args, argsErr := options2.ParseServerOptions(options) if argsErr != nil { log.Errorf("Error parsing transport options: %s", options) return @@ -188,46 +168,73 @@ func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, ptServerIn return false, nil } - idPath, ok := shargs.Get("Url") + untypedIdPath, ok := shargs["Url"] if !ok { return false, nil } - transport := Dust.NewDustServer(idPath) + idPath, err := options2.CoerceToString(untypedIdPath) + if err != nil { + log.Errorf("could not coerce Dust Url to string") + return false, nil + } + transport := Dust.NewDustServer(*idPath) listen = transport.Listen case "meeklite": - shargs, aok := args["meeklite"] + args, aok := args["meeklite"] if !aok { return false, nil } - Url, ok := shargs.Get("Url") + untypedUrl, ok := args["Url"] if !ok { return false, nil } - Front, ok2 := shargs.Get("Front") - if !ok2 { + + Url, err := options2.CoerceToString(untypedUrl) + if err != nil { + log.Errorf("could not coerce meeklite Url to string") + } + + untypedFront, ok := args["Front"] + if !ok { return false, nil } - transport := meeklite.NewMeekTransportWithFront(Url, Front) + + Front, err := options2.CoerceToString(untypedFront) + if err != nil { + log.Errorf("could not coerce meeklite Front to string") + } + transport := meeklite.NewMeekTransportWithFront(*Url, *Front) listen = transport.Listen case "shadow": - shargs, aok := args["shadow"] + args, aok := args["shadow"] if !aok { return false, nil } - password, ok := shargs.Get("password") + untypedPassword, ok := args["password"] if !ok { return false, nil } - cipherName, ok2 := shargs.Get("cipherName") - if !ok2 { + Password, err := options2.CoerceToString(untypedPassword) + if err != nil { + log.Errorf("could not coerce meeklite Url to string") + } + + untypedCertString, ok := args["Url"] + if !ok { return false, nil } - transport := shadow.NewShadowServer(password, cipherName) + + certString, err := options2.CoerceToString(untypedCertString) + if err != nil { + log.Errorf("could not coerce meeklite Url to string") + } + + transport := shadow.NewShadowServer(*Password, *certString) listen = transport.Listen default: log.Errorf("Unknown transport: %s", name) @@ -249,33 +256,32 @@ func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, ptServerIn return } -func getServerBindaddrs(serverBindaddr string) ([]pt.Bindaddr, error) { - var result []pt.Bindaddr - - for _, spec := range strings.Split(serverBindaddr, ",") { - var bindaddr pt.Bindaddr - - parts := strings.SplitN(spec, "-", 2) - if len(parts) != 2 { - log.Errorf("TOR_PT_SERVER_BINDADDR: doesn't contain \"-\" %q", spec) - return nil, nil - } - bindaddr.MethodName = parts[0] - addr, err := pt.ResolveAddr(parts[1]) - if err != nil { - log.Errorf("TOR_PT_SERVER_BINDADDR: %q %q", spec, err.Error()) - return nil, nil - } - bindaddr.Addr = addr - // bindaddr.Options = optionsMap[bindaddr.MethodName] - result = append(result, bindaddr) - } - - return result, nil -} +//func getServerBindaddrs(serverBindaddr string) ([]pt.Bindaddr, error) { +// var result []pt.Bindaddr +// +// for _, spec := range strings.Split(serverBindaddr, ",") { +// var bindaddr pt.Bindaddr +// +// parts := strings.SplitN(spec, "-", 2) +// if len(parts) != 2 { +// log.Errorf("TOR_PT_SERVER_BINDADDR: doesn't contain \"-\" %q", spec) +// return nil, nil +// } +// bindaddr.MethodName = parts[0] +// addr, err := pt.ResolveAddr(parts[1]) +// if err != nil { +// log.Errorf("TOR_PT_SERVER_BINDADDR: %q %q", spec, err.Error()) +// return nil, nil +// } +// bindaddr.Addr = addr +// // bindaddr.Options = optionsMap[bindaddr.MethodName] +// result = append(result, bindaddr) +// } +// +// return result, nil +//} func serverAcceptLoop(termMon *termmon.TermMonitor, name string, ln net.Listener, info *pt.ServerInfo) { - defer ln.Close() for { conn, err := ln.Accept() if err != nil { @@ -300,7 +306,6 @@ func serverHandler(termMon *termmon.TermMonitor, name string, remote net.Conn, i log.Errorf("%s - failed to connect to ORPort: %s", name, log.ElideError(err)) return } - defer orConn.Close() if err = copyLoop(orConn, remote); err != nil { log.Warnf("%s - closed connection: %s", name, log.ElideError(err)) @@ -318,15 +323,11 @@ func copyLoop(a net.Conn, b net.Conn) error { go func() { defer wg.Done() - defer b.Close() - defer a.Close() _, err := io.Copy(b, a) errChan <- err }() go func() { defer wg.Done() - defer a.Close() - defer b.Close() _, err := io.Copy(a, b) errChan <- err }() diff --git a/modes/transparent_udp/transparent_udp.go b/modes/transparent_udp/transparent_udp.go index d69059d..64bc711 100644 --- a/modes/transparent_udp/transparent_udp.go +++ b/modes/transparent_udp/transparent_udp.go @@ -34,23 +34,22 @@ import ( "encoding/binary" "fmt" options2 "github.com/OperatorFoundation/shapeshifter-dispatcher/common" + "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-ipc" "github.com/OperatorFoundation/shapeshifter-transports/transports/Dust" replicant "github.com/OperatorFoundation/shapeshifter-transports/transports/Replicant" "github.com/OperatorFoundation/shapeshifter-transports/transports/meeklite" + "github.com/OperatorFoundation/shapeshifter-transports/transports/obfs2" + "github.com/OperatorFoundation/shapeshifter-transports/transports/obfs4" "github.com/OperatorFoundation/shapeshifter-transports/transports/shadow" + "golang.org/x/net/proxy" "io" golog "log" "net" "net/url" "strconv" - "strings" - - "github.com/OperatorFoundation/shapeshifter-dispatcher/common/log" - "github.com/OperatorFoundation/shapeshifter-dispatcher/common/termmon" - "github.com/OperatorFoundation/shapeshifter-ipc" - "github.com/OperatorFoundation/shapeshifter-transports/transports/obfs2" - "github.com/OperatorFoundation/shapeshifter-transports/transports/obfs4" //"github.com/OperatorFoundation/shapeshifter-transports/transports/Optimizer" //"github.com/OperatorFoundation/shapeshifter-transports/transports/shadow" ) @@ -139,7 +138,7 @@ func clientHandler(target string, termMon *termmon.TermMonitor, name string, opt if writErr != nil { continue } else { - _, writeBufErr :=state.Conn.Write(buf) + _, writeBufErr := state.Conn.Write(buf) if writeBufErr != nil { _ = state.Conn.Close() _ = conn.Close() @@ -173,18 +172,20 @@ func openConnection(tracker *ConnTracker, addr string, target string, termMon *t 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 { - // dialer, err := proxy.FromURL(proxyURI, proxy.Direct) - // if err != nil { - // // This should basically never happen, since config protocol - // // verifies this. - // fmt.Println("failed to obtain dialer", proxyURI, proxy.Direct) - // log.Errorf("(%s) - failed to obtain proxy dialer: %s", target, log.ElideError(err)) - // return - // } - // dialFn = dialer.Dial - // } + var dialer proxy.Dialer + dialer = proxy.Direct + if proxyURI != nil { + var err error + dialer, err = proxy.FromURL(proxyURI, proxy.Direct) + if err != nil { + // This should basically never happen, since config protocol + // verifies this. + fmt.Println("failed to obtain dialer", proxyURI, proxy.Direct) + log.Errorf("(%s) - failed to obtain proxy dialer: %s", target, log.ElideError(err)) + return + } + + } fmt.Println("Dialing....") @@ -193,9 +194,8 @@ func dialConn(tracker *ConnTracker, addr string, target string, name string, opt log.Errorf("Error parsing transport options: %s", options) return } - // Deal with arguments. - transport, _ := pt_extras.ArgsToDialer(target, name, args) + transport, _ := pt_extras.ArgsToDialer(target, name, args, dialer) fmt.Println("Dialing ", target) remote, _ := transport.Dial() // if err != nil { @@ -211,7 +211,7 @@ func dialConn(tracker *ConnTracker, addr string, target string, name string, opt (*tracker)[addr] = ConnState{remote, false} } -func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, ptServerInfo pt.ServerInfo, options string) (launched bool, listeners []net.Listener) { +func ServerSetup(termMon *termmon.TermMonitor, ptServerInfo pt.ServerInfo, options string) (launched bool, listeners []net.Listener) { fmt.Println("ServerSetup") // Launch each of the server listeners. @@ -233,11 +233,12 @@ func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, ptServerIn transport := obfs2.NewObfs2Transport() listen = transport.Listen case "obfs4": + var dialer proxy.Dialer if cert, ok := args["cert"]; ok { if iatModeStr, ok2 := args["iat-mode"]; ok2 { iatMode, err := strconv.Atoi(iatModeStr[0]) if err != nil { - transport := obfs4.NewObfs4Client(cert[0], iatMode) + transport := obfs4.NewObfs4Client(cert[0], iatMode, dialer) listen = transport.Listen } else { log.Errorf("obfs4 transport bad iat-mode value: %s", iatModeStr) @@ -317,52 +318,53 @@ func ServerSetup(termMon *termmon.TermMonitor, bindaddrString string, ptServerIn // Resolve an address string into a net.TCPAddr. We are a bit more strict than // net.ResolveTCPAddr; we don't allow an empty host or port, and the host part // must be a literal IP address. -func resolveAddr(addrStr string) (*net.TCPAddr, error) { - ipStr, portStr, err := net.SplitHostPort(addrStr) - if err != nil { - // Before the fixing of bug #7011, tor doesn't put brackets around IPv6 - // addresses. Split after the last colon, assuming it is a port - // separator, and try adding the brackets. - parts := strings.Split(addrStr, ":") - if len(parts) <= 2 { - return nil, err - } - addrStr := "[" + strings.Join(parts[:len(parts)-1], ":") + "]:" + parts[len(parts)-1] - ipStr, portStr, err = net.SplitHostPort(addrStr) - } - if err != nil { - return nil, err - } - if ipStr == "" { - return nil, net.InvalidAddrError(fmt.Sprintf("address string %q lacks a host part", addrStr)) - } - if portStr == "" { - return nil, net.InvalidAddrError(fmt.Sprintf("address string %q lacks a port part", addrStr)) - } - ip := net.ParseIP(ipStr) - if ip == nil { - return nil, net.InvalidAddrError(fmt.Sprintf("not an IP string: %q", ipStr)) - } - port, err := parsePort(portStr) - if err != nil { - return nil, err - } - return &net.TCPAddr{IP: ip, Port: port}, nil -} - -func parsePort(portStr string) (int, error) { - port, err := strconv.ParseUint(portStr, 10, 16) - return int(port), err -} - -func serverAcceptLoop(termMon *termmon.TermMonitor, name string, ln net.Listener, info *pt.ServerInfo) error { - defer ln.Close() +//func resolveAddr(addrStr string) (*net.TCPAddr, error) { +// ipStr, portStr, err := net.SplitHostPort(addrStr) +// if err != nil { +// // Before the fixing of bug #7011, tor doesn't put brackets around IPv6 +// // addresses. Split after the last colon, assuming it is a port +// // separator, and try adding the brackets. +// parts := strings.Split(addrStr, ":") +// if len(parts) <= 2 { +// return nil, err +// } +// addrStr := "[" + strings.Join(parts[:len(parts)-1], ":") + "]:" + parts[len(parts)-1] +// ipStr, portStr, err = net.SplitHostPort(addrStr) +// } +// if err != nil { +// return nil, err +// } +// if ipStr == "" { +// return nil, net.InvalidAddrError(fmt.Sprintf("address string %q lacks a host part", addrStr)) +// } +// if portStr == "" { +// return nil, net.InvalidAddrError(fmt.Sprintf("address string %q lacks a port part", addrStr)) +// } +// ip := net.ParseIP(ipStr) +// if ip == nil { +// return nil, net.InvalidAddrError(fmt.Sprintf("not an IP string: %q", ipStr)) +// } +// port, err := parsePort(portStr) +// if err != nil { +// return nil, err +// } +// return &net.TCPAddr{IP: ip, Port: port}, nil +//} +// +//func parsePort(portStr string) (int, error) { +// port, err := strconv.ParseUint(portStr, 10, 16) +// return int(port), err +//} + +func serverAcceptLoop(termMon *termmon.TermMonitor, name string, ln net.Listener, info *pt.ServerInfo) { for { conn, err := ln.Accept() fmt.Println("accepted") if err != nil { if e, ok := err.(net.Error); ok && !e.Temporary() { - return err + log.Errorf("serverAcceptLoop failed") + _ = ln.Close() + return } continue } @@ -373,7 +375,6 @@ func serverAcceptLoop(termMon *termmon.TermMonitor, name string, ln net.Listener func serverHandler(termMon *termmon.TermMonitor, name string, remote net.Conn, info *pt.ServerInfo) { var length16 uint16 - defer remote.Close() termMon.OnHandlerStart() defer termMon.OnHandlerFinish() @@ -428,6 +429,6 @@ func serverHandler(termMon *termmon.TermMonitor, name string, remote net.Conn, i break } - dest.Write(readBuffer) + _, _ = dest.Write(readBuffer) } } diff --git a/shapeshifter-dispatcher/shapeshifter-dispatcher.go b/shapeshifter-dispatcher/shapeshifter-dispatcher.go index d7f49e4..a4412c9 100644 --- a/shapeshifter-dispatcher/shapeshifter-dispatcher.go +++ b/shapeshifter-dispatcher/shapeshifter-dispatcher.go @@ -188,7 +188,7 @@ func main() { // launched = transparent_udp.ServerSetup(termMon, *bindAddr, *target) ptServerInfo := getServerInfo(ptversion, bindAddr, options, transportsList, orport, extorport, authcookie) - launched, serverListeners = transparent_udp.ServerSetup(termMon, *bindAddr, ptServerInfo, *options) + launched, serverListeners = transparent_udp.ServerSetup(termMon, ptServerInfo, *options) } } } else { @@ -208,7 +208,7 @@ func main() { log.Errorf("%s - transparent mode requires a bindaddr", execName) } else { ptServerInfo := getServerInfo(ptversion, bindAddr, options, transportsList, orport, extorport, authcookie) - launched, serverListeners = transparent_tcp.ServerSetup(termMon, *bindAddr, ptServerInfo, *statePath, *options) + launched, serverListeners = transparent_tcp.ServerSetup(termMon, ptServerInfo, *statePath, *options) } } } @@ -230,7 +230,7 @@ func main() { log.Errorf("%s - STUN mode requires a bindaddr", execName) } else { ptServerInfo := getServerInfo(ptversion, bindAddr, options, transportsList, orport, extorport, authcookie) - launched, serverListeners = stun_udp.ServerSetup(termMon, *bindAddr, ptServerInfo, *options) + launched, serverListeners = stun_udp.ServerSetup(termMon, ptServerInfo, *options, stateDir) } } } else { @@ -244,7 +244,7 @@ func main() { } else { log.Infof("%s - initializing server transport listeners", execName) ptServerInfo := getServerInfo(ptversion, bindAddr, options, transportsList, orport, extorport, authcookie) - launched, serverListeners = pt_socks5.ServerSetup(termMon, *bindAddr, ptServerInfo, *options) + launched, serverListeners = pt_socks5.ServerSetup(termMon, ptServerInfo, *options) } } } @@ -272,11 +272,11 @@ func main() { // the parent dies, all the current connections are closed, or either // a SIGINT/SIGTERM is received, and exit. for _, ln := range clientListeners { - ln.Close() + _ = ln.Close() } for _, ln := range serverListeners { - ln.Close() + _ = ln.Close() } termMon.Wait(true) diff --git a/state/dispatcher.log b/state/dispatcher.log index 8c0f59c..abba35d 100644 --- a/state/dispatcher.log +++ b/state/dispatcher.log @@ -325,3 +325,17 @@ 2019/10/13 21:11:57 [INFO]: ___go_build_github_com_OperatorFoundation_shapeshifter_dispatcher_shapeshifter_dispatcher - initializing client transport listeners 2019/10/13 21:11:57 [INFO]: Optimizer - registered listener: 127.0.0.1:1444 2019/10/13 21:11:57 [INFO]: ___go_build_github_com_OperatorFoundation_shapeshifter_dispatcher_shapeshifter_dispatcher - accepting connections +2019/10/21 12:43:57 [ERROR]: Fatal listener error: accept tcp 127.0.0.1:1444: use of closed network connection +2019/10/21 12:44:28 [NOTICE]: dispatcher-0.0.7-dev - launched +2019/10/21 12:44:28 [INFO]: ___go_build_github_com_OperatorFoundation_shapeshifter_dispatcher_shapeshifter_dispatcher - initializing transparent proxy +2019/10/21 12:44:28 [INFO]: ___go_build_github_com_OperatorFoundation_shapeshifter_dispatcher_shapeshifter_dispatcher - initializing TCP transparent proxy +2019/10/21 12:44:28 [INFO]: ___go_build_github_com_OperatorFoundation_shapeshifter_dispatcher_shapeshifter_dispatcher - initializing client transport listeners +2019/10/21 12:44:28 [INFO]: Optimizer - registered listener: 127.0.0.1:1444 +2019/10/21 12:44:28 [INFO]: ___go_build_github_com_OperatorFoundation_shapeshifter_dispatcher_shapeshifter_dispatcher - accepting connections +2019/10/21 15:13:08 [ERROR]: Fatal listener error: accept tcp 127.0.0.1:1444: use of closed network connection +2019/10/21 15:13:16 [NOTICE]: dispatcher-0.0.7-dev - launched +2019/10/21 15:13:16 [INFO]: ___go_build_github_com_OperatorFoundation_shapeshifter_dispatcher_shapeshifter_dispatcher - initializing transparent proxy +2019/10/21 15:13:16 [INFO]: ___go_build_github_com_OperatorFoundation_shapeshifter_dispatcher_shapeshifter_dispatcher - initializing TCP transparent proxy +2019/10/21 15:13:16 [INFO]: ___go_build_github_com_OperatorFoundation_shapeshifter_dispatcher_shapeshifter_dispatcher - initializing client transport listeners +2019/10/21 15:13:16 [INFO]: Optimizer - registered listener: 127.0.0.1:1444 +2019/10/21 15:13:16 [INFO]: ___go_build_github_com_OperatorFoundation_shapeshifter_dispatcher_shapeshifter_dispatcher - accepting connections diff --git a/transports/transports.go b/transports/transports.go index 5cfd468..021b176 100644 --- a/transports/transports.go +++ b/transports/transports.go @@ -42,6 +42,7 @@ import ( "github.com/OperatorFoundation/shapeshifter-transports/transports/obfs4" "github.com/OperatorFoundation/shapeshifter-transports/transports/shadow" "github.com/mufti1/interconv/package" + "golang.org/x/net/proxy" gourl "net/url" "strconv" ) @@ -51,7 +52,7 @@ func Transports() []string { return []string{"obfs2", "shadow", "obfs4", "Optimizer"} } -func ParseArgsObfs4(args map[string]interface{}, target string) (*obfs4.Transport, error) { +func ParseArgsObfs4(args map[string]interface{}, target string, dialer proxy.Dialer) (*obfs4.Transport, error) { var cert string var iatMode int @@ -140,6 +141,7 @@ func ParseArgsObfs4(args map[string]interface{}, target string) (*obfs4.Transpor CertString: cert, IatMode: iatMode, Address: target, + Dialer: dialer, } return &transport, nil @@ -687,7 +689,7 @@ func ParseArgsMeeklite(args map[string]interface{}, target string) (*meeklite.Tr return &transport, nil } -func ParseArgsOptimizer(args map[string]interface{}) (*Optimizer.Client, error) { +func ParseArgsOptimizer(args map[string]interface{}, dialer proxy.Dialer) (*Optimizer.Client, error) { var transports []Optimizer.Transport var strategy Optimizer.Strategy @@ -701,7 +703,7 @@ func ParseArgsOptimizer(args map[string]interface{}) (*Optimizer.Client, error) otcs := untypedTransports.([]interface{}) var parseErr error - transports, parseErr = parseTransports(otcs) + transports, parseErr = parseTransports(otcs, dialer) if parseErr != nil { return nil, errors.New("could not parse transports") } @@ -758,13 +760,13 @@ func parseStrategy(strategyString string, transports []Optimizer.Transport) (Opt } } -func parseTransports(otcs []interface{}) ([]Optimizer.Transport, error) { +func parseTransports(otcs []interface{}, dialer proxy.Dialer) ([]Optimizer.Transport, error) { transports := make([]Optimizer.Transport, len(otcs)) for index, untypedOtc := range otcs { switch untypedOtc.(type) { case map[string]interface{}: otc := untypedOtc.(map[string]interface{}) - transport, err := parsedTransport(otc) + transport, err := parsedTransport(otc, dialer) if err != nil { return nil, errors.New("transport could not parse config") //this error sucks and is uninformative @@ -778,10 +780,11 @@ func parseTransports(otcs []interface{}) ([]Optimizer.Transport, error) { return transports, nil } -func parsedTransport(otc map[string]interface{}) (Optimizer.Transport, error) { +func parsedTransport(otc map[string]interface{}, dialer proxy.Dialer) (Optimizer.Transport, error) { var address string var name string var config map[string]interface{} + //start by parsing the address untypedAddress, ok := otc["address"] if !ok { @@ -841,7 +844,7 @@ func parsedTransport(otc map[string]interface{}) (Optimizer.Transport, error) { } return shadowTransport, nil case "obfs4": - obfs4Transport, parseErr := ParseArgsObfs4(config, address) + obfs4Transport, parseErr := ParseArgsObfs4(config, address, dialer) if parseErr != nil { return nil, errors.New("could not parse obfs4 Args") } @@ -865,7 +868,7 @@ func parsedTransport(otc map[string]interface{}) (Optimizer.Transport, error) { } return replicantTransport, nil case "Optimizer": - optimizerTransport, parseErr := ParseArgsOptimizer(config) + optimizerTransport, parseErr := ParseArgsOptimizer(config, dialer) if parseErr != nil { return nil, errors.New("could not parse Optimizer Args") } -- cgit v1.2.3