func clientHandler(f base.ClientFactory, conn net.Conn, proxyURI *url.URL) { defer conn.Close() termMon.onHandlerStart() defer termMon.onHandlerFinish() name := f.Transport().Name() // Read the client's SOCKS handshake. socksReq, err := socks5.Handshake(conn) if err != nil { log.Errorf("%s - client failed socks handshake: %s", name, err) return } addrStr := log.ElideAddr(socksReq.Target) // 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 } // 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 } remote, err := f.Dial("tcp", socksReq.Target, dialFn, args) 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)) return } if err = copyLoop(conn, remote); err != nil { log.Warnf("%s(%s) - closed connection: %s", name, addrStr, log.ElideError(err)) } else { log.Infof("%s(%s) - closed connection", name, addrStr) } return }
func clientHandler(f base.ClientFactory, conn net.Conn, proxyURI *url.URL, linkInfo LinkInfo) { defer conn.Close() termMon.onHandlerStart() defer termMon.onHandlerFinish() name := f.Transport().Name() fakeReq, err := parseClientParameters(strings.Replace(linkInfo.PtArgs, ",", ";", -1)) if err != nil { log.Errorf("%s - client failed socks handshake: %s", name, err) return } addrStr := log.ElideAddr(linkInfo.ServerAddr) // Deal with arguments. args, err := f.ParseArgs(&fakeReq) if err != nil { log.Errorf("%s(%s) - invalid arguments: %s", name, addrStr, err) return } // 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)) return } dialFn = dialer.Dial } remote, er := f.Dial("tcp", linkInfo.ServerAddr, dialFn, args) if er != nil { log.Errorf("%s(%s) - outgoing connection failed: %s", name, addrStr, log.ElideError(er)) return } defer remote.Close() if err = copyLoop(conn, remote); err != nil { log.Warnf("%s(%s) - closed connection: %s", name, addrStr, log.ElideError(err)) } else { log.Infof("%s(%s) - closed connection", name, addrStr) } return }
func serverHandler(f base.ServerFactory, conn net.Conn, info *pt.ServerInfo) { defer conn.Close() termMon.onHandlerStart() defer termMon.onHandlerFinish() name := f.Transport().Name() addrStr := log.ElideAddr(conn.RemoteAddr().String()) log.Infof("%s(%s) - new connection", name, addrStr) // Instantiate the server transport method and handshake. remote, err := f.WrapConn(conn) if err != nil { log.Warnf("%s(%s) - handshake failed: %s", name, addrStr, log.ElideError(err)) return } // Connect to the orport. orConn, err := pt.DialOr(info, conn.RemoteAddr().String(), name) if err != nil { 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)) } else { log.Infof("%s(%s) - closed connection", name, addrStr) } return }
func main() { // Initialize the termination state monitor as soon as possible. termMon = newTermMonitor() // Handle the command line arguments. _, execName := path.Split(os.Args[0]) 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/"+obfs4proxyLogFile) unsafeLogging := flag.Bool("unsafeLogging", false, "Disable the address scrubber") flag.Parse() if *showVer { fmt.Printf("%s\n", getVersion()) os.Exit(0) } if err := log.SetLogLevel(*logLevelStr); err != nil { golog.Fatalf("[ERROR]: %s - failed to set log level: %s", execName, err) } // Determine if this is a client or server, initialize the common state. var ptListeners []net.Listener launched := false isClient, err := ptIsClient() if err != nil { golog.Fatalf("[ERROR]: %s - must be run as a managed transport", execName) } if stateDir, err = pt.MakeStateDir(); err != nil { golog.Fatalf("[ERROR]: %s - No state directory: %s", execName, err) } if err = log.Init(*enableLogging, path.Join(stateDir, obfs4proxyLogFile), *unsafeLogging); err != nil { golog.Fatalf("[ERROR]: %s - failed to initialize logging", execName) } if err = transports.Init(); err != nil { log.Errorf("%s - failed to initialize transports: %s", execName, err) os.Exit(-1) } log.Noticef("%s - launched", getVersion()) // Do the managed pluggable transport protocol configuration. if isClient { log.Infof("%s - initializing client transport listeners", execName) launched, ptListeners = clientSetup() } else { log.Infof("%s - initializing server transport listeners", execName) launched, ptListeners = serverSetup() } if !launched { // Initialization failed, the client or server setup routines should // have logged, so just exit here. os.Exit(-1) } log.Infof("%s - accepting connections", execName) defer func() { log.Noticef("%s - terminated", execName) }() // At this point, the pt config protocol is finished, and incoming // connections will be processed. Wait till the parent dies // (immediate exit), a SIGTERM is received (immediate exit), // or a SIGINT is received. if sig := termMon.wait(false); sig == syscall.SIGTERM { return } // Ok, it was the first SIGINT, close all listeners, and wait till, // the parent dies, all the current connections are closed, or either // a SIGINT/SIGTERM is received, and exit. for _, ln := range ptListeners { ln.Close() } termMon.wait(true) }
func clientHandler(f base.ClientFactory, conn *pt.SocksConn, proxyURI *url.URL) { defer conn.Close() termMon.onHandlerStart() defer termMon.onHandlerFinish() name := f.Transport().Name() addrStr := log.ElideAddr(conn.Req.Target) log.Infof("%s(%s) - new connection", name, addrStr) // Deal with arguments. args, err := f.ParseArgs(&conn.Req.Args) if err != nil { log.Errorf("%s(%s) - invalid arguments: %s", name, addrStr, err) conn.Reject() return } // Obtain the proxy dialer if any, and create the outgoing TCP connection. var dialFn DialFn if proxyURI == nil { dialFn = proxy.Direct.Dial } else { // This is unlikely to happen as the proxy protocol is verified during // the configuration phase. dialer, err := proxy.FromURL(proxyURI, proxy.Direct) if err != nil { log.Errorf("%s(%s) - failed to obtain proxy dialer: %s", name, addrStr, log.ElideError(err)) conn.Reject() return } dialFn = dialer.Dial } remoteConn, err := dialFn("tcp", conn.Req.Target) // XXX: Allow UDP? if err != nil { log.Errorf("%s(%s) - outgoing connection failed: %s", name, addrStr, log.ElideError(err)) conn.Reject() return } defer remoteConn.Close() // Instantiate the client transport method, handshake, and start pushing // bytes back and forth. remote, err := f.WrapConn(remoteConn, args) if err != nil { log.Errorf("%s(%s) - handshake failed: %s", name, addrStr, log.ElideError(err)) conn.Reject() return } err = conn.Grant(remoteConn.RemoteAddr().(*net.TCPAddr)) if err != nil { log.Errorf("%s(%s) - SOCKS grant failed: %s", name, addrStr, log.ElideError(err)) return } if err = copyLoop(conn, remote); err != nil { log.Warnf("%s(%s) - closed connection: %s", name, addrStr, log.ElideError(err)) } else { log.Infof("%s(%s) - closed connection", name, addrStr) } return }