Example #1
0
    def __init__(self, config):
        self._interface = config.pop('interface', 'eth0')
        util.assert_like_interface_name(self._interface)

        self._priority = config.pop('priority')
        util.assert_number_in_range(self._priority, 0, 255)

        self._id = config.pop('id')
        util.assert_number_in_range(self._id, 1, 255)

        self._pass = str(config.pop('pass')).strip()
        if len(self._pass) == 0:
            raise ValueError("No vrrp password specified!")
        if len(self._pass) > 8:
            logger.warn("Only first 8 characters of vrrp password will be used.")
Example #2
0
 def run(outdir, diff, no_write, no_exec, no_git):
     if util.write_file(outdir, 'ipsec-tools.conf',
                        _render_ipsec_tools(tunnels), no_write, diff):
         if os.geteuid() == 0:
             util.cmd(('/etc/ipsec-tools.conf',), no_exec)
     if any([
         util.write_file(outdir, 'racoon/psk.txt', _render_racoon_psk(tunnels), no_write, diff),
         util.write_file(outdir, 'racoon/racoon.conf', _render_racoon(tunnels), no_write, diff),
     ]):
         if os.geteuid() == 0:
             util.cmd(('racoonctl', 'reload-config'), no_exec)
     if util.write_file(outdir, 'network/interfaces.d/caretakr.ipsec.conf',
                        _render_interfaces(internal_interfaces), no_write, diff=True):
         logger.warn("Automatic activation of interface changes not implemented!")
     util.git_commit(outdir, ['ipsec-tools.conf',
                              'racoon/psk.txt', 'racoon/racoon.conf',
                              'network/interfaces.d/caretakr.ipsec.conf'], no_git, 'ipsec')
Example #3
0
def _custom_rules(custom, interfaces):
    _expand_interface = lambda iface: interfaces.get(iface, iface)
    stages = defaultdict(dict)
    for table, chains in custom.iteritems():
        for chain, rules in chains.iteritems():
            for rule in rules:
                stage = rule.pop('stage', 'middle')
                comment = rule.pop('comment', None)
                command = rule.pop('command', 'A')
                i = map(_expand_interface, util.flatten(rule.pop('i', [])))
                o = map(_expand_interface, util.flatten(rule.pop('o', [])))
                s = check_wildcard(rule.pop('s', []))
                d = check_wildcard(rule.pop('d', []))
                r = rule.pop('r', '-j ACCEPT')
                if len(rule) > 0:
                    logger.warn("Unrecognized options in custom rule: %s" % rule)
                ruleset = stages[stage].setdefault((table, chain),
                                                   firewall.IPTablesRuleset(table, chain))
                ruleset.add(comment=comment, command=command, i=i, o=o, s=s, d=d, r=r)
    return stages
Example #4
0
    def _resolve(fqdn):
        ipv4 = []
        try:
            a_result = dns.resolver.query(fqdn, dns.rdatatype.A)
            ipv4 = sorted([ipaddr.IPv4Address(rr.to_text()) for rr in a_result.rrset])
        except dns.resolver.NoAnswer:
            pass
        except dns.resolver.NXDOMAIN:
            pass
        except dns.resolver.Timeout:
            logger.warn("DNS Resolver timeout on resolving A record of %s" % fqdn)
            pass
        ipv6 = []
        try:
            aaaa_result = dns.resolver.query(fqdn, dns.rdatatype.AAAA)
            ipv6 = sorted([ipaddr.IPv6Address(rr.to_text()) for rr in aaaa_result.rrset])
        except dns.resolver.NoAnswer:
            pass
        except dns.resolver.NXDOMAIN:
            pass
        except dns.resolver.Timeout:
            logger.warn("DNS Resolver timeout on resolving AAAA record of %s" % fqdn)
            pass
        if len(ipv4) == 0 and len(ipv6) == 0:
            logger.warn("No A or AAAA found for %s!" % fqdn)

        return ipv4, ipv6
