Exemplo n.º 1
0
def pfctl(*args):
    # TODO: pretty sure this doesn't work. Need to research how pf works.
    argv = ['pfctl', '-q', ] + list(args)
    debug1('>> %s\n' % ' '.join(argv))
    rv = ssubprocess.call(argv)
    if rv:
        raise Fatal('%r returned %d' % (argv, rv))
Exemplo n.º 2
0
 def print_listening(self, what):
     if self.v6:
         listenip = self.v6.getsockname()
         debug1('%s listening on %r.\n' % (what, listenip))
     if self.v4:
         listenip = self.v4.getsockname()
         debug1('%s listening on %r.\n' % (what, listenip))
Exemplo n.º 3
0
 def print_listening(self, what):
     if self.v6:
         listenip = self.v6.getsockname()
         debug1('%s listening on %r.\n' % (what, listenip))
     if self.v4:
         listenip = self.v4.getsockname()
         debug1('%s listening on %r.\n' % (what, listenip))
Exemplo n.º 4
0
def _ipt(family, table, *args):
    if family == socket.AF_INET6:
        argv = ['ip6tables', '-t', table] + list(args)
    elif family == socket.AF_INET:
        argv = ['iptables', '-t', table] + list(args)
    else:
        raise Exception('Unsupported family "%s"' % family_to_string(family))
    debug1('>> %s\n' % ' '.join(argv))
    rv = ssubprocess.call(argv)
    if rv:
        raise Fatal('%r returned %d' % (argv, rv))
Exemplo n.º 5
0
def _ipt(family, table, *args):
    if family == socket.AF_INET6:
        argv = ['ip6tables', '-t', table] + list(args)
    elif family == socket.AF_INET:
        argv = ['iptables', '-t', table] + list(args)
    else:
        raise Exception('Unsupported family "%s"' % family_to_string(family))
    debug1('>> %s\n' % ' '.join(argv))
    rv = ssubprocess.call(argv)
    if rv:
        raise Fatal('%r returned %d' % (argv, rv))
Exemplo n.º 6
0
def found_host(hostname, ip):
    hostname = re.sub(r'\..*', '', hostname)
    hostname = re.sub(r'[^-\w]', '_', hostname)
    if (ip.startswith('127.') or ip.startswith('255.')
            or hostname == 'localhost'):
        return
    oldip = hostnames.get(hostname)
    if oldip != ip:
        hostnames[hostname] = ip
        debug1('Found: %s: %s\n' % (hostname, ip))
        sys.stdout.write('%s,%s\n' % (hostname, ip))
        write_host_cache()
Exemplo n.º 7
0
def found_host(hostname, ip):
    hostname = re.sub(r'\..*', '', hostname)
    hostname = re.sub(r'[^-\w]', '_', hostname)
    if (ip.startswith('127.') or ip.startswith('255.')
            or hostname == 'localhost'):
        return
    oldip = hostnames.get(hostname)
    if oldip != ip:
        hostnames[hostname] = ip
        debug1('Found: %s: %s\n' % (hostname, ip))
        sys.stdout.write('%s,%s\n' % (hostname, ip))
        write_host_cache()
Exemplo n.º 8
0
 def size(self):
     """Get this file's size."""
     if self._cached_size == None:
         debug1('<<<<File.size() is calculating (for %r)...\n' % self.name)
         if self.bupmode == git.BUP_CHUNKED:
             self._cached_size = _total_size(self.hash,
                                             repo_dir = self._repo_dir)
         else:
             self._cached_size = _chunk_len(self.hash,
                                            repo_dir = self._repo_dir)
         debug1('<<<<File.size() done.\n')
     return self._cached_size
Exemplo n.º 9
0
def pfctl(args, stdin = None):
    argv = ['pfctl'] + list(args.split(" "))
    debug1('>> %s\n' % ' '.join(argv))

    p = ssubprocess.Popen(argv, stdin = ssubprocess.PIPE, 
                                stdout = ssubprocess.PIPE, 
                                stderr = ssubprocess.PIPE)
    o = p.communicate(stdin)
    if p.returncode:
        raise Fatal('%r returned %d' % (argv, p.returncode))

    return o
