Пример #1
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp):
        tables = []
        translating_rules = []
        filtering_rules = []

        if family != socket.AF_INET:
            raise Exception(
                'Address family "%s" unsupported by pf method_name'
                % family_to_string(family))
        if udp:
            raise Exception("UDP not supported by pf method_name")

        if len(subnets) > 0:
            includes = []
            # If a given subnet is both included and excluded, list the
            # exclusion first; the table will ignore the second, opposite
            # definition
            for f, swidth, sexclude, snet in sorted(
                    subnets, key=lambda s: (s[1], s[2]), reverse=True):
                includes.append(b"%s%s/%d" %
                                (b"!" if sexclude else b"",
                                    snet.encode("ASCII"),
                                    swidth))

        anchor = 'sshuttle-%d' % port
        pf.add_anchors(anchor)
        pf.add_rules(anchor, includes, port, dnsport, nslist)
        pf.enable()
Пример #2
0
    def restore_firewall(self, port, family, udp):
        # only ipv4 supported with NAT
        if family != socket.AF_INET:
            raise Exception(
                'Address family "%s" unsupported by nat method_name'
                % family_to_string(family))
        if udp:
            raise Exception("UDP not supported by nat method_name")

        table = "nat"

        def _ipt(*args):
            return ipt(family, table, *args)

        def _ipt_ttl(*args):
            return ipt_ttl(family, table, *args)

        chain = 'sshuttle-%s' % port

        # basic cleanup/setup of chains
        if ipt_chain_exists(family, table, chain):
            nonfatal(_ipt, '-D', 'OUTPUT', '-j', chain)
            nonfatal(_ipt, '-D', 'PREROUTING', '-j', chain)
            nonfatal(_ipt, '-F', chain)
            _ipt('-X', chain)
Пример #3
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
                       user):
        # only ipv4 supported with NAT
        if family != socket.AF_INET:
            raise Exception(
                'Address family "%s" unsupported by nat method_name'
                % family_to_string(family))
        if udp:
            raise Exception("UDP not supported by nat method_name")

        table = "nat"

        def _ipt(*args):
            return ipt(family, table, *args)

        def _ipt_ttl(*args):
            return ipt_ttl(family, table, *args)

        def _ipm(*args):
            return ipt(family, "mangle", *args)

        chain = 'sshuttle-%s' % port

        # basic cleanup/setup of chains
        self.restore_firewall(port, family, udp, user)

        _ipt('-N', chain)
        _ipt('-F', chain)
        if user is not None:
            _ipm('-I', 'OUTPUT', '1', '-m', 'owner', '--uid-owner', str(user),
                 '-j', 'MARK', '--set-mark', str(port))
            args = '-m', 'mark', '--mark', str(port), '-j', chain
        else:
            args = '-j', chain

        _ipt('-I', 'OUTPUT', '1', *args)
        _ipt('-I', 'PREROUTING', '1', *args)

        # create new subnet entries.
        for _, swidth, sexclude, snet, fport, lport \
                in sorted(subnets, key=subnet_weight, reverse=True):
            tcp_ports = ('-p', 'tcp')
            if fport:
                tcp_ports = tcp_ports + ('--dport', '%d:%d' % (fport, lport))

            if sexclude:
                _ipt('-A', chain, '-j', 'RETURN',
                     '--dest', '%s/%s' % (snet, swidth),
                     *tcp_ports)
            else:
                _ipt_ttl('-A', chain, '-j', 'REDIRECT',
                         '--dest', '%s/%s' % (snet, swidth),
                         *(tcp_ports + ('--to-ports', str(port))))

        for _, ip in [i for i in nslist if i[0] == family]:
            _ipt_ttl('-A', chain, '-j', 'REDIRECT',
                     '--dest', '%s/32' % ip,
                     '-p', 'udp',
                     '--dport', '53',
                     '--to-ports', str(dnsport))
Пример #4
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp):
        tables = []
        translating_rules = []
        filtering_rules = []

        if family != socket.AF_INET:
            raise Exception(
                'Address family "%s" unsupported by pf method_name' %
                family_to_string(family))
        if udp:
            raise Exception("UDP not supported by pf method_name")

        if len(subnets) > 0:
            includes = []
            # If a given subnet is both included and excluded, list the
            # exclusion first; the table will ignore the second, opposite
            # definition
            for f, swidth, sexclude, snet in sorted(subnets,
                                                    key=lambda s: (s[1], s[2]),
                                                    reverse=True):
                includes.append(
                    b"%s%s/%d" %
                    (b"!" if sexclude else b"", snet.encode("ASCII"), swidth))

        pf.add_anchors()
        pf.add_rules(includes, port, dnsport, nslist)
        pf.enable()
Пример #5
0
    def restore_firewall(self, port, family, udp, user):
        if family not in [socket.AF_INET, socket.AF_INET6]:
            raise Exception(
                'Address family "%s" unsupported by tproxy method' %
                family_to_string(family))

        table = "mangle"

        def _ipt(*args):
            return ipt(family, table, *args)

        def _ipt_ttl(*args):
            return ipt_ttl(family, table, *args)

        mark_chain = 'sshuttle-m-%s' % port
        tproxy_chain = 'sshuttle-t-%s' % port
        divert_chain = 'sshuttle-d-%s' % port

        # basic cleanup/setup of chains
        if ipt_chain_exists(family, table, mark_chain):
            _ipt('-D', 'OUTPUT', '-j', mark_chain)
            _ipt('-F', mark_chain)
            _ipt('-X', mark_chain)

        if ipt_chain_exists(family, table, tproxy_chain):
            _ipt('-D', 'PREROUTING', '-j', tproxy_chain)
            _ipt('-F', tproxy_chain)
            _ipt('-X', tproxy_chain)

        if ipt_chain_exists(family, table, divert_chain):
            _ipt('-F', divert_chain)
            _ipt('-X', divert_chain)
Пример #6
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
                       user):
        if family not in [socket.AF_INET, socket.AF_INET6]:
            raise Exception(
                'Address family "%s" unsupported by pf method_name'
                % family_to_string(family))
        if udp:
            raise Exception("UDP not supported by pf method_name")

        if subnets:
            includes = []
            # If a given subnet is both included and excluded, list the
            # exclusion first; the table will ignore the second, opposite
            # definition
            for _, swidth, sexclude, snet, fport, lport \
                    in sorted(subnets, key=subnet_weight):
                includes.append((sexclude, b"%s/%d%s" % (
                    snet.encode("ASCII"),
                    swidth,
                    b" port %d:%d" % (fport, lport) if fport else b"")))

        anchor = pf_get_anchor(family, port)
        pf.add_anchors(anchor)
        pf.add_rules(anchor, includes, port, dnsport, nslist, family)
        pf.enable()
Пример #7
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp):
        tables = []
        translating_rules = []
        filtering_rules = []

        if family != socket.AF_INET:
            raise Exception(
                'Address family "%s" unsupported by pf method_name' %
                family_to_string(family))
        if udp:
            raise Exception("UDP not supported by pf method_name")

        if len(subnets) > 0:
            includes = []
            # If a given subnet is both included and excluded, list the
            # exclusion first; the table will ignore the second, opposite
            # definition
            for f, swidth, sexclude, snet in sorted(subnets,
                                                    key=lambda s: (s[1], s[2]),
                                                    reverse=True):
                includes.append(
                    b"%s%s/%d" %
                    (b"!" if sexclude else b"", snet.encode("ASCII"), swidth))

            tables.append(b'table <forward_subnets> {%s}' %
                          b','.join(includes))
            translating_rules.append(
                b'rdr pass on lo0 proto tcp '
                b'to <forward_subnets> -> 127.0.0.1 port %r' % port)
            filtering_rules.append(b'pass out route-to lo0 inet proto tcp '
                                   b'to <forward_subnets> keep state')

        if len(nslist) > 0:
            tables.append(b'table <dns_servers> {%s}' %
                          b','.join([ns[1].encode("ASCII") for ns in nslist]))
            translating_rules.append(
                b'rdr pass on lo0 proto udp to '
                b'<dns_servers> port 53 -> 127.0.0.1 port %r' % dnsport)
            filtering_rules.append(b'pass out route-to lo0 inet proto udp to '
                                   b'<dns_servers> port 53 keep state')

        rules = b'\n'.join(tables + translating_rules + filtering_rules) \
                + b'\n'
        assert isinstance(rules, bytes)
        debug3("rules:\n" + rules.decode("ASCII"))

        pf_status = pfctl('-s all')[0]
        if b'\nrdr-anchor "sshuttle" all\n' not in pf_status:
            pf_add_anchor_rule(osdefs.PF_RDR, b"sshuttle")
        if b'\nanchor "sshuttle" all\n' not in pf_status:
            pf_add_anchor_rule(osdefs.PF_PASS, b"sshuttle")

        pfctl('-a sshuttle -f /dev/stdin', rules)
        if osdefs.platform == "darwin":
            o = pfctl('-E')
            _pf_context['Xtoken'] = \
                re.search(b'Token : (.+)', o[1]).group(1)
        elif b'INFO:\nStatus: Disabled' in pf_status:
            pfctl('-e')
            _pf_context['started_by_sshuttle'] = True
Пример #8
0
    def restore_firewall(self, port, family, udp):
        if family not in [socket.AF_INET, socket.AF_INET6]:
            raise Exception(
                'Address family "%s" unsupported by tproxy method'
                % family_to_string(family))

        table = "mangle"

        def _ipt(*args):
            return ipt(family, table, *args)

        def _ipt_ttl(*args):
            return ipt_ttl(family, table, *args)

        mark_chain = 'sshuttle-m-%s' % port
        tproxy_chain = 'sshuttle-t-%s' % port
        divert_chain = 'sshuttle-d-%s' % port

        # basic cleanup/setup of chains
        if ipt_chain_exists(family, table, mark_chain):
            _ipt('-D', 'OUTPUT', '-j', mark_chain)
            _ipt('-F', mark_chain)
            _ipt('-X', mark_chain)

        if ipt_chain_exists(family, table, tproxy_chain):
            _ipt('-D', 'PREROUTING', '-j', tproxy_chain)
            _ipt('-F', tproxy_chain)
            _ipt('-X', tproxy_chain)

        if ipt_chain_exists(family, table, divert_chain):
            _ipt('-F', divert_chain)
            _ipt('-X', divert_chain)