Example #5
0
    def __init__(self, name, redir_dict, ff_ssl_catchall):
        self.name = name
        self.server_name = util.HostIPPort(redir_dict.pop('fqdn'))
        self.redirect = redir_dict.pop('redirect')
        self.catchall = find_catchall_for_app(self.server_name.fqdn,
                                              redir_dict.pop('catchall', None),
                                              ff_ssl_catchall)
        if 'hsts_max_age' in redir_dict:
            self.hsts_max_age = int(redir_dict.pop('hsts_max_age'))
        else:
            self.hsts_max_age = None
        self.ssl = redir_dict.pop('ssl', self.catchall.ssl)

        server_name_ips = self.server_name.addresses
        catchall_ips = util.flatten([listen.addresses
                                     for listen in self.catchall.listen])
        if len(set(server_name_ips) - set(catchall_ips)) > 0:
            logger.warn("%s %s (%s) resolves to [%s] but catchall (%s) listens on [%s]" %
                        (type(self).__name__, self._name, self.server_name.fqdn,
                         ', '.join([str(x) for x in server_name_ips]),
                         self.catchall.name,
                         ', '.join([str(x) for x in catchall_ips])))
Example #6
0
    def __init__(self, name, app_dict, ff_ssl_catchall):
        self.name = name
        self.appnode = util.HostIPPort(app_dict.pop('appnode'))
        self.server_name = util.HostIPPort(app_dict.pop('fqdn'))
        self.catchall = find_catchall_for_app(self.server_name.fqdn,
                                              app_dict.pop('catchall', None),
                                              ff_ssl_catchall)
        self.client_max_body_size = app_dict.pop('client_max_body_size', '1024M')
        self.hsts_max_age = app_dict.pop('hsts_max_age', None)
        self.x_frame_options = app_dict.pop('x_frame_options', None)
        self.ssl = app_dict.pop('ssl', self.catchall.ssl)
        self.ssl_client_certificate = app_dict.pop('ssl_client_certificate', None)
        self.ssl_crl = app_dict.pop('ssl_crl', None)
        self.ssl_verify_client = app_dict.pop('ssl_verify_client', 'on')

        server_name_ips = self.server_name.addresses
        catchall_ips = util.flatten([listen.addresses
                                     for listen in self.catchall.listen])
        if len(set(server_name_ips) - set(catchall_ips)) > 0:
            logger.warn("%s %s (%s) resolves to [%s] but catchall (%s) listens on [%s]" %
                        (type(self).__name__, self.name, self.server_name.fqdn,
                         ', '.join([str(x) for x in server_name_ips]),
                         self.catchall.name,
                         ', '.join([str(x) for x in catchall_ips])))