Exemplo n.º 10
0
def udp_done(chan, data, method, family, dstip):
    (src, srcport, data) = data.split(",", 2)
    srcip = (src, int(srcport))
    debug3('doing send from %r to %r\n' % (srcip, dstip,))

    try:
        sender = socket.socket(family, socket.SOCK_DGRAM)
        sender.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sender.setsockopt(socket.SOL_IP, IP_TRANSPARENT, 1)
        sender.bind(srcip)
        sender.sendto(data, dstip)
        sender.close()
    except socket.error, e:
        debug1('-- ignored socket error sending UDP data: %r\n' % e)
Exemplo n.º 11
0
def ondns(listener, method, mux, handlers):
    now = time.time()
    srcip, dstip, data = recv_udp(listener, 4096)
    if method == "tproxy" and not dstip:
        debug1("-- ignored UDP from %r: "
               "couldn't determine destination IP address\n" % (srcip, ))
        return
    debug1('DNS request from %r to %r: %d bytes\n' % (srcip, dstip, len(data)))
    chan = mux.next_channel()
    dnsreqs[chan] = now + 30
    mux.send(chan, ssnet.CMD_DNS_REQ, data)
    mux.channels[chan] = lambda cmd, data: dns_done(
        chan, data, method, listener, srcip=dstip, dstip=srcip, mux=mux)
    expire_connections(now, mux)
Exemplo n.º 12
0
 def uwrite(self, buf):
     if self.connect_to:
         return 0  # still connecting
     self.wsock.setblocking(False)
     try:
         return _nb_clean(os.write, self.wsock.fileno(), buf)
     except OSError, e:
         if e.errno == errno.EPIPE:
             debug1('%r: uwrite: got EPIPE\n' % self)
             self.nowrite()
             return 0
         else:
             # unexpected error... stream is dead
             self.seterr('uwrite: %s' % e)
             return 0
Exemplo n.º 13
0
def ondns(listener, method, mux, handlers):
    now = time.time()
    srcip, dstip, data = recv_udp(listener, 4096)
    if method == "tproxy" and not dstip:
        debug1(
            "-- ignored UDP from %r: "
            "couldn't determine destination IP address\n" % (srcip,))
        return
    debug1('DNS request from %r to %r: %d bytes\n' % (srcip, dstip, len(data)))
    chan = mux.next_channel()
    dnsreqs[chan] = now + 30
    mux.send(chan, ssnet.CMD_DNS_REQ, data)
    mux.channels[chan] = lambda cmd, data: dns_done(
        chan, data, method, listener, srcip=dstip, dstip=srcip, mux=mux)
    expire_connections(now, mux)
Exemplo n.º 14
0
def onaccept_tcp(listener, method, mux, handlers):
    global _extra_fd
    try:
        sock, srcip = listener.accept()
    except socket.error, e:
        if e.args[0] in [errno.EMFILE, errno.ENFILE]:
            debug1('Rejected incoming connection: too many open files!\n')
            # free up an fd so we can eat the connection
            os.close(_extra_fd)
            try:
                sock, srcip = listener.accept()
                sock.close()
            finally:
                _extra_fd = os.open('/dev/null', os.O_RDONLY)
            return
        else:
            raise
Exemplo n.º 15
0
def onaccept_tcp(listener, method, mux, handlers):
    global _extra_fd
    try:
        sock, srcip = listener.accept()
    except socket.error, e:
        if e.args[0] in [errno.EMFILE, errno.ENFILE]:
            debug1('Rejected incoming connection: too many open files!\n')
            # free up an fd so we can eat the connection
            os.close(_extra_fd)
            try:
                sock, srcip = listener.accept()
                sock.close()
            finally:
                _extra_fd = os.open('/dev/null', os.O_RDONLY)
            return
        else:
            raise
Exemplo n.º 16
0
def udp_done(chan, data, method, family, dstip):
    (src, srcport, data) = data.split(",", 2)
    srcip = (src, int(srcport))
    debug3('doing send from %r to %r\n' % (
        srcip,
        dstip,
    ))

    try:
        sender = socket.socket(family, socket.SOCK_DGRAM)
        sender.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sender.setsockopt(socket.SOL_IP, IP_TRANSPARENT, 1)
        sender.bind(srcip)
        sender.sendto(data, dstip)
        sender.close()
    except socket.error, e:
        debug1('-- ignored socket error sending UDP data: %r\n' % e)
