summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrandon Wiley <brandon@blanu.net>2016-11-15 14:51:32 -0600
committerBrandon Wiley <brandon@blanu.net>2016-11-15 14:51:32 -0600
commit93cb566c11b9c968677786bc6b5cf01ac06931e6 (patch)
tree018f8eac909ad110d0730849a8c415e944a2a0ae
parent17f2cb99c26454c519ca23185ee5dd3176a9363d (diff)
Renamed obfs4proxy to shapeshifter-dispatcher
-rw-r--r--shapeshifter-dispatcher/shapeshifter-dispatcher.go247
1 files changed, 247 insertions, 0 deletions
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 <yawning at torproject dot org>
+ * 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()
+ }
+}