modify nodes and bundles for new nftables syntax

This commit is contained in:
Franzi 2021-06-03 13:59:15 +02:00
parent ecb67d012b
commit d569b00960
Signed by: kunsi
GPG key ID: 12E3D2136B818350
30 changed files with 172 additions and 126 deletions

View file

@ -37,18 +37,20 @@ def get_static_allocations(metadata):
@metadata_reactor.provides( @metadata_reactor.provides(
'iptables/bundle_rules/dhcpd', 'nftables/rules/input/dhcpd',
) )
def iptables(metadata): def nftables(metadata):
rules = set() rules = set()
for subnet in node.metadata.get('dhcpd/subnets', {}): for iface in node.metadata.get('dhcpd/subnets', {}):
rules.add('iptables -A INPUT -i {} -p udp --dport 67:68 -j ACCEPT'.format(subnet)) rules.add(f'udp dport {{ 67, 68 }} iif {iface} accept')
return { return {
'iptables': { 'nftables': {
'bundle_rules': { 'rules': {
'input': {
# can't use port_rules here, because we're generating interface based rules. # can't use port_rules here, because we're generating interface based rules.
'dhcpd': sorted(list(rules)), 'dhcpd': sorted(rules),
},
}, },
} }
} }

View file

@ -76,13 +76,13 @@ def import_database_settings_from_postfixadmin(metadata):
@metadata_reactor.provides( @metadata_reactor.provides(
'iptables/port_rules/143', 'firewall/port_rules/143',
'iptables/port_rules/993', 'firewall/port_rules/993',
'iptables/port_rules/4190', 'firewall/port_rules/4190',
) )
def iptables(metadata): def firewall(metadata):
return { return {
'iptables': { 'firewall': {
'port_rules': { 'port_rules': {
# imap(s) # imap(s)
'143': atomic(metadata.get('dovecot/restrict-to', {'*'})), '143': atomic(metadata.get('dovecot/restrict-to', {'*'})),

View file

@ -103,11 +103,11 @@ def add_users_from_json(metadata):
@metadata_reactor.provides( @metadata_reactor.provides(
'iptables/port_rules/5665', 'firewall/port_rules/5665',
) )
def iptables(metadata): def firewall(metadata):
return { return {
'iptables': { 'firewall': {
'port_rules': { 'port_rules': {
'5665': atomic(metadata.get('icinga2/restrict-to', set())), '5665': atomic(metadata.get('icinga2/restrict-to', set())),
}, },

View file

@ -44,11 +44,11 @@ defaults = {
@metadata_reactor.provides( @metadata_reactor.provides(
'iptables/port_rules/8080', 'firewall/port_rules/8080',
) )
def iptables(metadata): def firewall(metadata):
return { return {
'iptables': { 'firewall': {
'port_rules': { 'port_rules': {
'8080': atomic(metadata.get('kodi/restrict-to', {'*'})), '8080': atomic(metadata.get('kodi/restrict-to', {'*'})),
}, },

View file

@ -26,9 +26,9 @@ defaults = {
@metadata_reactor.provides( @metadata_reactor.provides(
'iptables/port_rules', 'firewall/port_rules',
) )
def iptables(metadata): def firewall(metadata):
sources = metadata.get('mosquitto/restrict-to', {'*'}) sources = metadata.get('mosquitto/restrict-to', {'*'})
result = {} result = {}
@ -36,7 +36,7 @@ def iptables(metadata):
result[listener] = atomic(sources) result[listener] = atomic(sources)
return { return {
'iptables': { 'firewall': {
'port_rules': result, 'port_rules': result,
}, },
} }

View file

@ -19,11 +19,11 @@ defaults = {
@metadata_reactor.provides( @metadata_reactor.provides(
'iptables/port_rules/19999', 'firewall/port_rules/19999',
) )
def iptables(metadata): def firewall(metadata):
return { return {
'iptables': { 'firewall': {
'port_rules': { 'port_rules': {
'19999': atomic(metadata.get('netdata/restrict-to', set())), '19999': atomic(metadata.get('netdata/restrict-to', set())),
}, },

View file

@ -10,9 +10,9 @@ defaults = {
@metadata_reactor.provides( @metadata_reactor.provides(
'iptables/port_rules', 'firewall/port_rules',
) )
def iptables(metadata): def firewall(metadata):
ips = set() ips = set()
for share_items in metadata.get('nfs-server/shares', {}).values(): for share_items in metadata.get('nfs-server/shares', {}).values():
@ -20,7 +20,7 @@ def iptables(metadata):
ips.add(share_target) ips.add(share_target)
return { return {
'iptables': { 'firewall': {
'port_rules': { 'port_rules': {
'111': atomic(ips), '111': atomic(ips),
'111/udp': atomic(ips), '111/udp': atomic(ips),

View file

@ -169,12 +169,12 @@ def monitoring(metadata):
@metadata_reactor.provides( @metadata_reactor.provides(
'iptables/port_rules/80', 'firewall/port_rules/80',
'iptables/port_rules/443', 'firewall/port_rules/443',
) )
def iptables(metadata): def firewall(metadata):
return { return {
'iptables': { 'firewall': {
'port_rules': { 'port_rules': {
'80': atomic(metadata.get('nginx/restrict-to', {'*'})), '80': atomic(metadata.get('nginx/restrict-to', {'*'})),
'443': atomic(metadata.get('nginx/restrict-to', {'*'})), '443': atomic(metadata.get('nginx/restrict-to', {'*'})),

View file

@ -10,11 +10,11 @@ defaults = {
@metadata_reactor.provides( @metadata_reactor.provides(
'iptables/port_rules/113', 'firewall/port_rules/113',
) )
def iptables(metadata): def firewall(metadata):
return { return {
'iptables': { 'firewall': {
'port_rules': { 'port_rules': {
'113': atomic(metadata.get('oidentd/restrict-to', {'*'})), '113': atomic(metadata.get('oidentd/restrict-to', {'*'})),
}, },

View file

@ -16,11 +16,11 @@ defaults = {
} }
@metadata_reactor.provides( @metadata_reactor.provides(
'iptables/port_rules/22', 'firewall/port_rules/22',
) )
def iptables(metadata): def firewall(metadata):
return { return {
'iptables': { 'firewall': {
'port_rules': { 'port_rules': {
'22': atomic(metadata.get('openssh/restrict-to', {'*'})), '22': atomic(metadata.get('openssh/restrict-to', {'*'})),
}, },

View file

@ -18,7 +18,7 @@ alias_maps = hash:/etc/aliases
relayhost = ${node.metadata['postfix']['relayhost']} relayhost = ${node.metadata['postfix']['relayhost']}
% endif % endif
% if node.has_bundle('postfixadmin') or node.has_bundle('iptables'): % if node.has_bundle('postfixadmin') or node.has_bundle('nftables'):
inet_interfaces = all inet_interfaces = all
% else: % else:
inet_interfaces = 127.0.0.1 inet_interfaces = 127.0.0.1

View file

@ -100,11 +100,11 @@ def letsencrypt(metadata):
@metadata_reactor.provides( @metadata_reactor.provides(
'iptables/port_rules/25', 'firewall/port_rules/25',
'iptables/port_rules/587', 'firewall/port_rules/587',
'iptables/port_rules/2525', 'firewall/port_rules/2525',
) )
def iptables(metadata): def firewall(metadata):
if node.has_bundle('postfixadmin'): if node.has_bundle('postfixadmin'):
default = {'*'} default = {'*'}
else: else:
@ -119,7 +119,7 @@ def iptables(metadata):
rules['2525'] = atomic(metadata.get('postfix/restrict-to', default)) rules['2525'] = atomic(metadata.get('postfix/restrict-to', default))
return { return {
'iptables': { 'firewall': {
'port_rules': rules, 'port_rules': rules,
}, },
} }

View file

@ -182,11 +182,11 @@ def hosts_entries_for_all_dns_servers(metadata):
@metadata_reactor.provides( @metadata_reactor.provides(
'iptables/port_rules', 'firewall/port_rules',
) )
def iptables(metadata): def firewall(metadata):
return { return {
'iptables': { 'firewall': {
'port_rules': { 'port_rules': {
'53': atomic(metadata.get('powerdns/restrict-to', {'*'})), '53': atomic(metadata.get('powerdns/restrict-to', {'*'})),
'53/udp': atomic(metadata.get('powerdns/restrict-to', {'*'})), '53/udp': atomic(metadata.get('powerdns/restrict-to', {'*'})),

View file

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
rm /etc/iptables-rules.d/90-pppd rm /etc/nftables-rules.d/90-pppd
rm /etc/sysctl.d/90-pppd.conf rm /etc/sysctl.d/90-pppd.conf
/usr/local/sbin/iptables-enforce systemctl reload nftables

View file

@ -2,9 +2,9 @@
INTERFACE=$1 INTERFACE=$1
echo "iptables -t nat -A POSTROUTING -o $INTERFACE -j MASQUERADE" > /etc/iptables-rules.d/90-pppd echo "add rule nat postrouting oif $INTERFACE masquerade" > /etc/nftables-rules.d/90-pppd
echo "net.ipv6.conf.$INTERFACE.accept_ra=2" > /etc/sysctl.d/90-pppd.conf echo "net.ipv6.conf.$INTERFACE.accept_ra=2" > /etc/sysctl.d/90-pppd.conf
/usr/local/sbin/iptables-enforce systemctl reload nftables
rdisc6 $INTERFACE rdisc6 $INTERFACE

View file

@ -32,7 +32,7 @@ directories = {
} }
files = { files = {
'/etc/iptables-rules.d/90-pppd': { '/etc/nftables-rules.d/90-pppd': {
'content_type': 'any', 'content_type': 'any',
}, },
'/etc/ppp/chap-secrets': { '/etc/ppp/chap-secrets': {
@ -53,11 +53,11 @@ files = {
'svc_systemd:pppoe:restart', 'svc_systemd:pppoe:restart',
}, },
}, },
'/etc/ppp/ip-down.d/iptables': { '/etc/ppp/ip-down.d/nftables': {
'source': 'ip-down', 'source': 'ip-down',
'mode': '0755', 'mode': '0755',
}, },
'/etc/ppp/ip-up.d/iptables': { '/etc/ppp/ip-up.d/nftables': {
'source': 'ip-up', 'source': 'ip-up',
'mode': '0755', 'mode': '0755',
}, },

View file

@ -50,11 +50,11 @@ if node.has_bundle('telegraf'):
@metadata_reactor.provides( @metadata_reactor.provides(
'iptables/port_rules', 'firewall/port_rules',
) )
def iptables(metadata): def firewall(metadata):
return { return {
'iptables': { 'firewall': {
'port_rules': { 'port_rules': {
str(metadata.get('transmission/config/peer-port')): atomic({'*'}), str(metadata.get('transmission/config/peer-port')): atomic({'*'}),
str(metadata.get('transmission/config/peer-port')) + '/udp': atomic({'*'}), str(metadata.get('transmission/config/peer-port')) + '/udp': atomic({'*'}),

View file

@ -10,8 +10,8 @@ server:
num-threads: ${threads} num-threads: ${threads}
% if node.has_bundle('iptables') and not node.has_bundle('vmhost'): % if node.has_bundle('nftables') and not node.has_bundle('vmhost'):
# Use iptables to manage access to this service # Use nftables to manage access to this service
interface: 0.0.0.0 interface: 0.0.0.0
interface: ::0 interface: ::0
access-control: 0.0.0.0/0 allow access-control: 0.0.0.0/0 allow

View file

@ -56,11 +56,11 @@ def cpu_cores_to_config_values(metadata):
@metadata_reactor.provides( @metadata_reactor.provides(
'iptables/port_rules', 'firewall/port_rules',
) )
def iptables(metadata): def firewall(metadata):
return { return {
'iptables': { 'firewall': {
'port_rules': { 'port_rules': {
'53': atomic(metadata.get('unbound/restrict-to', set())), '53': atomic(metadata.get('unbound/restrict-to', set())),
'53/udp': atomic(metadata.get('unbound/restrict-to', set())), '53/udp': atomic(metadata.get('unbound/restrict-to', set())),

View file

@ -3,3 +3,24 @@ files = {
'mode': '0755', 'mode': '0755',
}, },
} }
if node.has_bundle('nftables'):
# libvirt on debian depends on either iptables or firewalld. Since
# we're managing firewall rules using bundlewrap, we don't want either
# of thos to interfere. So we install firewalld, then ensure it is
# never running. After that, we ensure the bundlewrap managed rules
# are active.
svc_systemd['firewalld'] = {
'running': False,
'enabled': False,
'masked': True,
'needs': {
'pkg_apt:firewalld',
},
'needed_by': {
'svc_systemd:nftables',
},
'triggers': {
'svc_systemd:nftables:reload',
},
}

View file

@ -28,3 +28,10 @@ if node.os == 'debian' and node.os_version[0] < 11:
if node.has_bundle('zfs'): if node.has_bundle('zfs'):
defaults['apt']['packages']['libvirt-daemon-driver-storage-zfs'] = {} defaults['apt']['packages']['libvirt-daemon-driver-storage-zfs'] = {}
if node.has_bundle('nftables'):
defaults['apt']['packages']['firewalld'] = {
'needed_by': {
'pkg_apt:libvirt-daemon-system',
},
}

View file

@ -16,11 +16,11 @@ defaults = {
@metadata_reactor.provides( @metadata_reactor.provides(
'iptables/port_rules', 'firewall/port_rules',
) )
def iptables(metadata): def firewall(metadata):
return { return {
'iptables': { 'firewall': {
'port_rules': { 'port_rules': {
str(metadata.get('webfs/port')): atomic(metadata.get('webfs/restrict-to', {'*'})), str(metadata.get('webfs/port')): atomic(metadata.get('webfs/restrict-to', {'*'})),
}, },

View file

@ -4,14 +4,16 @@ defaults = {
'wide-dhcpv6-client': {}, 'wide-dhcpv6-client': {},
}, },
}, },
'iptables': { 'nftables': {
'bundle_rules': { 'rules': {
'input': {
'wide-dhcp6c': [ 'wide-dhcp6c': [
'ip6tables -A INPUT -p udp -s ff00::/12 -j ACCEPT', 'udp dport { 546, 547 } ip6 saddr ff00::/12 accept',
'ip6tables -A INPUT -p udp -s fe80::/10 -j ACCEPT', 'udp dport { 546, 547 } ip6 saddr fe80::/10 accept',
], ],
}, },
}, },
},
'icinga2_api': { 'icinga2_api': {
'wide-dhcp6c': { 'wide-dhcp6c': {
'services': { 'services': {

View file

@ -18,14 +18,16 @@ defaults = {
}, },
}, },
}, },
'iptables': { 'nftables': {
'bundle_rules': { 'rules': {
'forward': {
'wireguard': [ 'wireguard': [
'iptables_both -A FORWARD -i wg0 -j ACCEPT', 'iif wg0 accept',
'iptables_both -A FORWARD -o wg0 -j ACCEPT', 'oif wg0 accept',
], ],
}, },
}, },
},
'wireguard': { 'wireguard': {
'privatekey': repo.libs.keys.gen_privkey(repo, f'{node.name} wireguard privatekey'), 'privatekey': repo.libs.keys.gen_privkey(repo, f'{node.name} wireguard privatekey'),
}, },
@ -149,9 +151,9 @@ def icinga2(metadata):
@metadata_reactor.provides( @metadata_reactor.provides(
'iptables/port_rules', 'firewall/port_rules',
) )
def iptables(metadata): def firewall(metadata):
sources = set(metadata.get('wireguard/restrict-to', set())) sources = set(metadata.get('wireguard/restrict-to', set()))
for peer_name in metadata.get('wireguard/peers'): for peer_name in metadata.get('wireguard/peers'):
try: try:
@ -162,7 +164,7 @@ def iptables(metadata):
sources.add(peer_name) sources.add(peer_name)
return { return {
'iptables': { 'firewall': {
'port_rules': { 'port_rules': {
'51820/udp': atomic(sources), '51820/udp': atomic(sources),
}, },

View file

@ -20,7 +20,7 @@ groups['linux'] = {
'bundles': { 'bundles': {
'basic', 'basic',
'cron', 'cron',
'iptables', 'nftables',
'openssh', 'openssh',
'postfix', 'postfix',
'sshmon', 'sshmon',
@ -39,7 +39,7 @@ groups['linux'] = {
'backup-client': { 'backup-client': {
'server': 'franzi-home.kunbox.net:2022', 'server': 'franzi-home.kunbox.net:2022',
}, },
'iptables': { 'firewall': {
'port_rules': { 'port_rules': {
'*': { '*': {
'ovh.icinga2', 'ovh.icinga2',

View file

@ -55,7 +55,7 @@ nodes['home.nas'] = {
'groups': { 'groups': {
'nas': {}, 'nas': {},
}, },
'iptables': { 'firewall': {
'port_rules': { 'port_rules': {
'4679': { # Dell ULNM '4679': { # Dell ULNM
'172.19.136.0/25', '172.19.136.0/25',

View file

@ -94,25 +94,28 @@ nodes['home.router'] = {
'vars.notification.sms': True 'vars.notification.sms': True
}, },
'iptables': { 'nftables': {
'custom_rules': [ 'rules': {
'forward': {
'router': [
# This is a router. Allow forwarding traffic for internal networks. # This is a router. Allow forwarding traffic for internal networks.
'iptables_both -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT', 'ct state { related, established } accept',
'iptables_both -A FORWARD -i enp1s0.23 -o ppp0 -j ACCEPT', 'iif enp1s0.23 oif ppp0 accept',
'iptables_both -A FORWARD -i enp1s0.42 -j ACCEPT', 'iif enp1s0.42 accept',
# External port 2022 should be home.nas
'iptables -t nat -A PREROUTING -p tcp --dport 2022 -j DNAT --to 172.19.138.20:22',
'iptables -A FORWARD -p tcp -d 172.19.138.20 --dport 22 -j ACCEPT',
# use MASQUERADE for tun0 (c3voc)
'iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE',
# yaaaaay, IPv6! No NAT! # yaaaaay, IPv6! No NAT!
'ip6tables -A FORWARD -p ipv6-icmp -j ACCEPT', 'ip6 nexthdr ipv6-icmp accept',
'ip6tables -A FORWARD -p tcp --dport 22 -j ACCEPT', 'tcp dport 22 accept',
], ],
}, },
'nat_prerouting': [
'tcp dport 2022 dnat 172.19.138.20:22',
],
'nat_postrouting': [
'oif tun0 masquerade',
],
},
},
'netdata': { 'netdata': {
'restrict-to': { 'restrict-to': {
'172.19.136.0/25', '172.19.136.0/25',

View file

@ -83,13 +83,6 @@ nodes['htz-cloud.miniserver'] = {
'icinga_options': { 'icinga_options': {
'vars.notification.sms': False, 'vars.notification.sms': False,
}, },
'iptables': {
'custom_rules': [
'iptables_both -A INPUT -p udp --dport 60000:61000 -j ACCEPT', # mosh
'iptables_both -A INPUT -p tcp --dport 9001 -j ACCEPT', # weechat
],
},
'letsencrypt': { 'letsencrypt': {
'concat_and_deploy': { 'concat_and_deploy': {
'sophie-weechat': { 'sophie-weechat': {
@ -151,6 +144,16 @@ nodes['htz-cloud.miniserver'] = {
'bot_token': '""', 'bot_token': '""',
}, },
}, },
'nftables': {
'rules': {
'input': {
'sophie-weechat': [
'udp dport { 60000-61000 } accept',
'tcp dport 9001 accept',
],
},
},
},
'nginx': { 'nginx': {
'vhosts': { 'vhosts': {
#'dimension.sophies-kitchen.eu': { #'dimension.sophies-kitchen.eu': {

View file

@ -137,24 +137,6 @@ nodes['htz.ex42-1048908'] = {
'icinga_options': { 'icinga_options': {
'pretty_name': 'kunsmann.eu', 'pretty_name': 'kunsmann.eu',
}, },
'iptables': {
# TODO move to bundles
'custom_rules': [
'iptables_both -A INPUT -p udp --dport 60000:61000 -j ACCEPT', # mosh
'iptables_both -A INPUT -p tcp --dport 9001 -j ACCEPT', # weechat
# libvirt rules. These are also added by libvirt itself,
# but they would be overridden by our own iptables
# management.
'iptables -A INPUT -i virbr0 -p udp --dport 53 -j ACCEPT',
'iptables -A INPUT -i virbr0 -p tcp --dport 53 -j ACCEPT',
'iptables -A INPUT -i virbr0 -p udp --dport 67:68 -j ACCEPT',
'iptables -A INPUT -i virbr0 -p tcp --dport 67:68 -j ACCEPT',
'iptables -A FORWARD -i virbr0 -j ACCEPT',
'iptables -A FORWARD -o virbr0 -j ACCEPT',
'iptables -t nat -A POSTROUTING -o enp0s31f6 -j MASQUERADE',
],
},
'letsencrypt': { 'letsencrypt': {
'concat_and_deploy': { 'concat_and_deploy': {
'kunsi-weechat': { 'kunsi-weechat': {
@ -247,6 +229,30 @@ nodes['htz.ex42-1048908'] = {
'@.*:franzi\\\\.business', '@.*:franzi\\\\.business',
}, },
}, },
'nftables': {
'rules': {
'input': {
'kunsi-weechat': [
'udp dport { 60000-61000 } accept',
'tcp dport 9001 accept',
],
'libvirt': [
'tcp dport 53 iif virbr0 accept',
'udp dport 53 iif virbr0 accept',
'udp dport { 67, 68 } iif virbr0 accept',
],
},
'forward': {
'libvirt': [
'iif virbr0 accept',
'oif virbr0 accept',
],
},
'nat_postrouting': {
'oif enp0s31f6 masquerade',
},
},
},
'nginx': { 'nginx': {
'vhosts': { 'vhosts': {
# TODO maybe some of this can be moved to a bundle? # TODO maybe some of this can be moved to a bundle?

View file

@ -31,7 +31,7 @@ nodes['kunsi-t470'] = {
}, },
# there is also wlp4s0, but that's managed by netctl # there is also wlp4s0, but that's managed by netctl
}, },
'iptables': { 'firewall': {
'port_rules': { 'port_rules': {
# For the occasional file-share using `python -m http.server` # For the occasional file-share using `python -m http.server`
'8000': {'*'}, '8000': {'*'},