Exemplo n.º 17
0
def sysctl_set(name, val, permanent=False):
    PREFIX = 'net.inet.ip'
    assert (name.startswith(PREFIX + '.'))
    val = str(val)
    if not _oldctls:
        _fill_oldctls(PREFIX)
    if not (name in _oldctls):
        debug1('>> No such sysctl: %r\n' % name)
        return False
    oldval = _oldctls[name]
    if val != oldval:
        rv = _sysctl_set(name, val)
        if rv == 0 and permanent:
            debug1('>>   ...saving permanently in /etc/sysctl.conf\n')
            f = open('/etc/sysctl.conf', 'a')
            f.write('\n' '# Added by sshuttle\n' '%s=%s\n' % (name, val))
            f.close()
        else:
            _changedctls.append(name)
        return True
Exemplo n.º 18
0
def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename,
          python, latency_control,
          dns_listener, method, seed_hosts, auto_nets,
          syslog, daemon):
    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, method=method))
    except socket.error, e:
        if e.args[0] == errno.EPIPE:
            raise Fatal("failed to establish ssh session (1)")
        else:
            raise
Exemplo n.º 19
0
def sysctl_set(name, val, permanent=False):
    PREFIX = 'net.inet.ip'
    assert(name.startswith(PREFIX + '.'))
    val = str(val)
    if not _oldctls:
        _fill_oldctls(PREFIX)
    if not (name in _oldctls):
        debug1('>> No such sysctl: %r\n' % name)
        return False
    oldval = _oldctls[name]
    if val != oldval:
        rv = _sysctl_set(name, val)
        if rv == 0 and permanent:
            debug1('>>   ...saving permanently in /etc/sysctl.conf\n')
            f = open('/etc/sysctl.conf', 'a')
            f.write('\n'
                    '# Added by sshuttle\n'
                    '%s=%s\n' % (name, val))
            f.close()
        else:
            _changedctls.append(name)
        return True
Exemplo n.º 20
0
def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename, python,
          latency_control, dns_listener, method, seed_hosts, auto_nets, syslog,
          daemon):
    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, method=method))
    except socket.error, e:
        if e.args[0] == errno.EPIPE:
            raise Fatal("failed to establish ssh session (1)")
        else:
            raise
Exemplo n.º 21
0
def onaccept_udp(listener, method, mux, handlers):
    now = time.time()
    srcip, dstip, data = recv_udp(listener, 4096)
    if not dstip:
        debug1(
            "-- ignored UDP from %r: "
            "couldn't determine destination IP address\n" % (srcip,))
        return
    debug1('Accept UDP: %r -> %r.\n' % (srcip, dstip,))
    if srcip in udp_by_src:
        chan, timeout = udp_by_src[srcip]
    else:
        chan = mux.next_channel()
        mux.channels[chan] = lambda cmd, data: udp_done(
            chan, data, method, listener.family, dstip=srcip)
        mux.send(chan, ssnet.CMD_UDP_OPEN, listener.family)
    udp_by_src[srcip] = chan, now + 30

    hdr = "%s,%r," % (dstip[0], dstip[1])
    mux.send(chan, ssnet.CMD_UDP_DATA, hdr + data)

    expire_connections(now, mux)
Exemplo n.º 22
0
def onaccept_udp(listener, method, mux, handlers):
    now = time.time()
    srcip, dstip, data = recv_udp(listener, 4096)
    if not dstip:
        debug1("-- ignored UDP from %r: "
               "couldn't determine destination IP address\n" % (srcip, ))
        return
    debug1('Accept UDP: %r -> %r.\n' % (
        srcip,
        dstip,
    ))
    if srcip in udp_by_src:
        chan, timeout = udp_by_src[srcip]
    else:
        chan = mux.next_channel()
        mux.channels[chan] = lambda cmd, data: udp_done(
            chan, data, method, listener.family, dstip=srcip)
        mux.send(chan, ssnet.CMD_UDP_OPEN, listener.family)
    udp_by_src[srcip] = chan, now + 30

    hdr = "%s,%r," % (dstip[0], dstip[1])
    mux.send(chan, ssnet.CMD_UDP_DATA, hdr + data)

    expire_connections(now, mux)
Exemplo n.º 23
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, pf, or iptables; 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:
                raise Fatal('expected EOF, got %r' % line)
            else:
                break
    finally:
        try:
            debug1('firewall manager: undoing changes.\n')
        except:
            pass
        if port_v6:
            do_it(port_v6, 0, socket.AF_INET6, [], udp)
        if port_v4:
            do_it(port_v4, 0, socket.AF_INET, [], udp)
        restore_etc_hosts(port_v6 or port_v4)
