From 93cb566c11b9c968677786bc6b5cf01ac06931e6 Mon Sep 17 00:00:00 2001 From: Brandon Wiley Date: Tue, 15 Nov 2016 14:51:32 -0600 Subject: Renamed obfs4proxy to shapeshifter-dispatcher --- shapeshifter-dispatcher/shapeshifter-dispatcher.go | 247 +++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 shapeshifter-dispatcher/shapeshifter-dispatcher.go diff --git a/shapeshifter-dispatcher/shapeshifter-dispatcher.go b/shapeshifter-dispatcher/shapeshifter-dispatcher.go new file mode 100644 index 0000000..d11a39b --- /dev/null +++ b/shapeshifter-dispatcher/shapeshifter-dispatcher.go @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2014-2015, Yawning Angel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +// Go language Tor Pluggable Transport suite. Works only as a managed +// client/server. +package main + +import ( + "flag" + "fmt" + golog "log" + "net" + "os" + "path" + "syscall" + + "git.torproject.org/pluggable-transports/goptlib.git" + "github.com/OperatorFoundation/obfs4/common/log" + "github.com/OperatorFoundation/obfs4/common/pt_extras" + "github.com/OperatorFoundation/obfs4/common/termmon" + "github.com/OperatorFoundation/obfs4/transports" + + "github.com/OperatorFoundation/obfs4/modes/pt_socks5" + "github.com/OperatorFoundation/obfs4/modes/transparent_tcp" + "github.com/OperatorFoundation/obfs4/modes/transparent_udp" + "github.com/OperatorFoundation/obfs4/modes/stun_udp" + + _ "github.com/OperatorFoundation/obfs4/proxy_dialers/proxy_socks4" + _ "github.com/OperatorFoundation/obfs4/proxy_dialers/proxy_http" +) + +const ( + dispatcherVersion = "0.0.7-dev" + dispatcherLogFile = "dispatcher.log" + socksAddr = "127.0.0.1:0" +) + +var stateDir string +var termMon *termmon.TermMonitor + +func getVersion() string { + return fmt.Sprintf("dispatcher-%s", dispatcherVersion) +} + +func main() { + // Initialize the termination state monitor as soon as possible. + termMon = 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/"+dispatcherLogFile) + unsafeLogging := flag.Bool("unsafeLogging", false, "Disable the address scrubber") + transparent := flag.Bool("transparent", false, "Enable transparent proxy mode") + udp := flag.Bool("udp", false, "Enable UDP proxy mode") + target := flag.String("target", "", "Specify transport server destination address") + clientMode := flag.Bool("client", false, "Enable client mode") + 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") + flag.Parse() + + if *showVer { + fmt.Printf("%s\n", getVersion()) + os.Exit(0) + } + if err := log.SetLogLevel(*logLevelStr); err != nil { + fmt.Println("failed to set log level") + 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 := checkIsClient(*clientMode, *serverMode) + if err != nil { + golog.Fatalf("[ERROR]: %s - must be run as a managed transport", execName) + } + if stateDir, err = makeStateDir(*statePath); err != nil { + golog.Fatalf("[ERROR]: %s - No state directory: %s", execName, err) + } + if err = log.Init(*enableLogging, path.Join(stateDir, dispatcherLogFile), *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()) + fmt.Println("launching") + + if *transparent { + // Do the transparent proxy configuration. + log.Infof("%s - initializing transparent proxy", execName) + if *udp { + log.Infof("%s - initializing UDP transparent proxy", execName) + if isClient { + log.Infof("%s - initializing client transport listeners", execName) + if *target == "" { + log.Errorf("%s - transparent mode requires a target", execName) + } else { + fmt.Println("transparent udp client") + launched = transparent_udp.ClientSetup(termMon, *target) + } + } else { + log.Infof("%s - initializing server transport listeners", execName) + if *bindAddr == "" { + fmt.Println("%s - transparent mode requires a bindaddr", execName) + } else { + fmt.Println("transparent udp server") + launched = transparent_udp.ServerSetup(termMon, *bindAddr, *target) + fmt.Println("launched", launched, ptListeners) + } + } + } else { + log.Infof("%s - initializing TCP transparent proxy", execName) + if isClient { + log.Infof("%s - initializing client transport listeners", execName) + if *target == "" { + log.Errorf("%s - transparent mode requires a target", execName) + } else { + launched, ptListeners = transparent_tcp.ClientSetup(termMon, *target) + } + } else { + log.Infof("%s - initializing server transport listeners", execName) + if *bindAddr == "" { + fmt.Println("%s - transparent mode requires a bindaddr", execName) + } else { + launched, ptListeners = transparent_tcp.ServerSetup(termMon, *bindAddr) + fmt.Println("launched", launched, ptListeners) + } + } + } + } else { + if *udp { + log.Infof("%s - initializing STUN UDP proxy", execName) + if isClient { + log.Infof("%s - initializing client transport listeners", execName) + if *target == "" { + log.Errorf("%s - STUN mode requires a target", execName) + } else { + fmt.Println("STUN udp client") + launched = stun_udp.ClientSetup(termMon, *target) + } + } else { + log.Infof("%s - initializing server transport listeners", execName) + if *bindAddr == "" { + fmt.Println("%s - STUN mode requires a bindaddr", execName) + } else { + fmt.Println("STUN udp server") + launched = stun_udp.ServerSetup(termMon, *bindAddr, *target) + fmt.Println("launched", launched, ptListeners) + } + } + } else { + // Do the managed pluggable transport protocol configuration. + 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) + } else { + log.Infof("%s - initializing server transport listeners", execName) + launched, ptListeners = pt_socks5.ServerSetup(termMon) + } + } + } + + if !launched { + // Initialization failed, the client or server setup routines should + // have logged, so just exit here. + os.Exit(-1) + } + + fmt.Println("launched") + + 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) + + fmt.Println("waiting") + for { + // FIXME - block because termMon.Wait is not blocking + } +} + +func checkIsClient(client bool, server bool) (bool, error) { + if client { + return true, nil + } else if server { + return false, nil + } else { + return pt_extras.PtIsClient() + } +} + +func makeStateDir(statePath string) (string, error) { + if statePath != "" { + err := os.MkdirAll(statePath, 0700) + return statePath, err + } else { + return pt.MakeStateDir() + } +} -- cgit v1.2.3