Example #7
0
def load(config):
    logger.trace("config: %s" % config)
    icmp_stateful = config.pop('icmp_stateful', True)
    ipv6_nat = config.pop('ipv6_nat', False)

    interfaces = _expand_interfaces(config.pop('interfaces', {}))

    input_ssh_from = check_wildcard(config.pop('input_ssh_from', []))
    input_munin_from = check_wildcard(config.pop('input_munin_from', None))
    input_nrpe_from = check_wildcard(config.pop('input_nrpe_from', None))
    input_dns_from = check_wildcard(config.pop('input_dns_from', None))
    input_dns_notrack = config.pop('input_dns_notrack', False)
    input_http_from = check_wildcard(config.pop('input_http_from', None))
    input_http_port = check_wildcard(config.pop('input_http_port', [80, 443]))
    input_http_notrack = config.pop('input_http_notrack', False)
    input_smtp_from = check_wildcard(config.pop('input_smtp_from', None))
    input_postgresql_from = check_wildcard(config.pop('input_postgresql_from', None))
    input_xmpp_c2s_from = check_wildcard(config.pop('input_xmpp_c2s_from', None))
    input_nsca_from = check_wildcard(config.pop('input_nsca_from', None))

    output_dns_to = check_wildcard(config.pop('output_dns_to', []))
    output_ntp_to = check_wildcard(config.pop('output_ntp_to', []))
    output_http_to = check_wildcard(config.pop('output_http_to', None))
    output_http_port = check_wildcard(config.pop('output_http_port', [80, 443]))
    output_smtp_to = check_wildcard(config.pop('output_smtp_to', []))
    output_munin_to = check_wildcard(config.pop('output_munin_to', None))
    output_nsca_to = check_wildcard(config.pop('output_nsca_to', None))
    output_postgresql_to = check_wildcard(config.pop('output_postgresql_to', None))
    output_xmpp_c2s_to = check_wildcard(config.pop('output_xmpp_c2s_to', None))
    output_user = config.pop('output_user', None)
    output_group = config.pop('output_group', None)

    xmpp_s2s_fromto = check_wildcard(config.pop('xmpp_s2s_fromto', None))
    gre_peers = check_wildcard(config.pop('gre_peers', None))

    if any([input_dns_notrack, input_http_notrack]):
        logger.debug("notrack option set, early accepting icmp")
        icmp_stateful = False

    input_tcp = config.pop('input_tcp', [])
    input_udp = config.pop('input_udp', [])
    output_tcp = config.pop('output_tcp', [])
    output_udp = config.pop('output_udp', [])
    custom = _custom_rules(config.pop('custom', {}), interfaces)

    input_log_ignore = config.pop('input_log_ignore', None)
    input_log_limit = config.pop('input_log_limit', None)
    input_log_burst = config.pop('input_log_burst', None)
    output_log_ignore = config.pop('output_log_ignore', None)
    output_log_limit = config.pop('output_log_limit', None)
    output_log_burst = config.pop('output_log_burst', None)

    forwarding = False
    stateful_forward = config.pop('stateful_forward', True)
    customer_ipsec_gateway = util.flatten(config.pop('customer_ipsec_gateway', []))
    if len(customer_ipsec_gateway) > 0:
        logger.debug("customer ipsec gateway set, enabling forwarding")
        forwarding = True

    fh = IPTablesHostsAllow()
    fh.fw.enable_ipv6_nat(ipv6_nat)

    logger.debug("creating rules for early phase")
    fh.add(libow.early_lo())
    if input_dns_from is not None and input_dns_notrack is True:
        fh.add(libow.input_dns(input_dns_from, input_dns_notrack))
    if input_http_from is not None and input_http_notrack is True:
        fh.add(libow.input_http(input_http_from, input_http_port, input_http_notrack))
    fh.add(custom['early'].values())

    logger.debug("creating rules for start phase")
    if icmp_stateful is False:
        fh.add(libow.input_icmp())
        fh.add(libow.output_icmp())
    fh.add(libow.start('INPUT'))
    fh.add(libow.start('OUTPUT'))
    if icmp_stateful is True:
        fh.add(libow.stateful_input_icmp())
        fh.add(libow.output_icmp())
    if forwarding is True:
        if stateful_forward is True:
            fh.add(libow.start('FORWARD'))
        fh.add(libow.forward_icmp())
    fh.add(custom['start'].values())

    logger.debug("creating rules for middle phase")
    if input_ssh_from is not None:
        fh.add(libow.input_ssh(input_ssh_from))
    if input_munin_from is not None:
        fh.add(libow.input_tcp(input_munin_from, 4949))
    if input_nrpe_from is not None:
        fh.add(libow.input_nrpe(input_nrpe_from))
    if input_dns_from is not None and input_dns_notrack is False:
        fh.add(libow.input_dns(input_dns_from, input_dns_notrack))
    if input_http_from is not None and input_http_notrack is False:
        fh.add(libow.input_http(input_http_from, input_http_port, input_http_notrack))
    if input_smtp_from is not None:
        fh.add(libow.input_tcp(input_smtp_from, 25))
    if input_postgresql_from is not None:
        fh.add(libow.input_tcp(input_postgresql_from, 5432))
    if input_xmpp_c2s_from is not None:
        fh.add(libow.input_tcp(input_xmpp_c2s_from, 5222))
        fh.add(libow.input_tcp([], 7777))  # XXX: unfiltered?
    for rule in input_tcp:
        comment = rule.get('comment', None)
        s = check_wildcard(rule.get('from', []))
        port = rule.get('port', None)
        fh.add(libow.input_tcp(comment=comment, s=s, port=port))
    for rule in input_udp:
        comment = rule.get('comment', None)
        s = check_wildcard(rule.get('from', []))
        port = rule.get('port', None)
        fh.add(libow.input_udp(comment=comment, s=s, port=port))
    if input_nsca_from is not None:
        fh.add(libow.input_tcp(input_nsca_from, 5667))
    if xmpp_s2s_fromto is not None:
        fh.add(libow.input_tcp(xmpp_s2s_fromto, 5269))
    if gre_peers is not None:
        fh.add(libow.input_gre(gre_peers))
    if output_dns_to is not None:
        fh.add(libow.output_dns(output_dns_to))
    if output_ntp_to is not None:
        fh.add(libow.output_udp(output_ntp_to, 123, uid='ntp'))
    if output_http_to is not None:
        fh.add(libow.output_http(output_http_to, output_http_port))
    if output_smtp_to is not None:
        fh.add(libow.output_tcp(output_smtp_to, 25, uid='postfix'))
    if output_munin_to is not None:
        fh.add(libow.output_tcp(output_munin_to, 4949, uid='munin'))
    if output_nsca_to is not None:
        fh.add(libow.output_tcp(output_nsca_to, 5667))
    if output_postgresql_to is not None:
        fh.add(libow.output_tcp(output_postgresql_to, 5432))
    if output_xmpp_c2s_to is not None:
        fh.add(libow.output_tcp(output_xmpp_c2s_to, 5222))
    if xmpp_s2s_fromto is not None:
        fh.add(libow.output_tcp(xmpp_s2s_fromto, 5269, uid='ejabberd'))
    if gre_peers is not None:
        fh.add(libow.output_gre(gre_peers))
    for rule in output_tcp:
        comment = rule.get('comment', None)
        d = check_wildcard(rule.get('to', []))
        port = rule.get('port', None)
        uid = rule.get('uid', None)
        fh.add(libow.output_tcp(comment=comment, d=d, port=port, uid=uid))
    for rule in output_udp:
        comment = rule.get('comment', None)
        d = check_wildcard(rule.get('to', []))
        port = rule.get('port', None)
        uid = rule.get('uid', None)
        fh.add(libow.output_udp(comment=comment, d=d, port=port, uid=uid))
    if output_user is not None:
        output_user = util.flatten(output_user)
        for user in output_user:
            if isinstance(user, str):
                fh.add(libow.output_tcp(d=[], uid=user))
            elif isinstance(user, int):
                fh.add(libow.output_tcp(d=[], uid=str(user)))
            else:
                raise Exception("don't understand output_user %s" % user)
    if output_group is not None:
        output_group = util.flatten(output_group)
        for group in output_group:
            if isinstance(group, str):
                fh.add(libow.output_tcp(d=[], gid=group))
            elif isinstance(group, int):
                fh.add(libow.output_tcp(d=[], gid=str(group)))
            else:
                raise Exception("don't understand output_group %s" % group)
    if len(customer_ipsec_gateway) > 0:
        for cig in customer_ipsec_gateway:
            fh.add(libow.customer_ipsec_gateway(
                remote_endpoint=cig['remote_endpoint'],
                remote_subnets=cig['remote_subnets'],
                local_subnets=cig['local_subnets'],
                allow_incoming_traffic=cig.get('allow_incoming_traffic', False),
                snat=cig.get('snat', None)
            ))
    fh.add(custom['middle'].values())

    logger.debug("creating rules for end phase")
    fh.add(libow.input_traceroute())
    fh.add(libow.output_beheer_root())
    fh.add(custom['end'].values())

    logger.debug("creating rules for late phase")
    fh.add(libow.log('INPUT', input_log_ignore, input_log_limit, input_log_burst))
    fh.add(libow.log('OUTPUT', output_log_ignore, output_log_limit, output_log_burst))
    fh.add(custom['late'].values())

    for hosts_allow in config.pop('hosts_allow', []):
        daemon = hosts_allow.pop('daemon')
        s = hosts_allow.pop('from', None)
        if '*' in util.flatten(s):
            s = 'all'
        if len(hosts_allow) > 0:
            logger.warn("Unrecognized options in hosts_allow rule: %s" % hosts_allow)

        fh.add(libow.hosts_allow(daemon, s))

    firewall_lines = fh.fw.get_iptables_restore_script(4).splitlines()
    firewall6_lines = fh.fw.get_iptables_restore_script(6).splitlines()
    hosts_allow_lines = fh.ha.get_hosts_allow_content().splitlines()

    additional_config = None

    def run(outdir, diff, no_write, no_exec, no_git):
        if any([
            util.write_file(outdir, 'network/firewall', firewall_lines, no_write, diff),
            util.write_file(outdir, 'network/firewall6', firewall6_lines, no_write, diff),
            util.write_file(outdir, 'hosts.allow', hosts_allow_lines, no_write, diff),
        ]):
            if os.geteuid() == 0:
                if no_exec is True:
                    util.cmd(('/sbin/iptables-restore', '-t'), dry_run=False, stdin=firewall_lines)
                    util.cmd(('/sbin/ip6tables-restore', '-t'),
                             dry_run=False, stdin=firewall6_lines)
                else:
                    util.cmd(('/sbin/iptables-restore'), dry_run=False, stdin=firewall_lines)
                    util.cmd(('/sbin/ip6tables-restore'), dry_run=False, stdin=firewall6_lines)
            util.git_commit(outdir, ['network/firewall', 'network/firewall6', 'hosts.allow'],
                            no_git, 'firewall')

    return run, additional_config