Exemplo n.º 24
0
        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:
                break
    finally:
        try:
            debug1('firewall manager: undoing changes.\n')
        except:
            pass
        if port_v6:
            do_it(port_v6, 0, socket.AF_INET6, [], udp)
        if port_v4:
            do_it(port_v4, 0, socket.AF_INET, [], udp)
        restore_etc_hosts(port_v6 or port_v4)
Exemplo n.º 25
0
def _sysctl_set(name, val):
    argv = ['sysctl', '-w', '%s=%s' % (name, val)]
    debug1('>> %s\n' % ' '.join(argv))
    return ssubprocess.call(argv, stdout=open('/dev/null', 'w'))
Exemplo n.º 26
0
def ipfw(*args):
    argv = ['ipfw', '-q'] + list(args)
    debug1('>> %s\n' % ' '.join(argv))
    rv = ssubprocess.call(argv)
    if rv:
        raise Fatal('%r returned %d' % (argv, rv))
Exemplo n.º 27
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:
Exemplo n.º 28
0
            os.close(_extra_fd)
            try:
                sock, srcip = listener.accept()
                sock.close()
            finally:
                _extra_fd = os.open('/dev/null', os.O_RDONLY)
            return
        else:
            raise
    if method == "tproxy":
        dstip = sock.getsockname()
    elif method == "pf":
        dstip = pf_dst(sock)
    else:
        dstip = original_dst(sock)
    debug1('Accept TCP: %s:%r -> %s:%r.\n' %
           (srcip[0], srcip[1], dstip[0], dstip[1]))
    if dstip[1] == sock.getsockname()[1] and islocal(dstip[0], sock.family):
        debug1("-- ignored: that's my address!\n")
        sock.close()
        return
    chan = mux.next_channel()
    if not chan:
        log('warning: too many open channels.  Discarded connection.\n')
        sock.close()
        return
    mux.send(chan, ssnet.CMD_TCP_CONNECT,
             '%d,%s,%s' % (sock.family, dstip[0], dstip[1]))
    outwrap = MuxWrapper(mux, chan)
    handlers.append(Proxy(SockWrapper(sock, sock), outwrap))
    expire_connections(time.time(), mux)