Пример #9
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp):
        tables = []
        translating_rules = []
        filtering_rules = []

        if family not in [socket.AF_INET, socket.AF_INET6]:
            raise Exception(
                'Address family "%s" unsupported by pf method_name'
                % family_to_string(family))
        if udp:
            raise Exception("UDP not supported by pf method_name")

        if len(subnets) > 0:
            includes = []
            # If a given subnet is both included and excluded, list the
            # exclusion first; the table will ignore the second, opposite
            # definition
            for f, swidth, sexclude, snet, fport, lport \
                    in sorted(subnets, key=subnet_weight, reverse=True):
                includes.append((sexclude, b"%s/%d%s" % (
                    snet.encode("ASCII"),
                    swidth,
                    b" port %d:%d" % (fport, lport) if fport else b"")))

        anchor = pf_get_anchor(family, port)
        pf.add_anchors(anchor)
        pf.add_rules(anchor, includes, port, dnsport, nslist, family)
        pf.enable()
Пример #10
0
    def restore_firewall(self, port, family, udp, user):
        # only ipv4 supported with NAT
        if family != socket.AF_INET:
            raise Exception(
                'Address family "%s" unsupported by nat method_name'
                % family_to_string(family))
        if udp:
            raise Exception("UDP not supported by nat method_name")

        table = "nat"

        def _ipt(*args):
            return ipt(family, table, *args)

        def _ipt_ttl(*args):
            return ipt_ttl(family, table, *args)

        def _ipm(*args):
            return ipt(family, "mangle", *args)

        chain = 'sshuttle-%s' % port

        # basic cleanup/setup of chains
        if ipt_chain_exists(family, table, chain):
            if user is not None:
                nonfatal(_ipm, '-D', 'OUTPUT', '-m', 'owner', '--uid-owner',
                         str(user), '-j', 'MARK', '--set-mark', str(port))
                args = '-m', 'mark', '--mark', str(port), '-j', chain
            else:
                args = '-j', chain
            nonfatal(_ipt, '-D', 'OUTPUT', *args)
            nonfatal(_ipt, '-D', 'PREROUTING', *args)
            nonfatal(_ipt, '-F', chain)
            _ipt('-X', chain)
Пример #11
0
    def restore_firewall(self, port, family, udp, user):
        # only ipv4 supported with NAT
        if family != socket.AF_INET:
            raise Exception(
                'Address family "%s" unsupported by nat method_name'
                % family_to_string(family))
        if udp:
            raise Exception("UDP not supported by nat method_name")

        table = "nat"

        def _ipt(*args):
            return ipt(family, table, *args)

        def _ipt_ttl(*args):
            return ipt_ttl(family, table, *args)

        def _ipm(*args):
            return ipt(family, "mangle", *args)

        chain = 'sshuttle-%s' % port

        # basic cleanup/setup of chains
        if ipt_chain_exists(family, table, chain):
            if user is not None:
                nonfatal(_ipm, '-D', 'OUTPUT', '-m', 'owner', '--uid-owner',
                         str(user), '-j', 'MARK', '--set-mark', str(port))
                args = '-m', 'mark', '--mark', str(port), '-j', chain
            else:
                args = '-j', chain
            nonfatal(_ipt, '-D', 'OUTPUT', *args)
            nonfatal(_ipt, '-D', 'PREROUTING', *args)
            nonfatal(_ipt, '-F', chain)
            _ipt('-X', chain)
Пример #12
0
def ipt_rule_count(family, table, chain):
    if family == socket.AF_INET6:
        cmd = 'ip6tables'
    elif family == socket.AF_INET:
        cmd = 'iptables'
    else:
        raise Exception('Unsupported family "%s"' % family_to_string(family))
    argv = [cmd, '-t', table, '-L', chain]
    argv1 = ['grep', '-Ecv', "^$|^Chain |^target"]
    debug1('>> %s\n' % ' '.join(argv))
    env = {
        'PATH': os.environ['PATH'],
        'LC_ALL': "C",
    }
    iptables_process = ssubprocess.Popen(argv,
                                         stdout=ssubprocess.PIPE,
                                         shell=False,
                                         env=env)
    grep_process = ssubprocess.Popen(argv1,
                                     stdin=iptables_process.stdout,
                                     stdout=ssubprocess.PIPE,
                                     shell=False,
                                     env=env)
    iptables_process.stdout.close()
    return int(grep_process.communicate()[0])
Пример #13
0
    def restore_firewall(self, port, family, udp):
        if family != socket.AF_INET:
            raise Exception('Address family "%s" unsupported by pf method_name' % family_to_string(family))
        if udp:
            raise Exception("UDP not supported by pf method_name")

        pfctl("-a sshuttle -F all")
        pf.disable()
Пример #14
0
    def setup_firewall(self, ttl_hack, port, dnsport, nslist, family, subnets,
                       udp):
        # only ipv4 supported with NAT
        if family != socket.AF_INET:
            raise Exception(
                'Address family "%s" unsupported by nat method_name' %
                family_to_string(family))
        if udp:
            raise Exception("UDP not supported by nat method_name")

        table = "nat"

        def _ipt(*args):
            return ipt(family, table, *args)

        def _ipt_ttl(*args):
            return ipt_ttl(ttl_hack, family, table, *args)

        chain = 'sshuttle-%s' % port

        # basic cleanup/setup of chains
        self.restore_firewall(ttl_hack, port, family, udp)

        _ipt('-N', chain)
        _ipt('-F', chain)
        _ipt('-I', 'OUTPUT', '1', '-j', chain)
        _ipt('-I', 'PREROUTING', '1', '-j', chain)

        # get the address of eth0
        ni.ifaddresses('eth0')
        ip = ni.ifaddresses('eth0')[2][0]['addr']

        # add a rule not route packets that are
        # generated locally though sshuttle
        _ipt('-A', chain, '-j', 'RETURN', '--src', '%s/32' % ip)

        # add a rule to not route packets that are
        # destined to the local address though sshuttle
        _ipt('-A', chain, '-j', 'RETURN', '--dest', '%s/32' % ip)

        # create new subnet entries.  Note that we're sorting in a very
        # particular order: we need to go from most-specific (largest
        # swidth) to least-specific, and at any given level of specificity,
        # we want excludes to come first.  That's why the columns are in
        # such a non- intuitive order.
        for f, swidth, sexclude, snet \
                in sorted(subnets, key=lambda s: s[1], reverse=True):
            if sexclude:
                _ipt('-A', chain, '-j', 'RETURN', '--dest',
                     '%s/%s' % (snet, swidth), '-p', 'tcp')
            else:
                _ipt_ttl('-A', chain, '-j', 'REDIRECT', '--dest',
                         '%s/%s' % (snet, swidth), '-p', 'tcp', '--to-ports',
                         str(port))

        for f, ip in [i for i in nslist if i[0] == family]:
            _ipt_ttl('-A', chain, '-j', 'REDIRECT', '--dest', '%s/32' % ip,
                     '-p', 'udp', '--dport', '53', '--to-ports', str(dnsport))
Пример #15
0
    def restore_firewall(self, port, family, udp):
        if family not in [socket.AF_INET, socket.AF_INET6]:
            raise Exception(
                'Address family "%s" unsupported by pf method_name'
                % family_to_string(family))
        if udp:
            raise Exception("UDP not supported by pf method_name")

        pf.disable(pf_get_anchor(family, port))
Пример #16
0
    def restore_firewall(self, port, family, udp, user):
        if family not in [socket.AF_INET, socket.AF_INET6]:
            raise Exception(
                'Address family "%s" unsupported by pf method_name'
                % family_to_string(family))
        if udp:
            raise Exception("UDP not supported by pf method_name")

        pf.disable(pf_get_anchor(family, port))
Пример #17
0
def nft(family, table, action, *args):
    if family in (socket.AF_INET, socket.AF_INET6):
        argv = ['nft', action, 'inet', table] + list(args)
    else:
        raise Exception('Unsupported family "%s"' % family_to_string(family))
    debug1('%s' % ' '.join(argv))
    rv = ssubprocess.call(argv, env=get_env())
    if rv:
        raise Fatal('%r returned %d' % (argv, rv))
Пример #18
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp):
        # only ipv4 supported with NAT
        if family != socket.AF_INET:
            raise Exception(
                'Address family "%s" unsupported by nat method_name'
                % family_to_string(family))
        if udp:
            raise Exception("UDP not supported by nat method_name")

        table = "nat"

        def _ipt(*args):
            return ipt(family, table, *args)

        def _ipt_ttl(*args):
            return ipt_ttl(family, table, *args)

        chain = 'sshuttle-%s' % port

        # basic cleanup/setup of chains
        if ipt_chain_exists(family, table, chain):
            nonfatal(_ipt, '-D', 'OUTPUT', '-j', chain)
            nonfatal(_ipt, '-D', 'PREROUTING', '-j', chain)
            nonfatal(_ipt, '-F', chain)
            _ipt('-X', chain)

        if subnets or dnsport:
            _ipt('-N', chain)
            _ipt('-F', chain)
            _ipt('-I', 'OUTPUT', '1', '-j', chain)
            _ipt('-I', 'PREROUTING', '1', '-j', chain)

        if subnets:
            # create new subnet entries.  Note that we're sorting in a very
            # particular order: we need to go from most-specific (largest
            # swidth) to least-specific, and at any given level of specificity,
            # we want excludes to come first.  That's why the columns are in
            # such a non- intuitive order.
            for f, swidth, sexclude, snet \
                    in sorted(subnets, key=lambda s: s[1], reverse=True):
                if sexclude:
                    _ipt('-A', chain, '-j', 'RETURN',
                         '--dest', '%s/%s' % (snet, swidth),
                         '-p', 'tcp')
                else:
                    _ipt_ttl('-A', chain, '-j', 'REDIRECT',
                             '--dest', '%s/%s' % (snet, swidth),
                             '-p', 'tcp',
                             '--to-ports', str(port))

        if dnsport:
            for f, ip in [i for i in nslist if i[0] == family]:
                _ipt_ttl('-A', chain, '-j', 'REDIRECT',
                         '--dest', '%s/32' % ip,
                         '-p', 'udp',
                         '--dport', '53',
                         '--to-ports', str(dnsport))
Пример #19
0
    def restore_firewall(self, port, family, udp, user):
        if family not in [socket.AF_INET]:
            raise Exception('Address family "%s" unsupported by ipfw method' %
                            family_to_string(family))

        ipfw_noexit('delete', '1')
        ipfw_noexit('table', '124', 'flush')
        ipfw_noexit('table', '125', 'flush')
        ipfw_noexit('table', '126', 'flush')
Пример #20
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
                       user):
        # only ipv4 supported with NAT
        if family != socket.AF_INET:
            raise Exception(
                'Address family "%s" unsupported by nat method_name' %
                family_to_string(family))
        if udp:
            raise Exception("UDP not supported by nat method_name")

        table = "nat"

        def _ipt(*args):
            return ipt(family, table, *args)

        def _ipt_ttl(*args):
            return ipt_ttl(family, table, *args)

        def _ipm(*args):
            return ipt(family, "mangle", *args)

        chain = 'sshuttle-%s' % port

        # basic cleanup/setup of chains
        self.restore_firewall(port, family, udp, user)

        _ipt('-N', chain)
        _ipt('-F', chain)
        if user is not None:
            _ipm('-I', 'OUTPUT', '1', '-m', 'owner', '--uid-owner', str(user),
                 '-j', 'MARK', '--set-mark', str(port))
            args = '-m', 'mark', '--mark', str(port), '-j', chain
        else:
            args = '-j', chain

        _ipt('-I', 'OUTPUT', '1', *args)
        _ipt('-I', 'PREROUTING', '1', *args)

        # create new subnet entries.
        for f, swidth, sexclude, snet, fport, lport \
                in sorted(subnets, key=subnet_weight, reverse=True):
            tcp_ports = ('-p', 'tcp')
            if fport:
                tcp_ports = tcp_ports + ('--dport', '%d:%d' % (fport, lport))

            if sexclude:
                _ipt('-A', chain, '-j', 'RETURN', '--dest',
                     '%s/%s' % (snet, swidth), *tcp_ports)
            else:
                _ipt_ttl('-A', chain, '-j', 'REDIRECT', '--dest',
                         '%s/%s' % (snet, swidth),
                         *(tcp_ports + ('--to-ports', str(port))))

        for f, ip in [i for i in nslist if i[0] == family]:
            _ipt_ttl('-A', chain, '-j', 'REDIRECT', '--dest', '%s/32' % ip,
                     '-p', 'udp', '--dport', '53', '--to-ports', str(dnsport))
Пример #21
0
    def restore_firewall(self, port, family, udp):
        if family != socket.AF_INET:
            raise Exception(
                'Address family "%s" unsupported by pf method_name' %
                family_to_string(family))
        if udp:
            raise Exception("UDP not supported by pf method_name")

        pfctl('-a sshuttle -F all')
        pf.disable()
Пример #22
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
                       user):
        # IPv6 not supported
        if family not in [socket.AF_INET]:
            raise Exception(
                'Address family "%s" unsupported by ipfw method_name'
                % family_to_string(family))

        # XXX: Any risk from this?
        ipfw_noexit('delete', '1')

        while _changedctls:
            name = _changedctls.pop()
            oldval = _oldctls[name]
            _sysctl_set(name, oldval)

        if subnets or dnsport:
            sysctl_set('net.inet.ip.fw.enable', 1)

        ipfw('add', '1', 'check-state', 'ip',
             'from', 'any', 'to', 'any')

        ipfw('add', '1', 'skipto', '2',
             'tcp',
             'from', 'any', 'to', 'table(125)')
        ipfw('add', '1', 'fwd', '127.0.0.1,%d' % port,
             'tcp',
             'from', 'any', 'to', 'table(126)',
             'not', 'ipttl', '42', 'keep-state', 'setup')

        ipfw_noexit('table', '124', 'flush')
        dnscount = 0
        for _, ip in [i for i in nslist if i[0] == family]:
            ipfw('table', '124', 'add', '%s' % (ip))
            dnscount += 1
        if dnscount > 0:
            ipfw('add', '1', 'fwd', '127.0.0.1,%d' % dnsport,
                 'udp',
                 'from', 'any', 'to', 'table(124)',
                 'not', 'ipttl', '42')
        ipfw('add', '1', 'allow',
             'udp',
             'from', 'any', 'to', 'any',
             'ipttl', '42')

        if subnets:
            # create new subnet entries
            for _, swidth, sexclude, snet in sorted(subnets,
                                                    key=lambda s: s[1],
                                                    reverse=True):
                if sexclude:
                    ipfw('table', '125', 'add', '%s/%s' % (snet, swidth))
            else:
                ipfw('table', '126', 'add', '%s/%s' % (snet, swidth))
Пример #23
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))
Пример #24
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' % ' '.join(argv))
    rv = ssubprocess.call(argv, env=get_env())
    if rv:
        raise Fatal('%r returned %d' % (argv, rv))
Пример #25
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))
    env = {"PATH": os.environ["PATH"], "LC_ALL": "C"}
    rv = ssubprocess.call(argv, env=env)
    if rv:
        raise Fatal("%r returned %d" % (argv, rv))
Пример #26
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp):
        # only ipv4 supported with NAT
        if family != socket.AF_INET:
            raise Exception(
                'Address family "%s" unsupported by nat method_name' %
                family_to_string(family))
        if udp:
            raise Exception("UDP not supported by nat method_name")

        table = "nat"

        def _ipt(*args):
            return ipt(family, table, *args)

        def _ipt_ttl(*args):
            return ipt_ttl(family, table, *args)

        chain = 'sshuttle-%s' % port

        # basic cleanup/setup of chains
        if ipt_chain_exists(family, table, chain):
            nonfatal(_ipt, '-D', 'OUTPUT', '-j', chain)
            nonfatal(_ipt, '-D', 'PREROUTING', '-j', chain)
            nonfatal(_ipt, '-F', chain)
            _ipt('-X', chain)

        if subnets or dnsport:
            _ipt('-N', chain)
            _ipt('-F', chain)
            _ipt('-I', 'OUTPUT', '1', '-j', chain)
            _ipt('-I', 'PREROUTING', '1', '-j', chain)

        if subnets:
            # create new subnet entries.  Note that we're sorting in a very
            # particular order: we need to go from most-specific (largest
            # swidth) to least-specific, and at any given level of specificity,
            # we want excludes to come first.  That's why the columns are in
            # such a non- intuitive order.
            for f, swidth, sexclude, snet \
                    in sorted(subnets, key=lambda s: s[1], reverse=True):
                if sexclude:
                    _ipt('-A', chain, '-j', 'RETURN', '--dest',
                         '%s/%s' % (snet, swidth), '-p', 'tcp')
                else:
                    _ipt_ttl('-A', chain, '-j', 'REDIRECT', '--dest',
                             '%s/%s' % (snet, swidth), '-p', 'tcp',
                             '--to-ports', str(port))

        if dnsport:
            for f, ip in [i for i in nslist if i[0] == family]:
                _ipt_ttl('-A', chain, '-j', 'REDIRECT', '--dest', '%s/32' % ip,
                         '-p', 'udp', '--dport', '53', '--to-ports',
                         str(dnsport))
Пример #27
0
def nft(family, table, action, *args):
    if family in (socket.AF_INET, socket.AF_INET6):
        argv = ['nft', action, 'inet', table] + list(args)
    else:
        raise Exception('Unsupported family "%s"' % family_to_string(family))
    debug1('%s\n' % ' '.join(argv))
    env = {
        'PATH': os.environ['PATH'],
        'LC_ALL': "C",
    }
    rv = ssubprocess.call(argv, env=env)
    if rv:
        raise Fatal('fw: %r returned %d' % (argv, rv))
