def daemonize(): if os.fork(): os._exit(0) os.setsid() if os.fork(): os._exit(0) outfd = os.open(_pidname, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0666) try: os.write(outfd, '%d\n' % os.getpid()) finally: os.close(outfd) os.chdir("/") # Normal exit when killed, or try/finally won't work and the pidfile won't # be deleted. signal.signal(signal.SIGTERM, got_signal) si = open('/dev/null', 'r+') os.dup2(si.fileno(), 0) os.dup2(si.fileno(), 1) si.close() ssyslog.stderr_to_syslog()
def main(port, dnsport, syslog): assert (port > 0) assert (port <= 65535) assert (dnsport >= 0) assert (dnsport <= 65535) if os.getuid() != 0: raise Fatal('you must be root (or enable su/sudo) to set the firewall') if program_exists('ipfw'): do_it = do_ipfw elif program_exists('iptables'): do_it = do_iptables else: raise Fatal("can't find either ipfw or iptables; check your PATH") # because of limitations of the 'su' command, the *real* stdin/stdout # are both attached to stdout initially. Clone stdout into stdin so we # can read from it. os.dup2(1, 0) if syslog: ssyslog.start_syslog() ssyslog.stderr_to_syslog() debug1('firewall manager ready.\n') sys.stdout.write('READY\n') sys.stdout.flush() # ctrl-c shouldn't be passed along to me. When the main sshuttle dies, # I'll die automatically. os.setsid() # we wait until we get some input before creating the rules. That way, # sshuttle can launch us as early as possible (and get sudo password # authentication as early in the startup process as possible). line = sys.stdin.readline(128) if not line: return # parent died; nothing to do subnets = [] if line != 'ROUTES\n': raise Fatal('firewall: expected ROUTES but got %r' % line) while 1: line = sys.stdin.readline(128) if not line: raise Fatal('firewall: expected route but got %r' % line) elif line == 'GO\n': break try: (width, exclude, ip) = line.strip().split(',', 2) except: raise Fatal('firewall: expected route or GO but got %r' % line) subnets.append((int(width), bool(int(exclude)), ip)) try: if line: debug1('firewall manager: starting transproxy.\n') do_wait = do_it(port, dnsport, subnets) sys.stdout.write('STARTED\n') try: sys.stdout.flush() except IOError: # the parent process died for some reason; he's surely been loud # enough, so no reason to report another error return # Now we wait until EOF or any other kind of exception. We need # to stay running so that we don't need a *second* password # authentication at shutdown time - that cleanup is important! while 1: if do_wait: do_wait() line = sys.stdin.readline(128) if line.startswith('HOST '): (name, ip) = line[5:].strip().split(',', 1) hostmap[name] = ip rewrite_etc_hosts(port) elif line: raise Fatal('expected EOF, got %r' % line) else: break finally: try: debug1('firewall manager: undoing changes.\n') except: pass do_it(port, 0, []) restore_etc_hosts(port)
rv = serverproc.poll() if rv: raise Fatal('server died with error code %d' % rv) if initstring != expected: raise Fatal('expected server init string %r; got %r' % (expected, initstring)) debug1('connected.\n') print 'Connected.' sys.stdout.flush() if daemon: daemonize() log('daemonizing (%s).\n' % _pidname) elif syslog: debug1('switching to syslog.\n') ssyslog.stderr_to_syslog() def onroutes(routestr): if auto_nets: for line in routestr.strip().split('\n'): (family, ip, width) = line.split(',', 2) fw.auto_nets.append((family, ip, int(width))) # we definitely want to do this *after* starting ssh, or we might end # up intercepting the ssh connection! # # Moreover, now that we have the --auto-nets option, we have to wait # for the server to send us that message anyway. Even if we haven't # set --auto-nets, we might as well wait for the message first, then # ignore its contents. mux.got_routes = None
def main(port_v6, port_v4, dnsport_v6, dnsport_v4, method, udp, syslog): assert(port_v6 >= 0) assert(port_v6 <= 65535) assert(port_v4 >= 0) assert(port_v4 <= 65535) assert(dnsport_v6 >= 0) assert(dnsport_v6 <= 65535) assert(dnsport_v4 >= 0) assert(dnsport_v4 <= 65535) if os.getuid() != 0: raise Fatal('you must be root (or enable su/sudo) to set the firewall') if method == "auto": if program_exists('ipfw'): method = "ipfw" elif program_exists('iptables'): method = "nat" elif program_exists('pfctl'): method = "pf" else: raise Fatal("can't find either ipfw, iptables or pfctl; check your PATH") if method == "nat": do_it = do_iptables_nat elif method == "tproxy": do_it = do_iptables_tproxy elif method == "ipfw": do_it = do_ipfw elif method == "pf": do_it = do_pf else: raise Exception('Unknown method "%s"' % method) # because of limitations of the 'su' command, the *real* stdin/stdout # are both attached to stdout initially. Clone stdout into stdin so we # can read from it. os.dup2(1, 0) if syslog: ssyslog.start_syslog() ssyslog.stderr_to_syslog() debug1('firewall manager ready method %s.\n' % method) sys.stdout.write('READY %s\n' % method) sys.stdout.flush() # don't disappear if our controlling terminal or stdout/stderr # disappears; we still have to clean up. signal.signal(signal.SIGHUP, signal.SIG_IGN) signal.signal(signal.SIGPIPE, signal.SIG_IGN) signal.signal(signal.SIGTERM, signal.SIG_IGN) signal.signal(signal.SIGINT, signal.SIG_IGN) # ctrl-c shouldn't be passed along to me. When the main sshuttle dies, # I'll die automatically. os.setsid() # we wait until we get some input before creating the rules. That way, # sshuttle can launch us as early as possible (and get sudo password # authentication as early in the startup process as possible). line = sys.stdin.readline(128) if not line: return # parent died; nothing to do subnets = [] if line != 'ROUTES\n': raise Fatal('firewall: expected ROUTES but got %r' % line) while 1: line = sys.stdin.readline(128) if not line: raise Fatal('firewall: expected route but got %r' % line) elif line == 'GO\n': break try: (family, width, exclude, ip) = line.strip().split(',', 3) except: raise Fatal('firewall: expected route or GO but got %r' % line) subnets.append((int(family), int(width), bool(int(exclude)), ip)) try: if line: debug1('firewall manager: starting transproxy.\n') subnets_v6 = filter(lambda i: i[0] == socket.AF_INET6, subnets) if port_v6: do_wait = do_it( port_v6, dnsport_v6, socket.AF_INET6, subnets_v6, udp) elif len(subnets_v6) > 0: debug1("IPv6 subnets defined but IPv6 disabled\n") subnets_v4 = filter(lambda i: i[0] == socket.AF_INET, subnets) if port_v4: do_wait = do_it( port_v4, dnsport_v4, socket.AF_INET, subnets_v4, udp) elif len(subnets_v4) > 0: debug1('IPv4 subnets defined but IPv4 disabled\n') sys.stdout.write('STARTED\n') try: sys.stdout.flush() except IOError: # the parent process died for some reason; he's surely been loud # enough, so no reason to report another error return # Now we wait until EOF or any other kind of exception. We need # to stay running so that we don't need a *second* password # authentication at shutdown time - that cleanup is important! while 1: if do_wait: do_wait() line = sys.stdin.readline(128) if line.startswith('HOST '): (name, ip) = line[5:].strip().split(',', 1) hostmap[name] = ip rewrite_etc_hosts(port_v6 or port_v4) elif line.startswith('QUERY_PF_NAT '): try: dst = pf_query_nat(*(line[13:].split(','))) sys.stdout.write('QUERY_PF_NAT_SUCCESS %s,%r\n' % dst) except IOError, e: sys.stdout.write('QUERY_PF_NAT_FAILURE %s\n' % e) sys.stdout.flush() elif line: raise Fatal('expected EOF, got %r' % line) else: