Exemple #1
0
func (m *TermMonitor) termOnStdinClose() {
	_, err := io.Copy(ioutil.Discard, os.Stdin)

	// io.Copy() will return a nil on EOF, since reaching EOF is
	// expected behavior.  No matter what, if this unblocks, assume
	// that stdin is closed, and treat that as having received a
	// SIGTERM.
	log.Noticef("Stdin is closed or unreadable: %v", err)
	m.sigChan <- syscall.SIGTERM
}
Exemple #2
0
func (m *TermMonitor) termOnPPIDChange(ppid int) {
	// Under most if not all U*IX systems, the parent PID will change
	// to that of init once the parent dies.  There are several notable
	// exceptions (Slowlaris/Android), but the parent PID changes
	// under those platforms as well.
	//
	// Naturally we lose if the parent has died by the time when the
	// Getppid() call was issued in our parent, but, this is better
	// than nothing.
	const ppidPollInterval = 1 * time.Second
	for ppid == os.Getppid() {
		time.Sleep(ppidPollInterval)
	}

	// Treat the parent PID changing as the same as having received
	// a SIGTERM.
	log.Noticef("Parent pid changed: %d (was %d)", os.Getppid(), ppid)
	m.sigChan <- syscall.SIGTERM
}
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/"+obfs4proxyLogFile)
	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, 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())
	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
	}
}