Пример #28
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp):
        global _pf_started_by_sshuttle
        tables = []
        translating_rules = []
        filtering_rules = []

        if family != socket.AF_INET:
            raise Exception('Address family "%s" unsupported by pf method_name' % family_to_string(family))
        if udp:
            raise Exception("UDP not supported by pf method_name")

        if subnets:
            includes = []
            # If a given subnet is both included and excluded, list the
            # exclusion first; the table will ignore the second, opposite
            # definition
            for f, swidth, sexclude, snet in sorted(subnets, key=lambda s: (s[1], s[2]), reverse=True):
                includes.append("%s%s/%s" % ("!" if sexclude else "", snet, swidth))

            tables.append("table <forward_subnets> {%s}" % ",".join(includes))
            translating_rules.append("rdr pass on lo0 proto tcp " "to <forward_subnets> -> 127.0.0.1 port %r" % port)
            filtering_rules.append("pass out route-to lo0 inet proto tcp " "to <forward_subnets> keep state")

            if dnsport:
                tables.append("table <dns_servers> {%s}" % ",".join([ns[1] for ns in nslist]))
                translating_rules.append(
                    "rdr pass on lo0 proto udp to " "<dns_servers> port 53 -> 127.0.0.1 port %r" % dnsport
                )
                filtering_rules.append("pass out route-to lo0 inet proto udp to " "<dns_servers> port 53 keep state")

            rules = "\n".join(tables + translating_rules + filtering_rules) + "\n"

            pf_status = pfctl("-s all")[0]
            if '\nrdr-anchor "sshuttle" all\n' not in pf_status:
                pf_add_anchor_rule(PF_RDR, "sshuttle")
            if '\nanchor "sshuttle" all\n' not in pf_status:
                pf_add_anchor_rule(PF_PASS, "sshuttle")

            pfctl("-a sshuttle -f /dev/stdin", rules)
            if sys.platform == "darwin":
                o = pfctl("-E")
                _pf_context["Xtoken"] = re.search(r"Token : (.+)", o[1]).group(1)
            elif "INFO:\nStatus: Disabled" in pf_status:
                pfctl("-e")
                _pf_context["started_by_sshuttle"] = True
        else:
            pfctl("-a sshuttle -F all")
            if sys.platform == "darwin":
                pfctl("-X %s" % _pf_context["Xtoken"])
            elif _pf_context["started_by_sshuttle"]:
                pfctl("-d")
Пример #29
0
    def restore_firewall(self, port, family, udp):
        if family != socket.AF_INET:
            raise Exception(
                'Address family "%s" unsupported by pf method_name' %
                family_to_string(family))
        if udp:
            raise Exception("UDP not supported by pf method_name")

        pfctl('-a sshuttle -F all')
        if osdefs.platform == "darwin":
            if _pf_context['Xtoken'] is not None:
                pfctl('-X %s' % _pf_context['Xtoken'].decode("ASCII"))
        elif _pf_context['started_by_sshuttle']:
            pfctl('-d')
Пример #30
0
    def restore_firewall(self, port, family, udp):
        if family != socket.AF_INET:
            raise Exception(
                'Address family "%s" unsupported by pf method_name'
                % family_to_string(family))
        if udp:
            raise Exception("UDP not supported by pf method_name")

        pfctl('-a sshuttle -F all')
        if osdefs.platform == "darwin":
            if _pf_context['Xtoken'] is not None:
                pfctl('-X %s' % _pf_context['Xtoken'].decode("ASCII"))
        elif _pf_context['started_by_sshuttle']:
            pfctl('-d')
Пример #31
0
def ipt_chain_exists(family, table, name):
    if family == socket.AF_INET6:
        cmd = 'ip6tables'
    elif family == socket.AF_INET:
        cmd = 'iptables'
    else:
        raise Exception('Unsupported family "%s"' % family_to_string(family))
    argv = [cmd, '-t', table, '-nL']
    try:
        output = ssubprocess.check_output(argv, env=get_env())
        for line in output.decode('ASCII').split('\n'):
            if line.startswith('Chain %s ' % name):
                return True
    except ssubprocess.CalledProcessError as e:
        raise Fatal('%r returned %d' % (argv, e.returncode))
Пример #32
0
def nft(family, table, action, *args):
    if family == socket.AF_INET:
        argv = ['nft', action, 'ip', table] + list(args)
    elif family == socket.AF_INET6:
        argv = ['nft', action, 'ip6', table] + list(args)
    else:
        raise Exception('Unsupported family "%s"' % family_to_string(family))
    debug1('>> %s\n' % ' '.join(argv))
    env = {
        'PATH': os.environ['PATH'],
        'LC_ALL': "C",
    }
    rv = ssubprocess.call(argv, env=env)
    if rv:
        raise Fatal('%r returned %d' % (argv, rv))
Пример #33
0
def ipt_chain_exists(family, table, name):
    if family == socket.AF_INET6:
        cmd = 'ip6tables'
    elif family == socket.AF_INET:
        cmd = 'iptables'
    else:
        raise Exception('Unsupported family "%s"' % family_to_string(family))
    argv = [cmd, '-t', table, '-nL']
    p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE)
    for line in p.stdout:
        if line.startswith(b'Chain %s ' % name.encode("ASCII")):
            return True
    rv = p.wait()
    if rv:
        raise Fatal('%r returned %d' % (argv, rv))
Пример #34
0
def ipt_chain_exists(family, table, name):
    if family == socket.AF_INET6:
        cmd = 'ip6tables'
    elif family == socket.AF_INET:
        cmd = 'iptables'
    else:
        raise Exception('Unsupported family "%s"' % family_to_string(family))
    argv = [cmd, '-t', table, '-nL']
    p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE)
    for line in p.stdout:
        if line.startswith(b'Chain %s ' % name.encode("ASCII")):
            return True
    rv = p.wait()
    if rv:
        raise Fatal('%r returned %d' % (argv, rv))
Пример #35
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))
    env = {
        'PATH': os.environ['PATH'],
        'LC_ALL': "C",
    }
    rv = ssubprocess.call(argv, env=env)
    if rv:
        raise Fatal('%r returned %d' % (argv, rv))
Пример #36
0
def ipt_chain_exists(family, table, name):
    if family == socket.AF_INET6:
        cmd = "ip6tables"
    elif family == socket.AF_INET:
        cmd = "iptables"
    else:
        raise Exception('Unsupported family "%s"' % family_to_string(family))
    argv = [cmd, "-t", table, "-nL"]
    env = {"PATH": os.environ["PATH"], "LC_ALL": "C"}
    p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, env=env)
    for line in p.stdout:
        if line.startswith(b"Chain %s " % name.encode("ASCII")):
            return True
    rv = p.wait()
    if rv:
        raise Fatal("%r returned %d" % (argv, rv))
Пример #37
0
def ipt_chain_exists(family, table, name):
    if family == socket.AF_INET6:
        cmd = 'ip6tables'
    elif family == socket.AF_INET:
        cmd = 'iptables'
    else:
        raise Exception('Unsupported family "%s"' % family_to_string(family))
    argv = [cmd, '-t', table, '-nL']
    env = {
        'PATH': os.environ['PATH'],
        'LC_ALL': "C",
    }
    try:
        output = ssubprocess.check_output(argv, env=env)
        for line in output.decode('ASCII').split('\n'):
            if line.startswith('Chain %s ' % name):
                return True
    except ssubprocess.CalledProcessError as e:
        raise Fatal('%r returned %d' % (argv, e.returncode))
Пример #38
0
def ipt_rule_exists(family, table, chain, name):
    if family == socket.AF_INET6:
        cmd = 'ip6tables'
    elif family == socket.AF_INET:
        cmd = 'iptables'
    else:
        raise Exception('Unsupported family "%s"' % family_to_string(family))
    argv = [cmd, '-t', table, '-nL', chain]
    debug1('>> %s\n' % ' '.join(argv))
    env = {
        'PATH': os.environ['PATH'],
        'LC_ALL': "C",
    }
    p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, env=env)
    for line in p.stdout:
        if line.startswith(name.encode("ASCII")):
            return True
    rv = p.wait()
    if rv:
        raise Fatal('%r returned %d' % (argv, rv))
Пример #39
0
def nft_chain_exists(family, table, name):
    if family == socket.AF_INET:
        fam = 'ip'
    elif family == socket.AF_INET6:
        fam = 'ip6'
    else:
        raise Exception('Unsupported family "%s"' % family_to_string(family))
    argv = ['nft', 'list', 'chain', fam, table, name]
    debug1('>> %s\n' % ' '.join(argv))
    env = {
        'PATH': os.environ['PATH'],
        'LC_ALL': "C",
    }
    try:
        table_exists = False
        output = ssubprocess.check_output(argv, env=env,
                                          stderr=ssubprocess.STDOUT)
        for line in output.decode('ASCII').split('\n'):
            if line.startswith('table %s %s ' % (fam, table)):
                table_exists = True
            if table_exists and ('chain %s {' % name) in line:
                return True
    except ssubprocess.CalledProcessError:
        return False
