import re import socket import sshuttle.helpers as helpers import sshuttle.client as client import sshuttle.firewall as firewall import sshuttle.hostwatch as hostwatch import sshuttle.ssyslog as ssyslog from sshuttle.options import parser, parse_ipport from sshuttle.helpers import family_ip_tuple, log, Fatal from sshuttle.sudoers import sudoers def main(): opt = parser.parse_args() if opt.sudoers_no_modify: # sudoers() calls exit() when it completes sudoers(user_name=opt.sudoers_user) 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: hostwatch.hw_main(opt.subnets, opt.auto_hosts) return 0 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 try: int(opt.tmark, 16) except ValueError: parser.error("--tmark must be a hexadecimal value") opt.tmark = opt.tmark.lower() # make 'x' in 0x lowercase if not opt.tmark.startswith("0x"): # accept without 0x prefix opt.tmark = "0x%s" % opt.tmark 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.latency_buffer_size, opt.dns, nslist, opt.method, sh, opt.auto_hosts, opt.auto_nets, includes, excludes, opt.daemon, opt.to_ns, opt.pidfile, opt.user, opt.group, opt.sudo_pythonpath, opt.tmark) 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' % e) return 99 except KeyboardInterrupt: log('\n') log('Keyboard interrupt: exiting.') return 1