Exemplo n.º 29
0
def main():
    if helpers.verbose >= 1:
        helpers.logprefix = ' s: '
    else:
        helpers.logprefix = 'server: '
    assert latency_control is not None
    debug1('latency control setting = %r\n' % latency_control)

    routes = list(list_routes())
    debug1('available routes:\n')
    for r in routes:
        debug1('  %d/%s/%d\n' % r)

    # synchronization header
    sys.stdout.write('\0\0SSHUTTLE0001')
    sys.stdout.flush()

    handlers = []
    mux = Mux(socket.fromfd(sys.stdin.fileno(),
                            socket.AF_INET, socket.SOCK_STREAM),
              socket.fromfd(sys.stdout.fileno(),
                            socket.AF_INET, socket.SOCK_STREAM))
    handlers.append(mux)
    routepkt = ''
    for r in routes:
        routepkt += '%d,%s,%d\n' % r
    mux.send(0, ssnet.CMD_ROUTES, routepkt)

    hw = Hostwatch()
    hw.leftover = ''

    def hostwatch_ready():
        assert(hw.pid)
        content = hw.sock.recv(4096)
        if content:
            lines = (hw.leftover + content).split('\n')
            if lines[-1]:
                # no terminating newline: entry isn't complete yet!
                hw.leftover = lines.pop()
                lines.append('')
            else:
                hw.leftover = ''
            mux.send(0, ssnet.CMD_HOST_LIST, '\n'.join(lines))
        else:
            raise Fatal('hostwatch process died')

    def got_host_req(data):
        if not hw.pid:
            (hw.pid, hw.sock) = start_hostwatch(data.strip().split())
            handlers.append(Handler(socks=[hw.sock],
                                    callback=hostwatch_ready))
    mux.got_host_req = got_host_req

    def new_channel(channel, data):
        (family, dstip, dstport) = data.split(',', 2)
        family = int(family)
        dstport = int(dstport)
        outwrap = ssnet.connect_dst(family, dstip, dstport)
        handlers.append(Proxy(MuxWrapper(mux, channel), outwrap))
    mux.new_channel = new_channel

    dnshandlers = {}

    def dns_req(channel, data):
        debug2('Incoming DNS request channel=%d.\n' % channel)
        h = DnsProxy(mux, channel, data)
        handlers.append(h)
        dnshandlers[channel] = h
    mux.got_dns_req = dns_req

    udphandlers = {}

    def udp_req(channel, cmd, data):
        debug2('Incoming UDP request channel=%d, cmd=%d\n' % (channel, cmd))
        if cmd == ssnet.CMD_UDP_DATA:
            (dstip, dstport, data) = data.split(",", 2)
            dstport = int(dstport)
            debug2('is incoming UDP data. %r %d.\n' % (dstip, dstport))
            h = udphandlers[channel]
            h.send((dstip, dstport), data)
        elif cmd == ssnet.CMD_UDP_CLOSE:
            debug2('is incoming UDP close\n')
            h = udphandlers[channel]
            h.ok = False
            del mux.channels[channel]

    def udp_open(channel, data):
        debug2('Incoming UDP open.\n')
        family = int(data)
        mux.channels[channel] = lambda cmd, data: udp_req(channel, cmd, data)
        if channel in udphandlers:
            raise Fatal('UDP connection channel %d already open' % channel)
        else:
            h = UdpProxy(mux, channel, family)
            handlers.append(h)
            udphandlers[channel] = h
    mux.got_udp_open = udp_open

    while mux.ok:
        if hw.pid:
            assert(hw.pid > 0)
            (rpid, rv) = os.waitpid(hw.pid, os.WNOHANG)
            if rpid:
                raise Fatal(
                    'hostwatch exited unexpectedly: code 0x%04x\n' % rv)

        ssnet.runonce(handlers, mux)
        if latency_control:
            mux.check_fullness()
        mux.callback()

        if dnshandlers:
            now = time.time()
            for channel, h in dnshandlers.items():
                if h.timeout < now or not h.ok:
                    debug3('expiring dnsreqs channel=%d\n' % channel)
                    del dnshandlers[channel]
                    h.ok = False
        if udphandlers:
            for channel, h in udphandlers.items():
                if not h.ok:
                    debug3('expiring UDP channel=%d\n' % channel)
                    del udphandlers[channel]
                    h.ok = False
Exemplo n.º 30
0
def _sysctl_set(name, val):
    argv = ['sysctl', '-w', '%s=%s' % (name, val)]
    debug1('>> %s\n' % ' '.join(argv))
    return ssubprocess.call(argv, stdout=open('/dev/null', 'w'))
Exemplo n.º 31
0
def ipfw(*args):
    argv = ['ipfw', '-q'] + list(args)
    debug1('>> %s\n' % ' '.join(argv))
    rv = ssubprocess.call(argv)
    if rv:
        raise Fatal('%r returned %d' % (argv, rv))
Exemplo n.º 32
0
 def __del__(self):
     global _swcount
     _swcount -= 1
     debug1('%r: deleting (%d remain)\n' % (self, _swcount))
     if self.exc:
         debug1('%r: error was: %s\n' % (self, self.exc))