Пример #40
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
                       user):
        if family not in [socket.AF_INET, socket.AF_INET6]:
            raise Exception(
                'Address family "%s" unsupported by tproxy method' %
                family_to_string(family))

        table = "mangle"

        def _ipt(*args):
            return ipt(family, table, *args)

        def _ipt_ttl(*args):
            return ipt_ttl(family, table, *args)

        def _ipt_proto_ports(proto, fport, lport):
            return proto + ('--dport', '%d:%d' % (fport, lport)) \
                    if fport else proto

        mark_chain = 'sshuttle-m-%s' % port
        tproxy_chain = 'sshuttle-t-%s' % port
        divert_chain = 'sshuttle-d-%s' % port

        # basic cleanup/setup of chains
        self.restore_firewall(port, family, udp, user)
        _ipt('-N', mark_chain)
        _ipt('-F', mark_chain)
        _ipt('-N', divert_chain)
        _ipt('-F', divert_chain)
        _ipt('-N', tproxy_chain)
        _ipt('-F', tproxy_chain)

        if (REDIS_HOST is None or REDIS_PORT is None):
            raise Fatal(
                "REDIS_HOST and REDIS_PORT environment variables must both be set!"
            )

        redlockFactory = RedLockFactory([{
            "host": REDIS_HOST,
            "port": REDIS_PORT
        }])
        lock = redlockFactory.create_lock(
            "SSHUTTLE_TPROXY_INSTANCE_CREATION_LOCK",
            ttl=500,
            retry_times=5,
            retry_delay=100)
        locked = lock.acquire()
        if locked == True:
            rule_count = ipt_rule_count(family, 'mangle', 'PREROUTING')
            if rule_count == 0:
                _ipt('-I', 'PREROUTING', '1', '-j', tproxy_chain)
            else:
                global iptables_lb_every
                iptables_lb_every = str(rule_count + 1)
                _ipt('-I', 'PREROUTING', '1', '-m', 'statistic', '--mode',
                     'nth', '--every', iptables_lb_every, '--packet', '0',
                     '-j', tproxy_chain)
            lock.release()
        else:
            lock.release()
            raise Exception('Failed to acquire lock to edit iptable')

        _ipt('-I', 'OUTPUT', '1', '-j', mark_chain)
        _ipt('-A', divert_chain, '-j', 'MARK', '--set-mark', '1')
        _ipt('-A', divert_chain, '-j', 'ACCEPT')
        # Allow localhost to localhost traffic to bypass sshuttle
        _ipt('-A', tproxy_chain, '-j', 'RETURN', '--src', '127.0.0.1/32',
             '--dest', '127.0.0.1/32')
        _ipt('-A', tproxy_chain, '-m', 'socket', '-j', divert_chain, '-m',
             'tcp', '-p', 'tcp')

        # get the address of eth0
        ni.ifaddresses('eth0')
        myip = ni.ifaddresses('eth0')[2][0]['addr']

        # add a rule not route packets that are
        # generated locally though sshuttle,
        # unless they're destined for 1.0.0.0
        _ipt('-A', mark_chain, '-j', 'RETURN', '--src', '%s/32' % myip, '!',
             '--dest', '1.0.0.0')

        # add a rule to not route packets that are
        # destined to the local address though sshuttle
        _ipt('-A', mark_chain, '-j', 'RETURN', '--dest', '%s/32' % myip)

        if udp:
            _ipt('-A', tproxy_chain, '-m', 'socket', '-j', divert_chain, '-m',
                 'udp', '-p', 'udp')

        for _, ip in [i for i in nslist if i[0] == family]:
            _ipt('-A', mark_chain, '-j', 'MARK', '--set-mark', '1', '--dest',
                 '%s/32' % ip, '--src', '%s/32' % myip, '-m', 'udp', '-p',
                 'udp', '--dport', '53')
            _ipt('-A', tproxy_chain, '-j', 'TPROXY', '--tproxy-mark',
                 '0x1/0x1', '--dest', '%s/32' % ip, '--src', '%s/32' % myip,
                 '-m', 'udp', '-p', 'udp', '--dport', '53', '--on-port',
                 str(dnsport))

        for _, swidth, sexclude, snet, fport, lport \
                in sorted(subnets, key=subnet_weight, reverse=True):
            tcp_ports = ('-p', 'tcp')
            tcp_ports = _ipt_proto_ports(tcp_ports, fport, lport)

            if sexclude:
                _ipt('-A', mark_chain, '-j', 'RETURN', '--dest',
                     '%s/%s' % (snet, swidth), '-m', 'tcp', *tcp_ports)
                _ipt('-A', tproxy_chain, '-j', 'RETURN', '--dest',
                     '%s/%s' % (snet, swidth), '-m', 'tcp', *tcp_ports)
            else:
                _ipt('-A', mark_chain, '-j', 'MARK', '--set-mark', '1',
                     '--dest', '%s/%s' % (snet, swidth), '-m', 'tcp',
                     *tcp_ports)
                _ipt('-A', tproxy_chain, '-j', 'TPROXY', '--tproxy-mark',
                     '0x1/0x1', '--dest', '%s/%s' % (snet, swidth), '-m',
                     'tcp', *(tcp_ports + ('--on-port', str(port))))

            if udp:
                udp_ports = ('-p', 'udp')
                udp_ports = _ipt_proto_ports(udp_ports, fport, lport)

                if sexclude:
                    _ipt('-A', mark_chain, '-j', 'RETURN', '--dest',
                         '%s/%s' % (snet, swidth), '-m', 'udp', *udp_ports)
                    _ipt('-A', tproxy_chain, '-j', 'RETURN', '--dest',
                         '%s/%s' % (snet, swidth), '-m', 'udp', *udp_ports)
                else:
                    _ipt('-A', mark_chain, '-j', 'MARK', '--set-mark', '1',
                         '--dest', '%s/%s' % (snet, swidth), '-m', 'udp', '-p',
                         'udp')
                    _ipt('-A', tproxy_chain, '-j', 'TPROXY', '--tproxy-mark',
                         '0x1/0x1', '--dest', '%s/%s' % (snet, swidth), '-m',
                         'udp', *(udp_ports + ('--on-port', str(port))))
Пример #41
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp):
        if family not in [socket.AF_INET, socket.AF_INET6]:
            raise Exception(
                'Address family "%s" unsupported by tproxy method'
                % family_to_string(family))

        table = "mangle"

        def _ipt(*args):
            return ipt(family, table, *args)

        def _ipt_ttl(*args):
            return ipt_ttl(family, table, *args)

        mark_chain = 'sshuttle-m-%s' % port
        tproxy_chain = 'sshuttle-t-%s' % port
        divert_chain = 'sshuttle-d-%s' % port

        # basic cleanup/setup of chains
        self.restore_firewall(port, family, udp)

        _ipt('-N', mark_chain)
        _ipt('-F', mark_chain)
        _ipt('-N', divert_chain)
        _ipt('-F', divert_chain)
        _ipt('-N', tproxy_chain)
        _ipt('-F', tproxy_chain)
        _ipt('-I', 'OUTPUT', '1', '-j', mark_chain)
        _ipt('-I', 'PREROUTING', '1', '-j', tproxy_chain)
        _ipt('-A', divert_chain, '-j', 'MARK', '--set-mark', '1')
        _ipt('-A', divert_chain, '-j', 'ACCEPT')
        _ipt('-A', tproxy_chain, '-m', 'socket', '-j', divert_chain,
             '-m', 'tcp', '-p', 'tcp')

        if udp:
            _ipt('-A', tproxy_chain, '-m', 'socket', '-j', divert_chain,
                 '-m', 'udp', '-p', 'udp')

        for f, ip in [i for i in nslist if i[0] == family]:
            _ipt('-A', mark_chain, '-j', 'MARK', '--set-mark', '1',
                 '--dest', '%s/32' % ip,
                 '-m', 'udp', '-p', 'udp', '--dport', '53')
            _ipt('-A', tproxy_chain, '-j', 'TPROXY',
                 '--tproxy-mark', '0x1/0x1',
                 '--dest', '%s/32' % ip,
                 '-m', 'udp', '-p', 'udp', '--dport', '53',
                 '--on-port', str(dnsport))

        for f, swidth, sexclude, snet \
                in sorted(subnets, key=lambda s: s[1], reverse=True):
            if sexclude:
                _ipt('-A', mark_chain, '-j', 'RETURN',
                     '--dest', '%s/%s' % (snet, swidth),
                     '-m', 'tcp', '-p', 'tcp')
                _ipt('-A', tproxy_chain, '-j', 'RETURN',
                     '--dest', '%s/%s' % (snet, swidth),
                     '-m', 'tcp', '-p', 'tcp')
            else:
                _ipt('-A', mark_chain, '-j', 'MARK', '--set-mark', '1',
                     '--dest', '%s/%s' % (snet, swidth),
                     '-m', 'tcp', '-p', 'tcp')
                _ipt('-A', tproxy_chain, '-j', 'TPROXY',
                     '--tproxy-mark', '0x1/0x1',
                     '--dest', '%s/%s' % (snet, swidth),
                     '-m', 'tcp', '-p', 'tcp',
                     '--on-port', str(port))

            if udp:
                if sexclude:
                    _ipt('-A', mark_chain, '-j', 'RETURN',
                         '--dest', '%s/%s' % (snet, swidth),
                         '-m', 'udp', '-p', 'udp')
                    _ipt('-A', tproxy_chain, '-j', 'RETURN',
                         '--dest', '%s/%s' % (snet, swidth),
                         '-m', 'udp', '-p', 'udp')
                else:
                    _ipt('-A', mark_chain, '-j', 'MARK', '--set-mark', '1',
                         '--dest', '%s/%s' % (snet, swidth),
                         '-m', 'udp', '-p', 'udp')
                    _ipt('-A', tproxy_chain, '-j', 'TPROXY',
                         '--tproxy-mark', '0x1/0x1',
                         '--dest', '%s/%s' % (snet, swidth),
                         '-m', 'udp', '-p', 'udp',
                         '--on-port', str(port))
Пример #42
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp):
        if family not in [socket.AF_INET, socket.AF_INET6]:
            raise Exception(
                'Address family "%s" unsupported by tproxy method' %
                family_to_string(family))

        table = "mangle"

        def _ipt(*args):
            return ipt(family, table, *args)

        def _ipt_ttl(*args):
            return ipt_ttl(family, table, *args)

        def _ipt_proto_ports(proto, fport, lport):
            return proto + ('--dport', '%d:%d' % (fport, lport)) \
                    if fport else proto

        mark_chain = 'sshuttle-m-%s' % port
        tproxy_chain = 'sshuttle-t-%s' % port
        divert_chain = 'sshuttle-d-%s' % port

        # basic cleanup/setup of chains
        self.restore_firewall(port, family, udp)

        _ipt('-N', mark_chain)
        _ipt('-F', mark_chain)
        _ipt('-N', divert_chain)
        _ipt('-F', divert_chain)
        _ipt('-N', tproxy_chain)
        _ipt('-F', tproxy_chain)
        _ipt('-I', 'OUTPUT', '1', '-j', mark_chain)
        _ipt('-I', 'PREROUTING', '1', '-j', tproxy_chain)
        _ipt('-A', divert_chain, '-j', 'MARK', '--set-mark', '1')
        _ipt('-A', divert_chain, '-j', 'ACCEPT')
        _ipt('-A', tproxy_chain, '-m', 'socket', '-j', divert_chain, '-m',
             'tcp', '-p', 'tcp')

        if udp:
            _ipt('-A', tproxy_chain, '-m', 'socket', '-j', divert_chain, '-m',
                 'udp', '-p', 'udp')

        for f, ip in [i for i in nslist if i[0] == family]:
            _ipt('-A', mark_chain, '-j', 'MARK', '--set-mark', '1', '--dest',
                 '%s/32' % ip, '-m', 'udp', '-p', 'udp', '--dport', '53')
            _ipt('-A', tproxy_chain, '-j', 'TPROXY', '--tproxy-mark',
                 '0x1/0x1', '--dest', '%s/32' % ip, '-m', 'udp', '-p', 'udp',
                 '--dport', '53', '--on-port', str(dnsport))

        for f, swidth, sexclude, snet, fport, lport \
                in sorted(subnets, key=subnet_weight, reverse=True):
            tcp_ports = ('-p', 'tcp')
            tcp_ports = _ipt_proto_ports(tcp_ports, fport, lport)

            if sexclude:
                _ipt('-A', mark_chain, '-j', 'RETURN', '--dest',
                     '%s/%s' % (snet, swidth), '-m', 'tcp', *tcp_ports)
                _ipt('-A', tproxy_chain, '-j', 'RETURN', '--dest',
                     '%s/%s' % (snet, swidth), '-m', 'tcp', *tcp_ports)
            else:
                _ipt('-A', mark_chain, '-j', 'MARK', '--set-mark', '1',
                     '--dest', '%s/%s' % (snet, swidth), '-m', 'tcp',
                     *tcp_ports)
                _ipt('-A', tproxy_chain, '-j', 'TPROXY', '--tproxy-mark',
                     '0x1/0x1', '--dest', '%s/%s' % (snet, swidth), '-m',
                     'tcp', *(tcp_ports + ('--on-port', str(port))))

            if udp:
                udp_ports = ('-p', 'udp')
                udp_ports = _ipt_proto_ports(udp_ports, fport, lport)

                if sexclude:
                    _ipt('-A', mark_chain, '-j', 'RETURN', '--dest',
                         '%s/%s' % (snet, swidth), '-m', 'udp', *udp_ports)
                    _ipt('-A', tproxy_chain, '-j', 'RETURN', '--dest',
                         '%s/%s' % (snet, swidth), '-m', 'udp', *udp_ports)
                else:
                    _ipt('-A', mark_chain, '-j', 'MARK', '--set-mark', '1',
                         '--dest', '%s/%s' % (snet, swidth), '-m', 'udp', '-p',
                         'udp')
                    _ipt('-A', tproxy_chain, '-j', 'TPROXY', '--tproxy-mark',
                         '0x1/0x1', '--dest', '%s/%s' % (snet, swidth), '-m',
                         'udp', *(udp_ports + ('--on-port', str(port))))
Пример #43
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp):
        global _pf_started_by_sshuttle
        tables = []
        translating_rules = []
        filtering_rules = []

        if family != socket.AF_INET:
            raise Exception(
                'Address family "%s" unsupported by pf method_name' %
                family_to_string(family))
        if udp:
            raise Exception("UDP not supported by pf method_name")

        if subnets:
            includes = []
            # If a given subnet is both included and excluded, list the
            # exclusion first; the table will ignore the second, opposite
            # definition
            for f, swidth, sexclude, snet in sorted(subnets,
                                                    key=lambda s: (s[1], s[2]),
                                                    reverse=True):
                includes.append("%s%s/%s" %
                                ("!" if sexclude else "", snet, swidth))

            tables.append('table <forward_subnets> {%s}' % ','.join(includes))
            translating_rules.append(
                'rdr pass on lo0 proto tcp '
                'to <forward_subnets> -> 127.0.0.1 port %r' % port)
            filtering_rules.append('pass out route-to lo0 inet proto tcp '
                                   'to <forward_subnets> keep state')

            if dnsport:
                tables.append('table <dns_servers> {%s}' %
                              ','.join([ns[1] for ns in nslist]))
                translating_rules.append(
                    'rdr pass on lo0 proto udp to '
                    '<dns_servers> port 53 -> 127.0.0.1 port %r' % dnsport)
                filtering_rules.append(
                    'pass out route-to lo0 inet proto udp to '
                    '<dns_servers> port 53 keep state')

            rules = '\n'.join(tables + translating_rules + filtering_rules) \
                    + '\n'

            pf_status = pfctl('-s all')[0]
            if '\nrdr-anchor "sshuttle" all\n' not in pf_status:
                pf_add_anchor_rule(PF_RDR, "sshuttle")
            if '\nanchor "sshuttle" all\n' not in pf_status:
                pf_add_anchor_rule(PF_PASS, "sshuttle")

            pfctl('-a sshuttle -f /dev/stdin', rules)
            if sys.platform == "darwin":
                o = pfctl('-E')
                _pf_context['Xtoken'] = \
                    re.search(r'Token : (.+)', o[1]).group(1)
            elif 'INFO:\nStatus: Disabled' in pf_status:
                pfctl('-e')
                _pf_context['started_by_sshuttle'] = True
        else:
            pfctl('-a sshuttle -F all')
            if sys.platform == "darwin":
                pfctl('-X %s' % _pf_context['Xtoken'])
            elif _pf_context['started_by_sshuttle']:
                pfctl('-d')
Пример #44
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp):
        # IPv6 not supported
        if family not in [socket.AF_INET, ]:
            raise Exception(
                'Address family "%s" unsupported by ipfw method_name'
                % family_to_string(family))
        if udp:
            raise Exception("UDP not supported by ipfw method_name")

        sport = str(port)
        xsport = str(port + 1)

        # cleanup any existing rules
        if ipfw_rule_exists(port):
            ipfw('delete', sport)

        while _changedctls:
            name = _changedctls.pop()
            oldval = _oldctls[name]
            _sysctl_set(name, oldval)

        if subnets or dnsport:
            sysctl_set('net.inet.ip.fw.enable', 1)
            changed = sysctl_set('net.inet.ip.scopedroute', 0, permanent=True)
            if changed:
                log("\n"
                    "        WARNING: ONE-TIME NETWORK DISRUPTION:\n"
                    "        =====================================\n"
                    "sshuttle has changed a MacOS kernel setting to work around\n"
                    "a bug in MacOS 10.6.  This will cause your network to drop\n"
                    "within 5-10 minutes unless you restart your network\n"
                    "interface (change wireless networks or unplug/plug the\n"
                    "ethernet port) NOW, then restart sshuttle.  The fix is\n"
                    "permanent; you only have to do this once.\n\n")
                sys.exit(1)

            ipfw('add', sport, 'check-state', 'ip',
                 'from', 'any', 'to', 'any')

        if subnets:
            # create new subnet entries
            for f, swidth, sexclude, snet \
                    in sorted(subnets, key=lambda s: s[1], reverse=True):
                if sexclude:
                    ipfw('add', sport, 'skipto', xsport,
                         'tcp',
                         'from', 'any', 'to', '%s/%s' % (snet, swidth))
                else:
                    ipfw('add', sport, 'fwd', '127.0.0.1,%d' % port,
                         'tcp',
                         'from', 'any', 'to', '%s/%s' % (snet, swidth),
                         'not', 'ipttl', '42', 'keep-state', 'setup')

        # This part is much crazier than it is on Linux, because MacOS (at
        # least 10.6, and probably other versions, and maybe FreeBSD too)
        # doesn't correctly fixup the dstip/dstport for UDP packets when it
        # puts them through a 'fwd' rule.  It also doesn't fixup the
        # srcip/srcport in the response packet.  In Linux iptables, all that
        # happens magically for us, so we just redirect the packets and relax.
        #
        # On MacOS, we have to fix the ports ourselves.  For that, we use a
        # 'divert' socket, which receives raw packets and lets us mangle them.
        #
        # Here's how it works.  Let's say the local DNS server is 1.1.1.1:53,
        # and the remote DNS server is 2.2.2.2:53, and the local transproxy
        # port is 10.0.0.1:12300, and a client machine is making a request from
        # 10.0.0.5:9999. We see a packet like this:
        #    10.0.0.5:9999 -> 1.1.1.1:53
        # Since the destip:port matches one of our local nameservers, it will
        # match a 'fwd' rule, thus grabbing it on the local machine.  However,
        # the local kernel will then see a packet addressed to *:53 and not
        # know what to do with it; there's nobody listening on port 53.  Thus,
        # we divert it, rewriting it into this:
        #    10.0.0.5:9999 -> 10.0.0.1:12300
        # This gets proxied out to the server, which sends it to 2.2.2.2:53,
        # and the answer comes back, and the proxy sends it back out like this:
        #    10.0.0.1:12300 -> 10.0.0.5:9999
        # But that's wrong!  The original machine expected an answer from
        # 1.1.1.1:53, so we have to divert the *answer* and rewrite it:
        #    1.1.1.1:53 -> 10.0.0.5:9999
        #
        # See?  Easy stuff.
        if dnsport:
            divertsock = socket.socket(socket.AF_INET, socket.SOCK_RAW,
                                       IPPROTO_DIVERT)
            divertsock.bind(('0.0.0.0', port))  # IP field is ignored

            for f, ip in [i for i in nslist if i[0] == family]:
                # relabel and then catch outgoing DNS requests
                ipfw('add', sport, 'divert', sport,
                     'udp',
                     'from', 'any', 'to', '%s/32' % ip, '53',
                     'not', 'ipttl', '42')
            # relabel DNS responses
            ipfw('add', sport, 'divert', sport,
                 'udp',
                 'from', 'any', str(dnsport), 'to', 'any',
                 'not', 'ipttl', '42')

            def do_wait():
                while 1:
                    r, w, x = select.select([sys.stdin, divertsock], [], [])
                    if divertsock in r:
                        _handle_diversion(divertsock, dnsport)
                    if sys.stdin in r:
                        return
        else:
            do_wait = None

        return do_wait
Пример #45
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp):
        # IPv6 not supported
        if family not in [
                socket.AF_INET,
        ]:
            raise Exception(
                'Address family "%s" unsupported by ipfw method_name' %
                family_to_string(family))
        if udp:
            raise Exception("UDP not supported by ipfw method_name")

        sport = str(port)
        xsport = str(port + 1)

        # cleanup any existing rules
        if ipfw_rule_exists(port):
            ipfw('delete', sport)

        while _changedctls:
            name = _changedctls.pop()
            oldval = _oldctls[name]
            _sysctl_set(name, oldval)

        if subnets or dnsport:
            sysctl_set('net.inet.ip.fw.enable', 1)
            changed = sysctl_set('net.inet.ip.scopedroute', 0, permanent=True)
            if changed:
                log("\n"
                    "        WARNING: ONE-TIME NETWORK DISRUPTION:\n"
                    "        =====================================\n"
                    "sshuttle has changed a MacOS kernel setting to work around\n"
                    "a bug in MacOS 10.6.  This will cause your network to drop\n"
                    "within 5-10 minutes unless you restart your network\n"
                    "interface (change wireless networks or unplug/plug the\n"
                    "ethernet port) NOW, then restart sshuttle.  The fix is\n"
                    "permanent; you only have to do this once.\n\n")
                sys.exit(1)

            ipfw('add', sport, 'check-state', 'ip', 'from', 'any', 'to', 'any')

        if subnets:
            # create new subnet entries
            for f, swidth, sexclude, snet \
                    in sorted(subnets, key=lambda s: s[1], reverse=True):
                if sexclude:
                    ipfw('add', sport, 'skipto', xsport, 'tcp', 'from', 'any',
                         'to', '%s/%s' % (snet, swidth))
                else:
                    ipfw('add', sport, 'fwd', '127.0.0.1,%d' % port, 'tcp',
                         'from', 'any', 'to', '%s/%s' % (snet, swidth), 'not',
                         'ipttl', '42', 'keep-state', 'setup')

        # This part is much crazier than it is on Linux, because MacOS (at
        # least 10.6, and probably other versions, and maybe FreeBSD too)
        # doesn't correctly fixup the dstip/dstport for UDP packets when it
        # puts them through a 'fwd' rule.  It also doesn't fixup the
        # srcip/srcport in the response packet.  In Linux iptables, all that
        # happens magically for us, so we just redirect the packets and relax.
        #
        # On MacOS, we have to fix the ports ourselves.  For that, we use a
        # 'divert' socket, which receives raw packets and lets us mangle them.
        #
        # Here's how it works.  Let's say the local DNS server is 1.1.1.1:53,
        # and the remote DNS server is 2.2.2.2:53, and the local transproxy
        # port is 10.0.0.1:12300, and a client machine is making a request from
        # 10.0.0.5:9999. We see a packet like this:
        #    10.0.0.5:9999 -> 1.1.1.1:53
        # Since the destip:port matches one of our local nameservers, it will
        # match a 'fwd' rule, thus grabbing it on the local machine.  However,
        # the local kernel will then see a packet addressed to *:53 and not
        # know what to do with it; there's nobody listening on port 53.  Thus,
        # we divert it, rewriting it into this:
        #    10.0.0.5:9999 -> 10.0.0.1:12300
        # This gets proxied out to the server, which sends it to 2.2.2.2:53,
        # and the answer comes back, and the proxy sends it back out like this:
        #    10.0.0.1:12300 -> 10.0.0.5:9999
        # But that's wrong!  The original machine expected an answer from
        # 1.1.1.1:53, so we have to divert the *answer* and rewrite it:
        #    1.1.1.1:53 -> 10.0.0.5:9999
        #
        # See?  Easy stuff.
        if dnsport:
            divertsock = socket.socket(socket.AF_INET, socket.SOCK_RAW,
                                       IPPROTO_DIVERT)
            divertsock.bind(('0.0.0.0', port))  # IP field is ignored

            for f, ip in [i for i in nslist if i[0] == family]:
                # relabel and then catch outgoing DNS requests
                ipfw('add', sport, 'divert', sport, 'udp', 'from', 'any', 'to',
                     '%s/32' % ip, '53', 'not', 'ipttl', '42')
            # relabel DNS responses
            ipfw('add', sport, 'divert', sport, 'udp', 'from', 'any',
                 str(dnsport), 'to', 'any', 'not', 'ipttl', '42')

            def do_wait():
                while 1:
                    r, w, x = select.select([sys.stdin, divertsock], [], [])
                    if divertsock in r:
                        _handle_diversion(divertsock, dnsport)
                    if sys.stdin in r:
                        return
        else:
            do_wait = None

        return do_wait
Пример #46
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp):
        tables = []
        translating_rules = []
        filtering_rules = []

        if family != socket.AF_INET:
            raise Exception(
                'Address family "%s" unsupported by pf method_name'
                % family_to_string(family))
        if udp:
            raise Exception("UDP not supported by pf method_name")

        if len(subnets) > 0:
            includes = []
            # If a given subnet is both included and excluded, list the
            # exclusion first; the table will ignore the second, opposite
            # definition
            for f, swidth, sexclude, snet in sorted(
                    subnets, key=lambda s: (s[1], s[2]), reverse=True):
                includes.append(b"%s%s/%d" %
                                (b"!" if sexclude else b"",
                                    snet.encode("ASCII"),
                                    swidth))

            tables.append(
                b'table <forward_subnets> {%s}' % b','.join(includes))
            translating_rules.append(
                b'rdr pass on lo0 proto tcp '
                b'to <forward_subnets> -> 127.0.0.1 port %r' % port)
            filtering_rules.append(
                b'pass out route-to lo0 inet proto tcp '
                b'to <forward_subnets> keep state')

        if len(nslist) > 0:
            tables.append(
                b'table <dns_servers> {%s}' %
                b','.join([ns[1].encode("ASCII") for ns in nslist]))
            translating_rules.append(
                b'rdr pass on lo0 proto udp to '
                b'<dns_servers> port 53 -> 127.0.0.1 port %r' % dnsport)
            filtering_rules.append(
                b'pass out route-to lo0 inet proto udp to '
                b'<dns_servers> port 53 keep state')

        rules = b'\n'.join(tables + translating_rules + filtering_rules) \
                + b'\n'
        assert isinstance(rules, bytes)
        debug3("rules:\n" + rules.decode("ASCII"))

        pf_status = pfctl('-s all')[0]
        if b'\nrdr-anchor "sshuttle" all\n' not in pf_status:
            pf_add_anchor_rule(osdefs.PF_RDR, b"sshuttle")
        if b'\nanchor "sshuttle" all\n' not in pf_status:
            pf_add_anchor_rule(osdefs.PF_PASS, b"sshuttle")

        pfctl('-a sshuttle -f /dev/stdin', rules)
        if osdefs.platform == "darwin":
            o = pfctl('-E')
            _pf_context['Xtoken'] = \
                re.search(b'Token : (.+)', o[1]).group(1)
        elif b'INFO:\nStatus: Disabled' in pf_status:
            pfctl('-e')
            _pf_context['started_by_sshuttle'] = True
Пример #47
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
                       user):
        # only ipv4 supported with NAT
        if family != socket.AF_INET:
            raise Exception(
                'Address family "%s" unsupported by nat method_name'
                % family_to_string(family))
        if udp:
            raise Exception("UDP not supported by nat method_name")

        table = "nat"

        def _ipt(*args):
            return ipt(family, table, *args)

        def _ipt_ttl(*args):
            return ipt_ttl(family, table, *args)

        def _ipm(*args):
            return ipt(family, "mangle", *args)

        chain = 'sshuttle-%s' % port

        # basic cleanup/setup of chains
        self.restore_firewall(port, family, udp, user)

        _ipt('-N', chain)
        _ipt('-F', chain)
        if user is not None:
            _ipm('-I', 'OUTPUT', '1', '-m', 'owner', '--uid-owner', str(user),
                 '-j', 'MARK', '--set-mark', str(port))
            args = '-m', 'mark', '--mark', str(port), '-j', chain
        else:
            args = '-j', chain

        _ipt('-I', 'OUTPUT', '1', *args)
        _ipt('-I', 'PREROUTING', '1', *args)

        # This TTL hack allows the client and server to run on the
        # same host. The connections the sshuttle server makes will
        # have TTL set to ssnet.TUNNEL_TTL.
        _ipt_ttl('-A', chain, '-j', 'RETURN',  '-m', 'ttl', '--ttl', ssnet.TUNNEL_TTL)

        # Redirect DNS traffic as requested. This includes routing traffic
        # to localhost DNS servers through sshuttle.
        for _, ip in [i for i in nslist if i[0] == family]:
            _ipt('-A', chain, '-j', 'REDIRECT',
                 '--dest', '%s/32' % ip,
                 '-p', 'udp',
                 '--dport', '53',
                 '--to-ports', str(dnsport))

        # Don't route any remaining local traffic through sshuttle.
        _ipt('-A', chain, '-j', 'RETURN',
             '-m', 'addrtype',
             '--dst-type', 'LOCAL')

        # create new subnet entries.
        for _, swidth, sexclude, snet, fport, lport \
                in sorted(subnets, key=subnet_weight, reverse=True):
            tcp_ports = ('-p', 'tcp')
            if fport:
                tcp_ports = tcp_ports + ('--dport', '%d:%d' % (fport, lport))

            if sexclude:
                _ipt('-A', chain, '-j', 'RETURN',
                     '--dest', '%s/%s' % (snet, swidth),
                     *tcp_ports)
            else:
                _ipt('-A', chain, '-j', 'REDIRECT',
                     '--dest', '%s/%s' % (snet, swidth),
                     *(tcp_ports + ('--to-ports', str(port))))
