diff --git a/bundles/dhcpd/metadata.py b/bundles/dhcpd/metadata.py index bdf47b7..cc091af 100644 --- a/bundles/dhcpd/metadata.py +++ b/bundles/dhcpd/metadata.py @@ -37,20 +37,18 @@ def get_static_allocations(metadata): @metadata_reactor.provides( - 'nftables/rules/input/dhcpd', + 'nftables/rules/10-dhcpd', ) def nftables(metadata): rules = set() for iface in node.metadata.get('dhcpd/subnets', {}): - rules.add(f'udp dport {{ 67, 68 }} iif {iface} accept') + rules.add(f'inet filter input udp dport {{ 67, 68 }} iif {iface} accept') return { 'nftables': { 'rules': { - 'input': { - # can't use port_rules here, because we're generating interface based rules. - 'dhcpd': sorted(rules), - }, + # can't use port_rules here, because we're generating interface based rules. + '10-dhcpd': sorted(rules), }, } } diff --git a/bundles/nftables/files/nftables.conf b/bundles/nftables/files/nftables.conf index c4ad541..4034ad4 100644 --- a/bundles/nftables/files/nftables.conf +++ b/bundles/nftables/files/nftables.conf @@ -19,14 +19,6 @@ table inet filter { ip protocol icmp accept ip6 nexthdr ipv6-icmp accept -% for ruleset, rules in sorted(node.metadata.get('nftables/rules/input', {}).items()): - - # ${ruleset} -% for rule in rules: - ${rule} -% endfor - # / ${ruleset} -% endfor } chain output { @@ -40,32 +32,15 @@ table inet filter { icmp type timestamp-request drop icmp type timestamp-reply drop - -% for ruleset, rules in sorted(node.metadata.get('nftables/rules/forward', {}).items()): - - # ${ruleset} -% for rule in rules: - ${rule} -% endfor - # / ${ruleset} -% endfor } } table nat { chain prerouting { type nat hook prerouting priority -100 - -% for rule in sorted(node.metadata.get('nftables/rules/nat_prerouting', [])): - ${rule} -% endfor } chain postrouting { type nat hook postrouting priority 100 - -% for rule in sorted(node.metadata.get('nftables/rules/nat_postrouting', [])): - ${rule} -% endfor } } diff --git a/bundles/nftables/files/rules-template b/bundles/nftables/files/rules-template new file mode 100644 index 0000000..7680393 --- /dev/null +++ b/bundles/nftables/files/rules-template @@ -0,0 +1,3 @@ +% for rule in rules: +add rule ${rule} +% endfor diff --git a/bundles/nftables/items.py b/bundles/nftables/items.py index ff28e31..8975d45 100644 --- a/bundles/nftables/items.py +++ b/bundles/nftables/items.py @@ -15,7 +15,6 @@ directories = { files = { '/etc/nftables.conf': { - 'content_type': 'mako', 'needs': { 'directory:/etc/nftables-rules.d', }, @@ -30,9 +29,23 @@ files = { 'svc_systemd:nftables:reload', }, }, - } +for ruleset, rules in node.metadata.get('nftables/rules', {}).items(): + files[f'/etc/nftables-rules.d/{ruleset}'] = { + 'source': 'rules-template', + 'content_type': 'mako', + 'context': { + 'rules': rules, + }, + 'needed_by': { + 'svc_systemd:nftables', + }, + 'triggers': { + 'svc_systemd:nftables:reload', + }, + } + svc_systemd = { 'nftables': { 'needs': { diff --git a/bundles/nftables/metadata.py b/bundles/nftables/metadata.py index 721c1e7..08396ce 100644 --- a/bundles/nftables/metadata.py +++ b/bundles/nftables/metadata.py @@ -9,12 +9,13 @@ defaults = { 'pacman': { 'packages': { 'nftables': {}, - 'iptables': { - 'installed': False, - 'needed_by': { - 'pkg_pacman:iptables-nft', - }, - }, +# https://github.com/bundlewrap/bundlewrap/issues/688 +# 'iptables': { +# 'installed': False, +# 'needed_by': { +# 'pkg_pacman:iptables-nft', +# }, +# }, 'iptables-nft': { 'needed_by': { 'pkg_pacman:nftables', @@ -34,7 +35,7 @@ if not node.has_bundle('vmhost'): } @metadata_reactor.provides( - 'nftables/rules/input/port_rules', + 'nftables/rules/99-port_rules', ) def port_rules_to_nftables(metadata): # Using this, bundles can simply set up port based rules. This @@ -63,36 +64,33 @@ def port_rules_to_nftables(metadata): if port != '*': if ':' in port: parts = port.split(':') - port_str = f'dport {{ {parts[0]}-{parts[1]} }} ' + port_str = f'{proto} dport {{ {parts[0]}-{parts[1]} }}' else: - port_str = f'dport {port} ' - prefix = '' + port_str = f'{proto} dport {port}' else: - port_str = '' - prefix = 'meta l4proto ' + port_str = f'meta l4proto {proto}' - if target == '*': - ruleset.add(f'{prefix}{proto} {port_str}accept {comment}') - elif target == 'ipv4': - ruleset.add(f'{prefix}{proto} {port_str}ip version 4 accept {comment}') - elif target == 'ipv6': - ruleset.add(f'{prefix}{proto} {port_str}ip6 version 6 accept {comment}') + if target in ('ipv4', 'ipv6'): + version_str = f'meta nfproto {target}' + else: + version_str = '' + + if target in ('*', 'ipv4', 'ipv6'): + ruleset.add(f'inet filter input {version_str} {port_str} accept {comment}') else: resolved = repo.libs.tools.resolve_identifier(repo, target) for address in resolved['ipv4']: - ruleset.add(f'{prefix}{proto} {port_str}ip saddr {address} accept {comment}') + ruleset.add(f'inet filter input meta nfproto ipv4 {port_str} ip saddr {address} accept {comment}') for address in resolved['ipv6']: - ruleset.add(f'{prefix}{proto} {port_str}ip6 saddr {address} accept {comment}') + ruleset.add(f'inet filter input meta nfproto ipv6 {port_str} ip6 saddr {address} accept {comment}') return { 'nftables': { 'rules': { # order does not matter here. - 'input': { - 'port_rules': sorted(ruleset), - }, + '99-port_rules': sorted(ruleset), }, }, } diff --git a/bundles/wide-dhcp6c/metadata.py b/bundles/wide-dhcp6c/metadata.py index f1a6957..7ac556b 100644 --- a/bundles/wide-dhcp6c/metadata.py +++ b/bundles/wide-dhcp6c/metadata.py @@ -6,12 +6,10 @@ defaults = { }, 'nftables': { 'rules': { - 'input': { - 'wide-dhcp6c': [ - 'udp dport { 546, 547 } ip6 saddr ff00::/12 accept', - 'udp dport { 546, 547 } ip6 saddr fe80::/10 accept', - ], - }, + '10-wide-dhcp6c': [ + 'inet filter input udp dport { 546, 547 } ip6 saddr ff00::/12 accept', + 'inet filter input udp dport { 546, 547 } ip6 saddr fe80::/10 accept', + ], }, }, 'icinga2_api': { diff --git a/bundles/wireguard/metadata.py b/bundles/wireguard/metadata.py index 7374d83..f81cde5 100644 --- a/bundles/wireguard/metadata.py +++ b/bundles/wireguard/metadata.py @@ -18,16 +18,6 @@ defaults = { }, }, }, - 'nftables': { - 'rules': { - 'forward': { - 'wireguard': [ - 'iif wg0 accept', - 'oif wg0 accept', - ], - }, - }, - }, 'wireguard': { 'privatekey': repo.libs.keys.gen_privkey(repo, f'{node.name} wireguard privatekey'), }, @@ -221,17 +211,20 @@ def interface_ips(metadata): @metadata_reactor.provides( - 'nftables/rules/nat_postrouting', + 'nftables/rules/10-wireguard', ) def snat(metadata): if not node.has_bundle('nftables'): raise DoNotRunAgain - rules = set() + rules = { + 'inet filter forward iif wg0 accept', + 'inet filter forward oif wg0 accept', + } for config in metadata.get('wireguard/peers', {}).values(): if 'snat_to' in config: - rules.add('ip saddr {} ip daddr != {} snat to {}'.format( + rules.add('nat postrouting ip saddr {} ip daddr != {} snat to {}'.format( config['my_ip'], config['their_ip'], config['snat_to'], @@ -240,7 +233,7 @@ def snat(metadata): return { 'nftables': { 'rules': { - 'nat_postrouting': rules, + '10-wireguard': sorted(rules), }, }, } diff --git a/nodes/home/router.py b/nodes/home/router.py index 22650f6..eca665f 100644 --- a/nodes/home/router.py +++ b/nodes/home/router.py @@ -102,21 +102,17 @@ nodes['home.router'] = { }, 'nftables': { 'rules': { - 'forward': { - 'router': [ - # This is a router. Allow forwarding traffic for internal networks. - 'ct state { related, established } accept', - 'iif enp1s0.23 oif ppp0 accept', - 'iif enp1s0.42 accept', + '50-router': [ + # This is a router. Allow forwarding traffic for internal networks. + 'inet filter forward ct state { related, established } accept', + 'inet filter forward iif enp1s0.23 oif ppp0 accept', + 'inet filter forward iif enp1s0.42 accept', - # yaaaaay, IPv6! No NAT! - 'ip6 nexthdr ipv6-icmp accept', - 'tcp dport 22 accept', - ], - }, - 'nat_prerouting': { - 'tcp dport 2022 dnat 172.19.138.20:22', - }, + # yaaaaay, IPv6! No NAT! + 'inet filter forward ip6 nexthdr ipv6-icmp accept', + 'inet filter forward tcp dport 22 accept', + 'nat prerouting tcp dport 2022 dnat 172.19.138.20:22', + ], }, }, 'nginx': { diff --git a/nodes/htz-cloud/influxdb.py b/nodes/htz-cloud/influxdb.py index f3eea5c..8dcb53f 100644 --- a/nodes/htz-cloud/influxdb.py +++ b/nodes/htz-cloud/influxdb.py @@ -51,6 +51,11 @@ nodes['htz-cloud.influxdb'] = { }, }, }, + #'openssh': { + # 'restrict-to': { + # 'versatel', + # }, + #}, 'vm': { 'cpu': 1, 'ram': 2, diff --git a/nodes/htz-cloud/miniserver.py b/nodes/htz-cloud/miniserver.py index 3b23a17..931758b 100644 --- a/nodes/htz-cloud/miniserver.py +++ b/nodes/htz-cloud/miniserver.py @@ -181,12 +181,10 @@ nodes['htz-cloud.miniserver'] = { }, 'nftables': { 'rules': { - 'input': { - 'sophie-weechat': [ - 'udp dport { 60000-61000 } accept', - 'tcp dport 9001 accept', - ], - }, + '50-sophie-weechat': [ + 'inet filter input udp dport { 60000-61000 } accept', + 'inet filter input tcp dport 9001 accept', + ], }, }, 'nginx': { diff --git a/nodes/rx300.py b/nodes/rx300.py index a305e9d..4a4224d 100644 --- a/nodes/rx300.py +++ b/nodes/rx300.py @@ -275,12 +275,10 @@ nodes['rx300'] = { }, 'nftables': { 'rules': { - 'input': { - 'kunsi-weechat': [ - 'udp dport { 60000-61000 } accept', - 'tcp dport 9001 accept', - ], - }, + '50-kunsi-weechat': [ + 'inet filter input udp dport { 60000-61000 } accept', + 'inet filter input tcp dport 9001 accept', + ], }, }, 'nginx': {