Exemplo n.º 33
0
def main():
    if helpers.verbose >= 1:
        helpers.logprefix = ' s: '
    else:
        helpers.logprefix = 'server: '
    assert latency_control is not None
    debug1('latency control setting = %r\n' % latency_control)

    routes = list(list_routes())
    debug1('available routes:\n')
    for r in routes:
        debug1('  %d/%s/%d\n' % r)

    # synchronization header
    sys.stdout.write('\0\0SSHUTTLE0001')
    sys.stdout.flush()

    handlers = []
    mux = Mux(
        socket.fromfd(sys.stdin.fileno(), socket.AF_INET, socket.SOCK_STREAM),
        socket.fromfd(sys.stdout.fileno(), socket.AF_INET, socket.SOCK_STREAM))
    handlers.append(mux)
    routepkt = ''
    for r in routes:
        routepkt += '%d,%s,%d\n' % r
    mux.send(0, ssnet.CMD_ROUTES, routepkt)

    hw = Hostwatch()
    hw.leftover = ''

    def hostwatch_ready():
        assert (hw.pid)
        content = hw.sock.recv(4096)
        if content:
            lines = (hw.leftover + content).split('\n')
            if lines[-1]:
                # no terminating newline: entry isn't complete yet!
                hw.leftover = lines.pop()
                lines.append('')
            else:
                hw.leftover = ''
            mux.send(0, ssnet.CMD_HOST_LIST, '\n'.join(lines))
        else:
            raise Fatal('hostwatch process died')

    def got_host_req(data):
        if not hw.pid:
            (hw.pid, hw.sock) = start_hostwatch(data.strip().split())
            handlers.append(Handler(socks=[hw.sock], callback=hostwatch_ready))

    mux.got_host_req = got_host_req

    def new_channel(channel, data):
        (family, dstip, dstport) = data.split(',', 2)
        family = int(family)
        dstport = int(dstport)
        outwrap = ssnet.connect_dst(family, dstip, dstport)
        handlers.append(Proxy(MuxWrapper(mux, channel), outwrap))

    mux.new_channel = new_channel

    dnshandlers = {}

    def dns_req(channel, data):
        debug2('Incoming DNS request channel=%d.\n' % channel)
        h = DnsProxy(mux, channel, data)
        handlers.append(h)
        dnshandlers[channel] = h

    mux.got_dns_req = dns_req

    udphandlers = {}

    def udp_req(channel, cmd, data):
        debug2('Incoming UDP request channel=%d, cmd=%d\n' % (channel, cmd))
        if cmd == ssnet.CMD_UDP_DATA:
            (dstip, dstport, data) = data.split(",", 2)
            dstport = int(dstport)
            debug2('is incoming UDP data. %r %d.\n' % (dstip, dstport))
            h = udphandlers[channel]
            h.send((dstip, dstport), data)
        elif cmd == ssnet.CMD_UDP_CLOSE:
            debug2('is incoming UDP close\n')
            h = udphandlers[channel]
            h.ok = False
            del mux.channels[channel]

    def udp_open(channel, data):
        debug2('Incoming UDP open.\n')
        family = int(data)
        mux.channels[channel] = lambda cmd, data: udp_req(channel, cmd, data)
        if channel in udphandlers:
            raise Fatal('UDP connection channel %d already open' % channel)
        else:
            h = UdpProxy(mux, channel, family)
            handlers.append(h)
            udphandlers[channel] = h

    mux.got_udp_open = udp_open

    while mux.ok:
        if hw.pid:
            assert (hw.pid > 0)
            (rpid, rv) = os.waitpid(hw.pid, os.WNOHANG)
            if rpid:
                raise Fatal('hostwatch exited unexpectedly: code 0x%04x\n' %
                            rv)

        ssnet.runonce(handlers, mux)
        if latency_control:
            mux.check_fullness()
        mux.callback()

        if dnshandlers:
            now = time.time()
            for channel, h in dnshandlers.items():
                if h.timeout < now or not h.ok:
                    debug3('expiring dnsreqs channel=%d\n' % channel)
                    del dnshandlers[channel]
                    h.ok = False
        if udphandlers:
            for channel, h in udphandlers.items():
                if not h.ok:
                    debug3('expiring UDP channel=%d\n' % channel)
                    del udphandlers[channel]
                    h.ok = False
Exemplo n.º 34
0
            debug1('Rejected incoming connection: too many open files!\n')
            # free up an fd so we can eat the connection
            os.close(_extra_fd)
            try:
                sock, srcip = listener.accept()
                sock.close()
            finally:
                _extra_fd = os.open('/dev/null', os.O_RDONLY)
            return
        else:
            raise
    if method == "tproxy":
        dstip = sock.getsockname()
    else:
        dstip = original_dst(sock)
    debug1('Accept TCP: %s:%r -> %s:%r.\n' % (srcip[0], srcip[1],
                                              dstip[0], dstip[1]))
    if dstip[1] == sock.getsockname()[1] and islocal(dstip[0], sock.family):
        debug1("-- ignored: that's my address!\n")
        sock.close()
        return
    chan = mux.next_channel()
    if not chan:
        log('warning: too many open channels.  Discarded connection.\n')
        sock.close()
        return
    mux.send(chan, ssnet.CMD_TCP_CONNECT, '%d,%s,%s' %
             (sock.family, dstip[0], dstip[1]))
    outwrap = MuxWrapper(mux, chan)
    handlers.append(Proxy(SockWrapper(sock, sock), outwrap))
    expire_connections(time.time(), mux)