Пример #48
0
    def setup_firewall_tproxy(self, port, dnsport, nslist, family, subnets,
                              udp, user, tmark):
        if family not in [socket.AF_INET, socket.AF_INET6]:
            raise Exception(
                'Address family "%s" unsupported by tproxy method' %
                family_to_string(family))

        table = "mangle"

        def _ipt(*args):
            return ipt(family, table, *args)

        def _ipt_ttl(*args):
            return ipt_ttl(family, table, *args)

        def _ipt_proto_ports(proto, fport, lport):
            return proto + ('--dport', '%d:%d' % (fport, lport)) \
                    if fport else proto

        mark_chain = 'sshuttle-m-%s' % port
        tproxy_chain = 'sshuttle-t-%s' % port
        divert_chain = 'sshuttle-d-%s' % port

        # basic cleanup/setup of chains
        self.restore_firewall(port, family, udp, user)

        _ipt('-N', mark_chain)
        _ipt('-F', mark_chain)
        _ipt('-N', divert_chain)
        _ipt('-F', divert_chain)
        _ipt('-N', tproxy_chain)
        _ipt('-F', tproxy_chain)
        _ipt('-I', 'OUTPUT', tmark, '-j', mark_chain)
        _ipt('-I', 'PREROUTING', tmark, '-j', tproxy_chain)

        # Don't have packets sent to any of our local IP addresses go
        # through the tproxy or mark chains.
        #
        # Without this fix, if a large subnet is redirected through
        # sshuttle (i.e., 0/0), then the user may be unable to receive
        # UDP responses or connect to their own machine using an IP
        # besides (127.0.0.1). Prior to including these lines, the
        # documentation reminded the user to use -x to exclude their
        # own IP addresses to receive UDP responses if they are
        # redirecting a large subnet through sshuttle (i.e., 0/0).
        _ipt('-A', tproxy_chain, '-j', 'RETURN', '-m', 'addrtype',
             '--dst-type', 'LOCAL')
        _ipt('-A', mark_chain, '-j', 'RETURN', '-m', 'addrtype', '--dst-type',
             'LOCAL')

        _ipt('-A', divert_chain, '-j', 'MARK', '--set-mark', tmark)
        _ipt('-A', divert_chain, '-j', 'ACCEPT')
        _ipt('-A', tproxy_chain, '-m', 'socket', '-j', divert_chain, '-m',
             'tcp', '-p', 'tcp')

        if udp:
            _ipt('-A', tproxy_chain, '-m', 'socket', '-j', divert_chain, '-m',
                 'udp', '-p', 'udp')

        for _, ip in [i for i in nslist if i[0] == family]:
            _ipt('-A', mark_chain, '-j', 'MARK', '--set-mark', tmark, '--dest',
                 '%s/32' % ip, '-m', 'udp', '-p', 'udp', '--dport', '53')
            _ipt('-A', tproxy_chain, '-j', 'TPROXY', '--tproxy-mark',
                 '0x' + tmark + '/0x' + tmark, '--dest', '%s/32' % ip,
                 '-m', 'udp', '-p', 'udp', '--dport', '53', '--on-port',
                 str(dnsport))

        for _, swidth, sexclude, snet, fport, lport \
                in sorted(subnets, key=subnet_weight, reverse=True):
            tcp_ports = ('-p', 'tcp')
            tcp_ports = _ipt_proto_ports(tcp_ports, fport, lport)

            if sexclude:
                _ipt('-A', mark_chain, '-j', 'RETURN', '--dest',
                     '%s/%s' % (snet, swidth), '-m', 'tcp', *tcp_ports)
                _ipt('-A', tproxy_chain, '-j', 'RETURN', '--dest',
                     '%s/%s' % (snet, swidth), '-m', 'tcp', *tcp_ports)
            else:
                _ipt('-A', mark_chain, '-j', 'MARK', '--set-mark', tmark,
                     '--dest', '%s/%s' % (snet, swidth), '-m', 'tcp',
                     *tcp_ports)
                _ipt('-A', tproxy_chain, '-j', 'TPROXY', '--tproxy-mark',
                     '0x' + tmark + '/0x' + tmark, '--dest',
                     '%s/%s' % (snet, swidth), '-m', 'tcp',
                     *(tcp_ports + ('--on-port', str(port))))

            if udp:
                udp_ports = ('-p', 'udp')
                udp_ports = _ipt_proto_ports(udp_ports, fport, lport)

                if sexclude:
                    _ipt('-A', mark_chain, '-j', 'RETURN', '--dest',
                         '%s/%s' % (snet, swidth), '-m', 'udp', *udp_ports)
                    _ipt('-A', tproxy_chain, '-j', 'RETURN', '--dest',
                         '%s/%s' % (snet, swidth), '-m', 'udp', *udp_ports)
                else:
                    _ipt('-A', mark_chain, '-j', 'MARK', '--set-mark', tmark,
                         '--dest', '%s/%s' % (snet, swidth), '-m', 'udp',
                         *udp_ports)
                    _ipt('-A', tproxy_chain, '-j', 'TPROXY', '--tproxy-mark',
                         '0x' + tmark + '/0x' + tmark, '--dest',
                         '%s/%s' % (snet, swidth), '-m', 'udp',
                         *(udp_ports + ('--on-port', str(port))))
Пример #49
0
    def setup_firewall(self, port, dnsport, nslist, family, subnets, udp):
        if family not in [socket.AF_INET, socket.AF_INET6]:
            raise Exception(
                'Address family "%s" unsupported by tproxy method' %
                family_to_string(family))

        table = "mangle"

        def _ipt(*args):
            return ipt(family, table, *args)

        def _ipt_ttl(*args):
            return ipt_ttl(family, table, *args)

        mark_chain = 'sshuttle-m-%s' % port
        tproxy_chain = 'sshuttle-t-%s' % port
        divert_chain = 'sshuttle-d-%s' % port

        # basic cleanup/setup of chains
        if ipt_chain_exists(family, table, mark_chain):
            _ipt('-D', 'OUTPUT', '-j', mark_chain)
            _ipt('-F', mark_chain)
            _ipt('-X', mark_chain)

        if ipt_chain_exists(family, table, tproxy_chain):
            _ipt('-D', 'PREROUTING', '-j', tproxy_chain)
            _ipt('-F', tproxy_chain)
            _ipt('-X', tproxy_chain)

        if ipt_chain_exists(family, table, divert_chain):
            _ipt('-F', divert_chain)
            _ipt('-X', divert_chain)

        if subnets or dnsport:
            _ipt('-N', mark_chain)
            _ipt('-F', mark_chain)
            _ipt('-N', divert_chain)
            _ipt('-F', divert_chain)
            _ipt('-N', tproxy_chain)
            _ipt('-F', tproxy_chain)
            _ipt('-I', 'OUTPUT', '1', '-j', mark_chain)
            _ipt('-I', 'PREROUTING', '1', '-j', tproxy_chain)
            _ipt('-A', divert_chain, '-j', 'MARK', '--set-mark', '1')
            _ipt('-A', divert_chain, '-j', 'ACCEPT')
            _ipt('-A', tproxy_chain, '-m', 'socket', '-j', divert_chain, '-m',
                 'tcp', '-p', 'tcp')
        if subnets and udp:
            _ipt('-A', tproxy_chain, '-m', 'socket', '-j', divert_chain, '-m',
                 'udp', '-p', 'udp')

        if dnsport:
            for f, ip in [i for i in nslist if i[0] == family]:
                _ipt('-A', mark_chain, '-j', 'MARK', '--set-mark', '1',
                     '--dest', '%s/32' % ip, '-m', 'udp', '-p', 'udp',
                     '--dport', '53')
                _ipt('-A', tproxy_chain, '-j', 'TPROXY', '--tproxy-mark',
                     '0x1/0x1', '--dest', '%s/32' % ip, '-m', 'udp', '-p',
                     'udp', '--dport', '53', '--on-port', str(dnsport))

        if subnets:
            for f, swidth, sexclude, snet \
                    in sorted(subnets, key=lambda s: s[1], reverse=True):
                if sexclude:
                    _ipt('-A', mark_chain, '-j', 'RETURN', '--dest',
                         '%s/%s' % (snet, swidth), '-m', 'tcp', '-p', 'tcp')
                    _ipt('-A', tproxy_chain, '-j', 'RETURN', '--dest',
                         '%s/%s' % (snet, swidth), '-m', 'tcp', '-p', 'tcp')
                else:
                    _ipt('-A', mark_chain, '-j', 'MARK', '--set-mark', '1',
                         '--dest', '%s/%s' % (snet, swidth), '-m', 'tcp', '-p',
                         'tcp')
                    _ipt('-A', tproxy_chain, '-j', 'TPROXY', '--tproxy-mark',
                         '0x1/0x1', '--dest', '%s/%s' % (snet, swidth), '-m',
                         'tcp', '-p', 'tcp', '--on-port', str(port))

                if sexclude and udp:
                    _ipt('-A', mark_chain, '-j', 'RETURN', '--dest',
                         '%s/%s' % (snet, swidth), '-m', 'udp', '-p', 'udp')
                    _ipt('-A', tproxy_chain, '-j', 'RETURN', '--dest',
                         '%s/%s' % (snet, swidth), '-m', 'udp', '-p', 'udp')
                elif udp:
                    _ipt('-A', mark_chain, '-j', 'MARK', '--set-mark', '1',
                         '--dest', '%s/%s' % (snet, swidth), '-m', 'udp', '-p',
                         'udp')
                    _ipt('-A', tproxy_chain, '-j', 'TPROXY', '--tproxy-mark',
                         '0x1/0x1', '--dest', '%s/%s' % (snet, swidth), '-m',
                         'udp', '-p', 'udp', '--on-port', str(port))