Ejemplo n.º 1
0
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()
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
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: