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, 0o666) 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(method_name, syslog, ttl): helpers.logprefix = 'fw: ' stdin, stdout = setup_daemon() hostmap = {} debug1('Starting firewall with Python version %s' % platform.python_version()) if method_name == "auto": method = get_auto_method() else: method = get_method(method_name) if syslog: ssyslog.start_syslog() ssyslog.stderr_to_syslog() if not method.is_supported(): raise Fatal("The %s method is not supported on this machine. " "Check that the appropriate programs are in your " "PATH." % method_name) debug1('ready method name %s.' % method.name) stdout.write('READY %s\n' % method.name) stdout.flush() # 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 = stdin.readline(128) if not line: return # parent died; nothing to do subnets = [] if line != 'ROUTES\n': raise Fatal('expected ROUTES but got %r' % line) while 1: line = stdin.readline(128) if not line: raise Fatal('expected route but got %r' % line) elif line.startswith("NSLIST\n"): break try: (family, width, exclude, ip, fport, lport) = \ line.strip().split(',', 5) except BaseException: raise Fatal('expected route or NSLIST but got %r' % line) subnets.append(( int(family), int(width), bool(int(exclude)), ip, int(fport), int(lport))) debug2('Got subnets: %r' % subnets) nslist = [] if line != 'NSLIST\n': raise Fatal('expected NSLIST but got %r' % line) while 1: line = stdin.readline(128) if not line: raise Fatal('expected nslist but got %r' % line) elif line.startswith("PORTS "): break try: (family, ip) = line.strip().split(',', 1) except BaseException: raise Fatal('expected nslist or PORTS but got %r' % line) nslist.append((int(family), ip)) debug2('Got partial nslist: %r' % nslist) debug2('Got nslist: %r' % nslist) if not line.startswith('PORTS '): raise Fatal('expected PORTS but got %r' % line) _, _, ports = line.partition(" ") ports = ports.split(",") if len(ports) != 4: raise Fatal('expected 4 ports but got %d' % len(ports)) port_v6 = int(ports[0]) port_v4 = int(ports[1]) dnsport_v6 = int(ports[2]) dnsport_v4 = int(ports[3]) 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) debug2('Got ports: %d,%d,%d,%d' % (port_v6, port_v4, dnsport_v6, dnsport_v4)) line = stdin.readline(128) if not line: raise Fatal('expected GO but got %r' % line) elif not line.startswith("GO "): raise Fatal('expected GO but got %r' % line) _, _, args = line.partition(" ") udp, user, ttl, tmark = args.strip().split(" ", 3) udp = bool(int(udp)) if user == '-': user = None ttl = int(ttl) debug2('Got udp: %r, user: %r, ttl: %s, tmark: %s' % (udp, user, ttl, tmark)) subnets_v6 = [i for i in subnets if i[0] == socket.AF_INET6] nslist_v6 = [i for i in nslist if i[0] == socket.AF_INET6] subnets_v4 = [i for i in subnets if i[0] == socket.AF_INET] nslist_v4 = [i for i in nslist if i[0] == socket.AF_INET] try: debug1('setting up.') if subnets_v6 or nslist_v6: debug2('setting up IPv6.') method.setup_firewall( port_v6, dnsport_v6, nslist_v6, socket.AF_INET6, subnets_v6, udp, user, ttl, tmark) if subnets_v4 or nslist_v4: debug2('setting up IPv4.') method.setup_firewall( port_v4, dnsport_v4, nslist_v4, socket.AF_INET, subnets_v4, udp, user, ttl, tmark) flush_systemd_dns_cache() stdout.write('STARTED\n') try: 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: line = stdin.readline(128) if line.startswith('HOST '): (name, ip) = line[5:].strip().split(',', 1) hostmap[name] = ip debug2('setting up /etc/hosts.') rewrite_etc_hosts(hostmap, port_v6 or port_v4) elif line: if not method.firewall_command(line): raise Fatal('expected command, got %r' % line) else: break finally: try: debug1('undoing changes.') except BaseException: debug2('An error occurred, ignoring it.') try: if subnets_v6 or nslist_v6: debug2('undoing IPv6 changes.') method.restore_firewall(port_v6, socket.AF_INET6, udp, user) except BaseException: try: debug1("Error trying to undo IPv6 firewall.") debug1(traceback.format_exc()) except BaseException: debug2('An error occurred, ignoring it.') try: if subnets_v4 or nslist_v4: debug2('undoing IPv4 changes.') method.restore_firewall(port_v4, socket.AF_INET, udp, user) except BaseException: try: debug1("Error trying to undo IPv4 firewall.") debug1(traceback.format_exc()) except BaseException: debug2('An error occurred, ignoring it.') try: # debug2() message printed in restore_etc_hosts() function. restore_etc_hosts(hostmap, port_v6 or port_v4) except BaseException: try: debug1("Error trying to undo /etc/hosts changes.") debug1(traceback.format_exc()) except BaseException: debug2('An error occurred, ignoring it.') try: flush_systemd_dns_cache() except BaseException: try: debug1("Error trying to flush systemd dns cache.") debug1(traceback.format_exc()) except BaseException: debug2("An error occurred, ignoring it.")
def main(method_name, syslog): stdin, stdout = setup_daemon() hostmap = {} debug1('firewall manager: Starting firewall with Python version %s\n' % platform.python_version()) if method_name == "auto": method = get_auto_method() else: method = get_method(method_name) if syslog: ssyslog.start_syslog() ssyslog.stderr_to_syslog() debug1('firewall manager: ready method name %s.\n' % method.name) stdout.write('READY %s\n' % method.name) stdout.flush() # 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 = 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 = stdin.readline(128) if not line: raise Fatal('firewall: expected route but got %r' % line) elif line.startswith("NSLIST\n"): break try: (family, width, exclude, ip) = line.strip().split(',', 3) except: raise Fatal('firewall: expected route or NSLIST but got %r' % line) subnets.append((int(family), int(width), bool(int(exclude)), ip)) debug2('firewall manager: Got subnets: %r\n' % subnets) nslist = [] if line != 'NSLIST\n': raise Fatal('firewall: expected NSLIST but got %r' % line) while 1: line = stdin.readline(128) if not line: raise Fatal('firewall: expected nslist but got %r' % line) elif line.startswith("PORTS "): break try: (family, ip) = line.strip().split(',', 1) except: raise Fatal('firewall: expected nslist or PORTS but got %r' % line) nslist.append((int(family), ip)) debug2('firewall manager: Got partial nslist: %r\n' % nslist) debug2('firewall manager: Got nslist: %r\n' % nslist) if not line.startswith('PORTS '): raise Fatal('firewall: expected PORTS but got %r' % line) _, _, ports = line.partition(" ") ports = ports.split(",") if len(ports) != 4: raise Fatal('firewall: expected 4 ports but got %n' % len(ports)) port_v6 = int(ports[0]) port_v4 = int(ports[1]) dnsport_v6 = int(ports[2]) dnsport_v4 = int(ports[3]) 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) debug2('firewall manager: Got ports: %d,%d,%d,%d\n' % (port_v6, port_v4, dnsport_v6, dnsport_v4)) line = stdin.readline(128) if not line: raise Fatal('firewall: expected GO but got %r' % line) elif not line.startswith("GO "): raise Fatal('firewall: expected GO but got %r' % line) _, _, udp = line.partition(" ") udp = bool(int(udp)) debug2('firewall manager: Got udp: %r\n' % udp) subnets_v6 = [i for i in subnets if i[0] == socket.AF_INET6] nslist_v6 = [i for i in nslist if i[0] == socket.AF_INET6] subnets_v4 = [i for i in subnets if i[0] == socket.AF_INET] nslist_v4 = [i for i in nslist if i[0] == socket.AF_INET] try: debug1('firewall manager: setting up.\n') if len(subnets_v6) > 0 or len(nslist_v6) > 0: debug2('firewall manager: setting up IPv6.\n') method.setup_firewall( port_v6, dnsport_v6, nslist_v6, socket.AF_INET6, subnets_v6, udp) if len(subnets_v4) > 0 or len(nslist_v4) > 0: debug2('firewall manager: setting up IPv4.\n') method.setup_firewall( port_v4, dnsport_v4, nslist_v4, socket.AF_INET, subnets_v4, udp) stdout.write('STARTED\n') try: 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: line = stdin.readline(128) if line.startswith('HOST '): (name, ip) = line[5:].strip().split(',', 1) hostmap[name] = ip debug2('firewall manager: setting up /etc/hosts.\n') rewrite_etc_hosts(hostmap, port_v6 or port_v4) elif line: if not method.firewall_command(line): raise Fatal('firewall: expected command, got %r' % line) else: break finally: try: debug1('firewall manager: undoing changes.\n') except: pass try: if len(subnets_v6) > 0 or len(nslist_v6) > 0: debug2('firewall manager: undoing IPv6 changes.\n') method.restore_firewall(port_v6, socket.AF_INET6, udp) except: try: debug1("firewall manager: " "Error trying to undo IPv6 firewall.\n") for line in traceback.format_exc().splitlines(): debug1("---> %s\n" % line) except: pass try: if len(subnets_v4) > 0 or len(nslist_v4) > 0: debug2('firewall manager: undoing IPv4 changes.\n') method.restore_firewall(port_v4, socket.AF_INET, udp) except: try: debug1("firewall manager: " "Error trying to undo IPv4 firewall.\n") for line in traceback.format_exc().splitlines(): debug1("firewall manager: ---> %s\n" % line) except: pass try: debug2('firewall manager: undoing /etc/hosts changes.\n') restore_etc_hosts(port_v6 or port_v4) except: try: debug1("firewall manager: " "Error trying to undo /etc/hosts changes.\n") for line in traceback.format_exc().splitlines(): debug1("firewall manager: ---> %s\n" % line) except: pass
def main(method_name, syslog): stdin, stdout = setup_daemon() hostmap = {} debug1('firewall manager: Starting firewall with Python version %s\n' % platform.python_version()) if method_name == "auto": method = get_auto_method() else: method = get_method(method_name) if syslog: ssyslog.start_syslog() ssyslog.stderr_to_syslog() debug1('firewall manager: ready method name %s.\n' % method.name) stdout.write('READY %s\n' % method.name) stdout.flush() # 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 = 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 = stdin.readline(128) if not line: raise Fatal('firewall: expected route but got %r' % line) elif line.startswith("NSLIST\n"): break try: (family, width, exclude, ip, fport, lport) = \ line.strip().split(',', 5) except: raise Fatal('firewall: expected route or NSLIST but got %r' % line) subnets.append((int(family), int(width), bool(int(exclude)), ip, int(fport), int(lport))) debug2('firewall manager: Got subnets: %r\n' % subnets) nslist = [] if line != 'NSLIST\n': raise Fatal('firewall: expected NSLIST but got %r' % line) while 1: line = stdin.readline(128) if not line: raise Fatal('firewall: expected nslist but got %r' % line) elif line.startswith("PORTS "): break try: (family, ip) = line.strip().split(',', 1) except: raise Fatal('firewall: expected nslist or PORTS but got %r' % line) nslist.append((int(family), ip)) debug2('firewall manager: Got partial nslist: %r\n' % nslist) debug2('firewall manager: Got nslist: %r\n' % nslist) if not line.startswith('PORTS '): raise Fatal('firewall: expected PORTS but got %r' % line) _, _, ports = line.partition(" ") ports = ports.split(",") if len(ports) != 4: raise Fatal('firewall: expected 4 ports but got %d' % len(ports)) port_v6 = int(ports[0]) port_v4 = int(ports[1]) dnsport_v6 = int(ports[2]) dnsport_v4 = int(ports[3]) 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) debug2('firewall manager: Got ports: %d,%d,%d,%d\n' % (port_v6, port_v4, dnsport_v6, dnsport_v4)) line = stdin.readline(128) if not line: raise Fatal('firewall: expected GO but got %r' % line) elif not line.startswith("GO "): raise Fatal('firewall: expected GO but got %r' % line) _, _, args = line.partition(" ") udp, user = args.strip().split(" ", 1) udp = bool(int(udp)) if user == '-': user = None debug2('firewall manager: Got udp: %r, user: %r\n' % (udp, user)) subnets_v6 = [i for i in subnets if i[0] == socket.AF_INET6] nslist_v6 = [i for i in nslist if i[0] == socket.AF_INET6] subnets_v4 = [i for i in subnets if i[0] == socket.AF_INET] nslist_v4 = [i for i in nslist if i[0] == socket.AF_INET] try: debug1('firewall manager: setting up.\n') if subnets_v6 or nslist_v6: debug2('firewall manager: setting up IPv6.\n') method.setup_firewall(port_v6, dnsport_v6, nslist_v6, socket.AF_INET6, subnets_v6, udp, user) if subnets_v4 or nslist_v4: debug2('firewall manager: setting up IPv4.\n') method.setup_firewall(port_v4, dnsport_v4, nslist_v4, socket.AF_INET, subnets_v4, udp, user) stdout.write('STARTED\n') sdnotify.send(sdnotify.ready(), sdnotify.status('Connected')) try: 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: line = stdin.readline(128) if line.startswith('HOST '): (name, ip) = line[5:].strip().split(',', 1) hostmap[name] = ip debug2('firewall manager: setting up /etc/hosts.\n') rewrite_etc_hosts(hostmap, port_v6 or port_v4) elif line: if not method.firewall_command(line): raise Fatal('firewall: expected command, got %r' % line) else: break finally: try: sdnotify.send(sdnotify.stop()) debug1('firewall manager: undoing changes.\n') except: pass try: if subnets_v6 or nslist_v6: debug2('firewall manager: undoing IPv6 changes.\n') method.restore_firewall(port_v6, socket.AF_INET6, udp, user) except: try: debug1("firewall manager: " "Error trying to undo IPv6 firewall.\n") for line in traceback.format_exc().splitlines(): debug1("---> %s\n" % line) except: pass try: if subnets_v4 or nslist_v4: debug2('firewall manager: undoing IPv4 changes.\n') method.restore_firewall(port_v4, socket.AF_INET, udp, user) except: try: debug1("firewall manager: " "Error trying to undo IPv4 firewall.\n") for line in traceback.format_exc().splitlines(): debug1("firewall manager: ---> %s\n" % line) except: pass try: debug2('firewall manager: undoing /etc/hosts changes.\n') restore_etc_hosts(port_v6 or port_v4) except: try: debug1("firewall manager: " "Error trying to undo /etc/hosts changes.\n") for line in traceback.format_exc().splitlines(): debug1("firewall manager: ---> %s\n" % line) except: pass
def main(): opt = parser.parse_args() if opt.daemon: opt.syslog = 1 if opt.wrap: import sshuttle.ssnet as ssnet ssnet.MAX_CHANNEL = opt.wrap helpers.verbose = opt.verbose try: if opt.firewall: if opt.subnets or opt.subnets_file: parser.error('exactly zero arguments expected') return firewall.main(opt.method, opt.syslog) elif opt.hostwatch: return hostwatch.hw_main(opt.subnets) else: includes = opt.subnets + opt.subnets_file excludes = opt.exclude if not includes and not opt.auto_nets: parser.error('at least one subnet, subnet file, ' 'or -N expected') remotename = opt.remote if remotename == '' or remotename == '-': remotename = None nslist = [family_ip_tuple(ns) for ns in opt.ns_hosts] if opt.seed_hosts: sh = re.split(r'[\s,]+', (opt.seed_hosts or "").strip()) elif opt.auto_hosts: sh = [] else: sh = None if opt.listen: ipport_v6 = None ipport_v4 = None list = opt.listen.split(",") for ip in list: family, ip, port = parse_ipport(ip) if family == socket.AF_INET6: ipport_v6 = (ip, port) else: ipport_v4 = (ip, port) else: # parse_ipport4('127.0.0.1:0') ipport_v4 = "auto" # parse_ipport6('[::1]:0') ipport_v6 = "auto" if not opt.disable_ipv6 else None if opt.syslog: ssyslog.start_syslog() ssyslog.stderr_to_syslog() return_code = client.main(ipport_v6, ipport_v4, opt.ssh_cmd, remotename, opt.python, opt.latency_control, opt.dns, nslist, opt.method, sh, opt.auto_hosts, opt.auto_nets, includes, excludes, opt.daemon, opt.pidfile) if return_code == 0: log('Normal exit code, exiting...') else: log('Abnormal exit code detected, failing...' % return_code) return return_code except Fatal as e: log('fatal: %s\n' % e) return 99 except KeyboardInterrupt: log('\n') log('Keyboard interrupt: exiting.\n') return 1
def main(): opt = parser.parse_args() if opt.daemon: opt.syslog = 1 if opt.wrap: import sshuttle.ssnet as ssnet ssnet.MAX_CHANNEL = opt.wrap helpers.verbose = opt.verbose try: if opt.firewall: if opt.subnets or opt.subnets_file: parser.error('exactly zero arguments expected') return firewall.main(opt.method, opt.syslog) elif opt.hostwatch: return hostwatch.hw_main(opt.subnets, opt.auto_hosts) else: includes = opt.subnets + opt.subnets_file excludes = opt.exclude if not includes and not opt.auto_nets: parser.error('at least one subnet, subnet file, ' 'or -N expected') remotename = opt.remote if remotename == '' or remotename == '-': remotename = None nslist = [family_ip_tuple(ns) for ns in opt.ns_hosts] if opt.seed_hosts: sh = re.split(r'[\s,]+', (opt.seed_hosts or "").strip()) elif opt.auto_hosts: sh = [] else: sh = None if opt.listen: ipport_v6 = None ipport_v4 = None lst = opt.listen.split(",") for ip in lst: family, ip, port = parse_ipport(ip) if family == socket.AF_INET6: ipport_v6 = (ip, port) else: ipport_v4 = (ip, port) else: # parse_ipport4('127.0.0.1:0') ipport_v4 = "auto" # parse_ipport6('[::1]:0') ipport_v6 = "auto" if not opt.disable_ipv6 else None if opt.syslog: ssyslog.start_syslog() ssyslog.close_stdin() ssyslog.stdout_to_syslog() ssyslog.stderr_to_syslog() return_code = client.main(ipport_v6, ipport_v4, opt.ssh_cmd, remotename, opt.python, opt.latency_control, opt.dns, nslist, opt.method, sh, opt.auto_hosts, opt.auto_nets, includes, excludes, opt.daemon, opt.to_ns, opt.pidfile, opt.user, opt.sudo_pythonpath) if return_code == 0: log('Normal exit code, exiting...') else: log('Abnormal exit code %d detected, failing...' % return_code) return return_code except Fatal as e: log('fatal: %s\n' % e) return 99 except KeyboardInterrupt: log('\n') log('Keyboard interrupt: exiting.\n') return 1
def main(): opt = parser.parse_args() if opt.sudoers or opt.sudoers_no_modify: if platform.platform().startswith('OpenBSD'): log('Automatic sudoers does not work on BSD') exit(1) if not opt.sudoers_filename: log('--sudoers-file must be set or omited.') exit(1) sudoers(user_name=opt.sudoers_user, no_modify=opt.sudoers_no_modify, file_name=opt.sudoers_filename) if opt.daemon: opt.syslog = 1 if opt.wrap: import sshuttle.ssnet as ssnet ssnet.MAX_CHANNEL = opt.wrap if opt.latency_buffer_size: import sshuttle.ssnet as ssnet ssnet.LATENCY_BUFFER_SIZE = opt.latency_buffer_size helpers.verbose = opt.verbose try: if opt.firewall: if opt.subnets or opt.subnets_file: parser.error('exactly zero arguments expected') return firewall.main(opt.method, opt.syslog) elif opt.hostwatch: return hostwatch.hw_main(opt.subnets, opt.auto_hosts) else: # parse_subnetports() is used to create a list of includes # and excludes. It is called once for each parameter and # returns a list of one or more items for each subnet (it # can return more than one item when a hostname in the # parameter resolves to multiple IP addresses. Here, we # flatten these lists. includes = [ item for sublist in opt.subnets + opt.subnets_file for item in sublist ] excludes = [item for sublist in opt.exclude for item in sublist] if not includes and not opt.auto_nets: parser.error('at least one subnet, subnet file, ' 'or -N expected') remotename = opt.remote if remotename == '' or remotename == '-': remotename = None nslist = [family_ip_tuple(ns) for ns in opt.ns_hosts] if opt.seed_hosts: sh = re.split(r'[\s,]+', (opt.seed_hosts or "").strip()) elif opt.auto_hosts: sh = [] else: sh = None if opt.listen: ipport_v6 = None ipport_v4 = None lst = opt.listen.split(",") for ip in lst: family, ip, port = parse_ipport(ip) if family == socket.AF_INET6: ipport_v6 = (ip, port) else: ipport_v4 = (ip, port) else: # parse_ipport4('127.0.0.1:0') ipport_v4 = "auto" # parse_ipport6('[::1]:0') ipport_v6 = "auto" if not opt.disable_ipv6 else None if opt.syslog: ssyslog.start_syslog() ssyslog.close_stdin() ssyslog.stdout_to_syslog() ssyslog.stderr_to_syslog() return_code = client.main( ipport_v6, ipport_v4, opt.ssh_cmd, remotename, opt.python, opt.latency_control, opt.dns, nslist, opt.method, sh, opt.auto_hosts, opt.auto_nets, includes, excludes, opt.daemon, opt.to_ns, opt.pidfile, opt.user, opt.sudo_pythonpath) if return_code == 0: log('Normal exit code, exiting...') else: log('Abnormal exit code %d detected, failing...' % return_code) return return_code except Fatal as e: log('fatal: %s\n' % e) return 99 except KeyboardInterrupt: log('\n') log('Keyboard interrupt: exiting.\n') return 1
def main(): opt = parser.parse_args() if opt.daemon: opt.syslog = 1 if opt.wrap: import sshuttle.ssnet as ssnet ssnet.MAX_CHANNEL = opt.wrap helpers.verbose = opt.verbose try: if opt.firewall: if opt.subnets or opt.subnets_file: parser.error('exactly zero arguments expected') return firewall.main(opt.method, opt.syslog) elif opt.hostwatch: return hostwatch.hw_main(opt.subnets, opt.auto_hosts) else: if opt.syslog: ssyslog.start_syslog() ssyslog.stderr_to_syslog() # Environment Variables that overrides the command line arguments log('opt.verbose was %s\n' % opt.verbose) if os.environ.__contains__('SSHUTTLE_VERBOSE_LEVEL') == True: helpers.verbose = int(os.environ['SSHUTTLE_VERBOSE_LEVEL']) log('SSHUTTLE_VERBOSE_LEVEL env variable was set. Setting helpers.verbose to %s\n' % helpers.verbose) log('opt.ns_hosts was %s\n' % opt.ns_hosts) if os.environ.__contains__('SSHUTTLE_NS_HOSTS') == True: opt.ns_hosts = re.split( r'[\s,]+', (os.environ['SSHUTTLE_NS_HOSTS']).strip()) log('SSHUTTLE_NS_HOSTS env variable was set. Setting --ns-hosts to %s\n' % opt.ns_hosts) log('opt.method was %s\n' % opt.method) if os.environ.__contains__('SSHUTTLE_METHOD') == True: opt.method = os.environ['SSHUTTLE_METHOD'] log('SSHUTTLE_METHOD env variable was set. Setting --method to %s\n' % opt.method) log('opt.disable_ipv6 was %s\n' % opt.disable_ipv6) if os.environ.__contains__('SSHUTTLE_DISABLE_IPV6') == True: if os.environ['SSHUTTLE_DISABLE_IPV6'] == 'True': opt.disable_ipv6 = True else: opt.disable_ipv6 = False log('SSHUTTLE_DISABLE_IPV6 env variable was set. Setting --disable-ipv6 to %s\n' % opt.disable_ipv6) log('opt.exclude was %s\n' % opt.exclude) if os.environ.__contains__('SSHUTTLE_EXCLUDES') == True: opt.exclude = list( map( lambda x: parse_subnetport(x), re.split(r'[\s,]+', (os.environ['SSHUTTLE_EXCLUDES']).strip()))) log('SSHUTTLE_EXCLUDES env variable was set. Setting --exclude to %s\n' % opt.exclude) includes = opt.subnets + opt.subnets_file excludes = opt.exclude if not includes and not opt.auto_nets: parser.error('at least one subnet, subnet file, ' 'or -N expected') remotename = opt.remote if remotename == '' or remotename == '-': remotename = None nslist = [family_ip_tuple(ns) for ns in opt.ns_hosts] if opt.seed_hosts: sh = re.split(r'[\s,]+', (opt.seed_hosts or "").strip()) elif opt.auto_hosts: sh = [] else: sh = None if opt.listen: ipport_v6 = None ipport_v4 = None lst = opt.listen.split(",") for ip in lst: family, ip, port = parse_ipport(ip) if family == socket.AF_INET6: ipport_v6 = (ip, port) else: ipport_v4 = (ip, port) else: # parse_ipport4('127.0.0.1:0') ipport_v4 = "auto" # parse_ipport6('[::1]:0') ipport_v6 = "auto" if not opt.disable_ipv6 else None return_code = client.main( ipport_v6, ipport_v4, opt.ssh_cmd, remotename, opt.python, opt.latency_control, opt.dns, nslist, opt.method, sh, opt.auto_hosts, opt.auto_nets, includes, excludes, opt.daemon, opt.to_ns, opt.pidfile, opt.user) if return_code == 0: log('Normal exit code, exiting...') else: log('Abnormal exit code detected, failing...' % return_code) return return_code except Fatal as e: log('fatal: %s\n' % e) return 99 except KeyboardInterrupt: log('\n') log('Keyboard interrupt: exiting.\n') return 1
def main(): opt = parser.parse_args() if opt.daemon: opt.syslog = 1 if opt.wrap: import sshuttle.ssnet as ssnet ssnet.MAX_CHANNEL = opt.wrap helpers.verbose = opt.verbose try: if opt.firewall: if opt.subnets or opt.subnets_file: parser.error("exactly zero arguments expected") return firewall.main(opt.method, opt.syslog) elif opt.hostwatch: return hostwatch.hw_main(opt.subnets) else: includes = opt.subnets + opt.subnets_file excludes = opt.exclude if not includes and not opt.auto_nets: parser.error("at least one subnet, subnet file, " "or -N expected") remotename = opt.remote if remotename == "" or remotename == "-": remotename = None nslist = [family_ip_tuple(ns) for ns in opt.ns_hosts] if opt.seed_hosts: sh = re.split(r"[\s,]+", (opt.seed_hosts or "").strip()) elif opt.auto_hosts: sh = [] else: sh = None if opt.listen: ipport_v6 = None ipport_v4 = None list = opt.listen.split(",") for ip in list: if "[" in ip and "]" in ip: ipport_v6 = parse_ipport6(ip) else: ipport_v4 = parse_ipport4(ip) else: # parse_ipport4('127.0.0.1:0') ipport_v4 = "auto" # parse_ipport6('[::1]:0') ipport_v6 = "auto" if not opt.disable_ipv6 else None if opt.syslog: ssyslog.start_syslog() ssyslog.stderr_to_syslog() return_code = client.main( ipport_v6, ipport_v4, opt.ssh_cmd, remotename, opt.python, opt.latency_control, opt.dns, nslist, opt.method, sh, opt.auto_hosts, opt.auto_nets, includes, excludes, opt.daemon, opt.pidfile, ) if return_code == 0: log("Normal exit code, exiting...") else: log("Abnormal exit code detected, failing..." % return_code) return return_code except Fatal as e: log("fatal: %s\n" % e) return 99 except KeyboardInterrupt: log("\n") log("Keyboard interrupt: exiting.\n") return 1
ipport_v6 = None ipport_v4 = None list = opt.listen.split(",") for ip in list: if '[' in ip and ']' in ip: ipport_v6 = parse_ipport6(ip) else: ipport_v4 = parse_ipport4(ip) else: # parse_ipport4('127.0.0.1:0') ipport_v4 = "auto" # parse_ipport6('[::1]:0') ipport_v6 = "auto" if not opt.disable_ipv6 else None if opt.syslog: ssyslog.start_syslog() ssyslog.stderr_to_syslog() return_code = client.main(ipport_v6, ipport_v4, opt.ssh_cmd, remotename, opt.python, opt.latency_control, opt.dns, nslist, method_name, sh, opt.auto_nets, parse_subnets(includes), parse_subnets(excludes), opt.daemon, opt.pidfile) if return_code == 0: log('Normal exit code, exiting...') else: log('Abnormal exit code detected, failing...' % return_code) sys.exit(return_code) except Fatal as e: log('fatal: %s\n' % e)
def main(): o = options.Options(optspec) (opt, flags, extra) = o.parse(sys.argv[1:]) if opt.version: from sshuttle.version import version print(version) return 0 if opt.daemon: opt.syslog = 1 if opt.wrap: import sshuttle.ssnet as ssnet ssnet.MAX_CHANNEL = int(opt.wrap) helpers.verbose = opt.verbose or 0 try: if opt.firewall: if len(extra) != 0: o.fatal('exactly zero arguments expected') return firewall.main(opt.method, opt.syslog) elif opt.hostwatch: return hostwatch.hw_main(extra) else: if len(extra) < 1 and not opt.auto_nets and not opt.subnets: o.fatal('at least one subnet, subnet file, or -N expected') includes = extra excludes = ['127.0.0.0/8'] for k, v in flags: if k in ('-x', '--exclude'): excludes.append(v) if k in ('-X', '--exclude-from'): excludes += open(v).read().split() remotename = opt.remote if remotename == '' or remotename == '-': remotename = None nslist = [family_ip_tuple(ns) for ns in parse_list(opt.ns_hosts)] if opt.seed_hosts and not opt.auto_hosts: o.fatal('--seed-hosts only works if you also use -H') if opt.seed_hosts: sh = re.split(r'[\s,]+', (opt.seed_hosts or "").strip()) elif opt.auto_hosts: sh = [] else: sh = None if opt.subnets: includes = parse_subnet_file(opt.subnets) if not opt.method: method_name = "auto" elif opt.method in ["auto", "nat", "tproxy", "pf"]: method_name = opt.method else: o.fatal("method_name %s not supported" % opt.method) if opt.listen: ipport_v6 = None ipport_v4 = None list = opt.listen.split(",") for ip in list: if '[' in ip and ']' in ip: ipport_v6 = parse_ipport6(ip) else: ipport_v4 = parse_ipport4(ip) else: # parse_ipport4('127.0.0.1:0') ipport_v4 = "auto" # parse_ipport6('[::1]:0') ipport_v6 = "auto" if not opt.disable_ipv6 else None if opt.syslog: ssyslog.start_syslog() ssyslog.stderr_to_syslog() return_code = client.main(ipport_v6, ipport_v4, opt.ssh_cmd, remotename, opt.python, opt.latency_control, opt.dns, nslist, method_name, sh, opt.auto_nets, parse_subnets(includes), parse_subnets(excludes), opt.daemon, opt.pidfile) if return_code == 0: log('Normal exit code, exiting...') else: log('Abnormal exit code detected, failing...' % return_code) return return_code except Fatal as e: log('fatal: %s\n' % e) return 99 except KeyboardInterrupt: log('\n') log('Keyboard interrupt: exiting.\n') return 1
def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename, python, latency_control, dns_listener, seed_hosts, auto_nets, syslog, daemon): method = fw.method handlers = [] if helpers.verbose >= 1: helpers.logprefix = 'c : ' else: helpers.logprefix = 'client: ' debug1('connecting to server...\n') try: (serverproc, serversock) = ssh.connect( ssh_cmd, remotename, python, stderr=ssyslog._p and ssyslog._p.stdin, options=dict(latency_control=latency_control)) except socket.error as e: if e.args[0] == errno.EPIPE: raise Fatal("failed to establish ssh session (1)") else: raise mux = Mux(serversock, serversock) handlers.append(mux) expected = b'SSHUTTLE0001' try: v = 'x' while v and v != b'\0': v = serversock.recv(1) v = 'x' while v and v != b'\0': v = serversock.recv(1) initstring = serversock.recv(len(expected)) except socket.error as e: if e.args[0] == errno.ECONNRESET: raise Fatal("failed to establish ssh session (2)") else: raise 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((int(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 fw.start() mux.got_routes = onroutes def onhostlist(hostlist): debug2('got host list: %r\n' % hostlist) for line in hostlist.strip().split(): if line: name, ip = line.split(',', 1) fw.sethostip(name, ip) mux.got_host_list = onhostlist tcp_listener.add_handler(handlers, onaccept_tcp, method, mux) if udp_listener: udp_listener.add_handler(handlers, onaccept_udp, method, mux) if dns_listener: dns_listener.add_handler(handlers, ondns, method, mux) if seed_hosts is not None: debug1('seed_hosts: %r\n' % seed_hosts) mux.send(0, ssnet.CMD_HOST_REQ, '\n'.join(seed_hosts)) while 1: rv = serverproc.poll() if rv: raise Fatal('server died with error code %d' % rv) ssnet.runonce(handlers, mux) if latency_control: mux.check_fullness()
def main(method_name, syslog): stdin, stdout = setup_daemon() if method_name == "auto": method = get_auto_method() else: method = get_method(method_name) if syslog: ssyslog.start_syslog() ssyslog.stderr_to_syslog() debug1('firewall manager ready method name %s.\n' % method.name) stdout.write('READY %s\n' % method.name) stdout.flush() # 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 = 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 = stdin.readline(128) if not line: raise Fatal('firewall: expected route but got %r' % line) elif line.startswith("NSLIST\n"): break try: (family, width, exclude, ip) = line.strip().split(',', 3) except: raise Fatal('firewall: expected route or NSLIST but got %r' % line) subnets.append((int(family), int(width), bool(int(exclude)), ip)) debug2('Got subnets: %r\n' % subnets) nslist = [] if line != 'NSLIST\n': raise Fatal('firewall: expected NSLIST but got %r' % line) while 1: line = stdin.readline(128) if not line: raise Fatal('firewall: expected nslist but got %r' % line) elif line.startswith("PORTS "): break try: (family, ip) = line.strip().split(',', 1) except: raise Fatal('firewall: expected nslist or PORTS but got %r' % line) nslist.append((int(family), ip)) debug2('Got partial nslist: %r\n' % nslist) debug2('Got nslist: %r\n' % nslist) if not line.startswith('PORTS '): raise Fatal('firewall: expected PORTS but got %r' % line) _, _, ports = line.partition(" ") ports = ports.split(",") if len(ports) != 4: raise Fatal('firewall: expected 4 ports but got %n' % len(ports)) port_v6 = int(ports[0]) port_v4 = int(ports[1]) dnsport_v6 = int(ports[2]) dnsport_v4 = int(ports[3]) 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) debug2('Got ports: %d,%d,%d,%d\n' % (port_v6, port_v4, dnsport_v6, dnsport_v4)) line = stdin.readline(128) if not line: raise Fatal('firewall: expected GO but got %r' % line) elif not line.startswith("GO "): raise Fatal('firewall: expected GO but got %r' % line) _, _, udp = line.partition(" ") udp = bool(int(udp)) debug2('Got udp: %r\n' % udp) try: do_wait = None debug1('firewall manager: starting transproxy.\n') nslist_v6 = [i for i in nslist if i[0] == socket.AF_INET6] subnets_v6 = [i for i in subnets if i[0] == socket.AF_INET6] if port_v6 > 0: do_wait = method.setup_firewall(port_v6, dnsport_v6, nslist_v6, socket.AF_INET6, subnets_v6, udp) elif len(subnets_v6) > 0: debug1("IPv6 subnets defined but IPv6 disabled\n") nslist_v4 = [i for i in nslist if i[0] == socket.AF_INET] subnets_v4 = [i for i in subnets if i[0] == socket.AF_INET] if port_v4 > 0: do_wait = method.setup_firewall(port_v4, dnsport_v4, nslist_v4, socket.AF_INET, subnets_v4, udp) elif len(subnets_v4) > 0: debug1('IPv4 subnets defined but IPv4 disabled\n') stdout.write('STARTED\n') try: 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 is not None: do_wait() line = 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: if not method.firewall_command(line): raise Fatal('expected EOF, got %r' % line) else: break finally: try: debug1('firewall manager: undoing changes.\n') except: pass if port_v6: method.setup_firewall(port_v6, 0, [], socket.AF_INET6, [], udp) if port_v4: method.setup_firewall(port_v4, 0, [], socket.AF_INET, [], udp) restore_etc_hosts(port_v6 or port_v4)
ipport_v6 = None ipport_v4 = None list = opt.listen.split(",") for ip in list: if '[' in ip and ']' in ip: ipport_v6 = parse_ipport6(ip) else: ipport_v4 = parse_ipport4(ip) else: # parse_ipport4('127.0.0.1:0') ipport_v4 = "auto" # parse_ipport6('[::1]:0') ipport_v6 = "auto" if not opt.disable_ipv6 else None if opt.syslog: ssyslog.start_syslog() ssyslog.stderr_to_syslog() return_code = client.main(ipport_v6, ipport_v4, opt.ssh_cmd, remotename, opt.python, opt.latency_control, opt.dns, nslist, method_name, sh, opt.auto_nets, parse_subnets(includes), parse_subnets(excludes), opt.daemon, opt.pidfile) if return_code == 0: