diff --git a/bundles/bird/metadata.py b/bundles/bird/metadata.py index c442a26..ea4c1e6 100644 --- a/bundles/bird/metadata.py +++ b/bundles/bird/metadata.py @@ -88,7 +88,7 @@ def firewall(metadata): return { 'firewall': { 'port_rules': { - '179': atomic(sources), + '179/tcp': atomic(sources), }, }, } diff --git a/bundles/dovecot/metadata.py b/bundles/dovecot/metadata.py index bd1427e..00ee5a4 100644 --- a/bundles/dovecot/metadata.py +++ b/bundles/dovecot/metadata.py @@ -76,19 +76,19 @@ def import_database_settings_from_postfixadmin(metadata): @metadata_reactor.provides( - 'firewall/port_rules/143', - 'firewall/port_rules/993', - 'firewall/port_rules/4190', + 'firewall/port_rules', + 'firewall/port_rules', + 'firewall/port_rules', ) def firewall(metadata): return { 'firewall': { 'port_rules': { # imap(s) - '143': atomic(metadata.get('dovecot/restrict-to', {'*'})), - '993': atomic(metadata.get('dovecot/restrict-to', {'*'})), + '143/tcp': atomic(metadata.get('dovecot/restrict-to', {'*'})), + '993/tcp': atomic(metadata.get('dovecot/restrict-to', {'*'})), # managesieve - '4190': atomic(metadata.get('dovecot/restrict-to', {'*'})), + '4190/tcp': atomic(metadata.get('dovecot/restrict-to', {'*'})), }, }, } diff --git a/bundles/kea-dhcp-server/metadata.py b/bundles/kea-dhcp-server/metadata.py index 7b69f3e..6a25c1f 100644 --- a/bundles/kea-dhcp-server/metadata.py +++ b/bundles/kea-dhcp-server/metadata.py @@ -66,16 +66,16 @@ def get_static_allocations(metadata): @metadata_reactor.provides( - 'nftables/rules/10-kea-dhcp-server', + 'nftables/input/10-kea-dhcp-server', ) def nftables(metadata): rules = set() for iface in node.metadata.get('kea-dhcp-server/subnets', {}): - rules.add(f'inet filter input udp dport {{ 67, 68 }} iif {iface} accept') + rules.add(f'udp dport {{ 67, 68 }} iifname {iface} accept') return { 'nftables': { - 'rules': { + 'input': { # can't use port_rules here, because we're generating interface based rules. '10-kea-dhcp-server': sorted(rules), }, diff --git a/bundles/kodi/metadata.py b/bundles/kodi/metadata.py index e217b21..0fe2061 100644 --- a/bundles/kodi/metadata.py +++ b/bundles/kodi/metadata.py @@ -43,15 +43,15 @@ defaults = { @metadata_reactor.provides( - 'firewall/port_rules/8080', - 'firewall/port_rules/9090', + 'firewall/port_rules', + 'firewall/port_rules', ) def firewall(metadata): return { 'firewall': { 'port_rules': { - '8080': atomic(metadata.get('kodi/restrict-to', {'*'})), - '9090': atomic(metadata.get('kodi/restrict-to', {'*'})), + '8080/tcp': atomic(metadata.get('kodi/restrict-to', {'*'})), + '9090/tcp': atomic(metadata.get('kodi/restrict-to', {'*'})), }, }, } diff --git a/bundles/minecraft/metadata.py b/bundles/minecraft/metadata.py index 4c7626b..4bd5223 100644 --- a/bundles/minecraft/metadata.py +++ b/bundles/minecraft/metadata.py @@ -150,13 +150,13 @@ def heap_to_java_opts(metadata): @metadata_reactor.provides( - 'firewall/port_rules/25565', + 'firewall/port_rules', ) def firewall(metadata): return { 'firewall': { 'port_rules': { - '25565': atomic(metadata.get('minecraft/restrict-to', set())), + '25565/tcp': atomic(metadata.get('minecraft/restrict-to', set())), }, }, } diff --git a/bundles/mosquitto/metadata.py b/bundles/mosquitto/metadata.py index c07a446..66199ac 100644 --- a/bundles/mosquitto/metadata.py +++ b/bundles/mosquitto/metadata.py @@ -33,7 +33,7 @@ def firewall(metadata): result = {} for listener in metadata.get('mosquitto/listeners').keys(): - result[listener] = atomic(sources) + result[f'{listener}/tcp'] = atomic(sources) return { 'firewall': { diff --git a/bundles/nfs-server/metadata.py b/bundles/nfs-server/metadata.py index 4b9e8d5..73dc68a 100644 --- a/bundles/nfs-server/metadata.py +++ b/bundles/nfs-server/metadata.py @@ -33,8 +33,8 @@ def firewall(metadata): ips.add(share_target) rules = {} - for port in ('111', '2049', '1110', '4045', '35295'): # TODO find out if we need more ports - for proto in ('', '/udp'): + for port in ('111', '2049', '1110', '4045', '35295'): + for proto in ('/tcp', '/udp'): rules[port + proto] = atomic(ips) return { diff --git a/bundles/nftables/files/nftables.conf b/bundles/nftables/files/nftables.conf index 4034ad4..83bf07f 100644 --- a/bundles/nftables/files/nftables.conf +++ b/bundles/nftables/files/nftables.conf @@ -19,6 +19,13 @@ table inet filter { ip protocol icmp accept ip6 nexthdr ipv6-icmp accept +% for ruleset, rules in sorted(input.items()): + + # ${ruleset} +% for rule in rules: + ${rule} +% endfor +% endfor } chain output { @@ -32,15 +39,36 @@ table inet filter { icmp type timestamp-request drop icmp type timestamp-reply drop +% for ruleset, rules in sorted(forward.items()): + + # ${ruleset} +% for rule in rules: + ${rule} +% endfor +% endfor } } table nat { chain prerouting { type nat hook prerouting priority -100 +% for ruleset, rules in sorted(prerouting.items()): + + # ${ruleset} +% for rule in rules: + ${rule} +% endfor +% endfor } chain postrouting { type nat hook postrouting priority 100 +% for ruleset, rules in sorted(postrouting.items()): + + # ${ruleset} +% for rule in rules: + ${rule} +% endfor +% endfor } } diff --git a/bundles/nftables/items.py b/bundles/nftables/items.py index 42bf2e4..96eebcf 100644 --- a/bundles/nftables/items.py +++ b/bundles/nftables/items.py @@ -15,8 +15,12 @@ directories = { files = { '/etc/nftables.conf': { - 'needs': { - 'directory:/etc/nftables-rules.d', + 'content_type': 'mako', + 'context': { + 'forward': node.metadata.get('nftables/forward', {}), + 'input': node.metadata.get('nftables/input', {}), + 'postrouting': node.metadata.get('nftables/postrouting', {}), + 'prerouting': node.metadata.get('nftables/prerouting', {}), }, 'triggers': { 'svc_systemd:nftables:reload', @@ -32,21 +36,6 @@ files = { }, } -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 acfb166..0d7819a 100644 --- a/bundles/nftables/metadata.py +++ b/bundles/nftables/metadata.py @@ -35,7 +35,7 @@ if not node.has_bundle('vmhost'): } @metadata_reactor.provides( - 'nftables/rules/99-port_rules', + 'nftables/input/99-port_rules', ) def port_rules_to_nftables(metadata): # Using this, bundles can simply set up port based rules. This @@ -49,46 +49,47 @@ def port_rules_to_nftables(metadata): if '/' in portdef: port, proto = portdef.split('/', 2) - if proto not in {'udp'}: + if proto not in ('tcp', 'udp'): raise BundleError(f'firewall/port_rules: illegal identifier {portdef} in metadata for {node.name}') else: port = portdef - proto = 'tcp' + proto = None for target in targets: - if port == '*' and target == '*': - raise BundleError('firewall/port_rules: setting both port and target to * is unsupported') + if ( + (port == '*' and target == '*') + or (target == '*' and proto is None) + or (port != '*' and proto is None) + ): + raise BundleError(f'firewall/port_rules: illegal combination of port, target and protocol: "{port}" "{target}" "{proto}"') comment = f'comment "port_rules {target}"' if port != '*': if ':' in port: parts = port.split(':') - port_str = f'{proto} dport {{ {parts[0]}-{parts[1]} }}' + port_str = f'{proto} dport {{ {parts[0]}-{parts[1]} }} ' else: - port_str = f'{proto} dport {port}' + port_str = f'{proto} dport {port} ' + elif proto is not None: + port_str = f'meta l4proto {proto} ' else: - port_str = f'meta l4proto {proto}' + port_str = '' - 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}') + if target == '*': + ruleset.add(f'{port_str}accept {comment}') else: resolved = repo.libs.tools.resolve_identifier(repo, target, linklocal=True) for address in resolved['ipv4']: - ruleset.add(f'inet filter input meta nfproto ipv4 {port_str} ip saddr {address} accept {comment}') + ruleset.add(f'{port_str}ip saddr {address} accept {comment}') for address in resolved['ipv6']: - ruleset.add(f'inet filter input meta nfproto ipv6 {port_str} ip6 saddr {address} accept {comment}') + ruleset.add(f'{port_str}ip6 saddr {address} accept {comment}') return { 'nftables': { - 'rules': { + 'input': { # order does not matter here. '99-port_rules': sorted(ruleset), }, diff --git a/bundles/nginx/metadata.py b/bundles/nginx/metadata.py index 1d386dd..e47e84d 100644 --- a/bundles/nginx/metadata.py +++ b/bundles/nginx/metadata.py @@ -172,15 +172,15 @@ def monitoring(metadata): @metadata_reactor.provides( - 'firewall/port_rules/80', - 'firewall/port_rules/443', + 'firewall/port_rules', + 'firewall/port_rules', ) def firewall(metadata): return { 'firewall': { 'port_rules': { - '80': atomic(metadata.get('nginx/restrict-to', {'*'})), - '443': atomic(metadata.get('nginx/restrict-to', {'*'})), + '80/tcp': atomic(metadata.get('nginx/restrict-to', {'*'})), + '443/tcp': atomic(metadata.get('nginx/restrict-to', {'*'})), }, }, } diff --git a/bundles/oidentd/metadata.py b/bundles/oidentd/metadata.py index f9d4390..dbc27a1 100644 --- a/bundles/oidentd/metadata.py +++ b/bundles/oidentd/metadata.py @@ -10,13 +10,13 @@ defaults = { @metadata_reactor.provides( - 'firewall/port_rules/113', + 'firewall/port_rules', ) def firewall(metadata): return { 'firewall': { 'port_rules': { - '113': atomic(metadata.get('oidentd/restrict-to', {'*'})), + '113/tcp': atomic(metadata.get('oidentd/restrict-to', {'*'})), }, }, } diff --git a/bundles/openssh/metadata.py b/bundles/openssh/metadata.py index 3cad1b9..630b851 100644 --- a/bundles/openssh/metadata.py +++ b/bundles/openssh/metadata.py @@ -16,13 +16,13 @@ defaults = { } @metadata_reactor.provides( - 'firewall/port_rules/22', + 'firewall/port_rules', ) def firewall(metadata): return { 'firewall': { 'port_rules': { - '22': atomic(metadata.get('openssh/restrict-to', {'*'})), + '22/tcp': atomic(metadata.get('openssh/restrict-to', {'*'})), }, }, } diff --git a/bundles/postfix/metadata.py b/bundles/postfix/metadata.py index e0dbe61..4788de6 100644 --- a/bundles/postfix/metadata.py +++ b/bundles/postfix/metadata.py @@ -96,10 +96,10 @@ def letsencrypt(metadata): @metadata_reactor.provides( - 'firewall/port_rules/25', - 'firewall/port_rules/465', - 'firewall/port_rules/587', - 'firewall/port_rules/2525', + 'firewall/port_rules', + 'firewall/port_rules', + 'firewall/port_rules', + 'firewall/port_rules', ) def firewall(metadata): if node.has_bundle('postfixadmin'): @@ -108,13 +108,13 @@ def firewall(metadata): default = metadata.get('postfix/mynetworks', set()) rules = { - '25': atomic(metadata.get('postfix/restrict-to', default)), - '465': atomic(metadata.get('postfix/restrict-to', default)), + '25/tcp': atomic(metadata.get('postfix/restrict-to', default)), + '465/tcp': atomic(metadata.get('postfix/restrict-to', default)), } if node.has_bundle('postfixadmin'): - rules['587'] = atomic(metadata.get('postfix/restrict-to', default)) - rules['2525'] = atomic(metadata.get('postfix/restrict-to', default)) + rules['587/tcp'] = atomic(metadata.get('postfix/restrict-to', default)) + rules['2525/tcp'] = atomic(metadata.get('postfix/restrict-to', default)) return { 'firewall': { diff --git a/bundles/powerdns/metadata.py b/bundles/powerdns/metadata.py index b418636..801161d 100644 --- a/bundles/powerdns/metadata.py +++ b/bundles/powerdns/metadata.py @@ -201,9 +201,9 @@ def firewall(metadata): return { 'firewall': { 'port_rules': { - '53': atomic(metadata.get('powerdns/restrict-to/dns', {'*'})), + '53/tcp': atomic(metadata.get('powerdns/restrict-to/dns', {'*'})), '53/udp': atomic(metadata.get('powerdns/restrict-to/dns', {'*'})), - '8081': atomic(metadata.get('powerdns/restrict-to/api', set())), + '8081/tcp': atomic(metadata.get('powerdns/restrict-to/api', set())), }, }, } diff --git a/bundles/pppd/files/ip-up b/bundles/pppd/files/ip-up index 8eba2b9..2ac4934 100644 --- a/bundles/pppd/files/ip-up +++ b/bundles/pppd/files/ip-up @@ -2,7 +2,7 @@ INTERFACE=$1 -echo "add rule nat postrouting oif $INTERFACE masquerade" > /etc/nftables-rules.d/90-pppd +echo "add rule nat postrouting oifname $INTERFACE masquerade" > /etc/nftables-rules.d/90-pppd % for rule in sorted(nftables): echo "add rule ${rule}" >> /etc/nftables-rules.d/90-pppd % endfor diff --git a/bundles/rsyslogd/metadata.py b/bundles/rsyslogd/metadata.py index 3fe9624..aec2591 100644 --- a/bundles/rsyslogd/metadata.py +++ b/bundles/rsyslogd/metadata.py @@ -25,7 +25,7 @@ def firewall(metadata): return { 'firewall': { 'port_rules': { - '514': atomic(metadata.get('rsyslogd/restrict-to', set())), + '514/tcp': atomic(metadata.get('rsyslogd/restrict-to', set())), '514/udp': atomic(metadata.get('rsyslogd/restrict-to', set())), }, }, diff --git a/bundles/transmission/metadata.py b/bundles/transmission/metadata.py index 60643b4..da2a09e 100644 --- a/bundles/transmission/metadata.py +++ b/bundles/transmission/metadata.py @@ -55,9 +55,9 @@ def firewall(metadata): return { 'firewall': { 'port_rules': { - str(metadata.get('transmission/config/peer-port')): atomic({'*'}), - str(metadata.get('transmission/config/peer-port')) + '/udp': atomic({'*'}), - str(metadata.get('transmission/config/rpc-port')): atomic(metadata.get('transmission/restrict-to', {'*'})), + f"{metadata.get('transmission/config/peer-port')}/tcp": atomic({'*'}), + f"{metadata.get('transmission/config/peer-port')}/udp": atomic({'*'}), + f"{metadata.get('transmission/config/rpc-port')}/tcp": atomic(metadata.get('transmission/restrict-to', {'*'})), }, }, } diff --git a/bundles/unbound/metadata.py b/bundles/unbound/metadata.py index b08df0b..70a3511 100644 --- a/bundles/unbound/metadata.py +++ b/bundles/unbound/metadata.py @@ -70,7 +70,7 @@ def firewall(metadata): return { 'firewall': { 'port_rules': { - '53': atomic(metadata.get('unbound/restrict-to', set())), + '53/tcp': atomic(metadata.get('unbound/restrict-to', set())), '53/udp': atomic(metadata.get('unbound/restrict-to', set())), }, }, diff --git a/bundles/weechat/metadata.py b/bundles/weechat/metadata.py index 6efc467..034ecfb 100644 --- a/bundles/weechat/metadata.py +++ b/bundles/weechat/metadata.py @@ -20,9 +20,9 @@ defaults = { }, }, 'nftables': { - 'rules': { - 'weechat-mosh': { - 'inet filter input udp dport { 60000-61000 } accept', + 'input': { + '10-weechat': { + 'udp dport { 60000-61000 } accept', }, }, }, diff --git a/bundles/wide-dhcp6c/metadata.py b/bundles/wide-dhcp6c/metadata.py index 7ac556b..050e690 100644 --- a/bundles/wide-dhcp6c/metadata.py +++ b/bundles/wide-dhcp6c/metadata.py @@ -5,10 +5,10 @@ defaults = { }, }, 'nftables': { - 'rules': { + 'input': { '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', + 'udp dport { 546, 547 } ip6 saddr ff00::/12 accept', + 'udp dport { 546, 547 } ip6 saddr fe80::/10 accept', ], }, }, diff --git a/bundles/wireguard/metadata.py b/bundles/wireguard/metadata.py index 987fd35..c8951ee 100644 --- a/bundles/wireguard/metadata.py +++ b/bundles/wireguard/metadata.py @@ -264,7 +264,8 @@ def interface_ips(metadata): @metadata_reactor.provides( - 'nftables/rules/10-wireguard', + 'nftables/forward/10-wireguard', + 'nftables/postrouting/10-wireguard', ) def snat(metadata): if not node.has_bundle('nftables') or node.os == 'arch': @@ -272,13 +273,14 @@ def snat(metadata): snat_ip = metadata.get('wireguard/snat_ip', None) - rules = set() + forward = set() + postrouting = set() for peer, config in sorted(metadata.get('wireguard/peers', {}).items()): - rules.add(f'inet filter forward iifname wg_{config["iface"]} accept') - rules.add(f'inet filter forward oifname wg_{config["iface"]} accept') + forward.add(f'iifname wg_{config["iface"]} accept') + forward.add(f'oifname wg_{config["iface"]} accept') if snat_ip: - rules.add('nat postrouting ip saddr {} ip daddr != {} snat to {}'.format( + postrouting.add('ip saddr {} ip daddr != {} snat to {}'.format( config['my_ip'], config['their_ip'], snat_ip, @@ -286,8 +288,11 @@ def snat(metadata): return { 'nftables': { - 'rules': { - '10-wireguard': sorted(rules), + 'forward': { + '10-wireguard': sorted(forward), + }, + 'postrouting': { + '10-wireguard': sorted(postrouting), }, }, } diff --git a/groups/os.py b/groups/os.py index 13e954f..65f2691 100644 --- a/groups/os.py +++ b/groups/os.py @@ -41,9 +41,6 @@ groups['linux'] = { '*': { 'icinga2', }, - '*/udp': { - 'icinga2', - }, }, }, }, diff --git a/nodes/home/nas.py b/nodes/home/nas.py index 818d9b3..2b23903 100644 --- a/nodes/home/nas.py +++ b/nodes/home/nas.py @@ -67,15 +67,15 @@ nodes['home.nas'] = { }, 'firewall': { 'port_rules': { - '4679': { # Dell ULNM + '4679/tcp': { # Dell ULNM '172.19.136.0/25', '172.19.138.0/24', }, - '5060': { # yate SIP + '5060/tcp': { # yate SIP 'home.snom-wohnzimmer', 'home.mitel-rfp35', }, - '5061': { # yate SIPS + '5061/tcp': { # yate SIPS 'home.snom-wohnzimmer', 'home.mitel-rfp35', }, diff --git a/nodes/home/router.py b/nodes/home/router.py index e6f9125..6a0fe3b 100644 --- a/nodes/home/router.py +++ b/nodes/home/router.py @@ -77,15 +77,16 @@ nodes['home.router'] = { #'vars.notification.sms': True }, 'nftables': { - 'rules': { + 'forward': { '50-router': [ - # This is a router. Allow forwarding traffic for internal networks. - 'inet filter forward ct state { related, established } accept', - - # 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', + 'ct state { related, established } accept', + 'ip6 nexthdr ipv6-icmp accept', + 'tcp dport 22 accept', + ], + }, + 'prerouting': { + '50-router': [ + 'tcp dport 2022 dnat 172.19.138.20:22', ], }, }, diff --git a/nodes/htz-cloud/miniserver.py b/nodes/htz-cloud/miniserver.py index c89b23a..b93bb53 100644 --- a/nodes/htz-cloud/miniserver.py +++ b/nodes/htz-cloud/miniserver.py @@ -164,10 +164,10 @@ nodes['htz-cloud.miniserver'] = { '2a01:4f8:0:1::add:9898', }, 'nftables': { - 'rules': { + 'input': { '50-sophie-weechat': [ - 'inet filter input udp dport { 60000-61000 } accept', - 'inet filter input tcp dport 9001 accept', + 'udp dport { 60000-61000 } accept', + 'tcp dport 9001 accept', ], }, }, diff --git a/nodes/htz-cloud/wireguard.py b/nodes/htz-cloud/wireguard.py index 90b15ad..0e2c03d 100644 --- a/nodes/htz-cloud/wireguard.py +++ b/nodes/htz-cloud/wireguard.py @@ -38,14 +38,18 @@ nodes['htz-cloud.wireguard'] = { }, }, 'nftables': { - 'rules': { + 'input': { '50-router': [ - 'inet filter forward ct state { related, established } accept', - 'inet filter forward oif eth0 accept', - 'nat postrouting oif eth0 masquerade', + 'ct state { related, established } accept', + 'oifname eth0 accept', ], - 'wg_special': [ - 'inet filter input udp dport 51819 accept', + '50-wireguard': [ + 'udp dport 51819 accept', + ], + }, + 'postrouting': { + '50-router': [ + 'oifname eth0 masquerade', ], }, }, diff --git a/nodes/htz-hel/backup-sophie.py b/nodes/htz-hel/backup-sophie.py index d6efed3..e6003f1 100644 --- a/nodes/htz-hel/backup-sophie.py +++ b/nodes/htz-hel/backup-sophie.py @@ -41,10 +41,10 @@ nodes['htz-hel.backup-sophie'] = { 'zfs-base': 'tank/backups', }, 'nftables': { - 'rules': { + 'input': { '50-sophie-misc': [ - 'inet filter input udp dport { 60000-61000 } accept', - 'inet filter input tcp dport 5201 accept', + 'udp dport { 60000-61000 } accept', + 'tcp dport 5201 accept', ], }, }, diff --git a/nodes/kunsi-p14s.py b/nodes/kunsi-p14s.py index 7c41354..03d63a1 100644 --- a/nodes/kunsi-p14s.py +++ b/nodes/kunsi-p14s.py @@ -34,7 +34,7 @@ nodes['kunsi-p14s'] = { # '192.168.0.0/16', #}, # For the occasional file-share using `python -m http.server` - '8000': {'*'}, + '8000/tcp': {'*'}, }, }, 'interfaces': { @@ -68,7 +68,6 @@ nodes['kunsi-p14s'] = { 'openssh': { 'restrict-to': { 'rfc1918', - 'ipv6', }, }, 'openvpn-client': { diff --git a/nodes/kunsi-t470.py b/nodes/kunsi-t470.py index 61f21d4..c5b1ee7 100644 --- a/nodes/kunsi-t470.py +++ b/nodes/kunsi-t470.py @@ -36,13 +36,13 @@ nodes['kunsi-t470'] = { 'firewall': { 'port_rules': { # obs websocket thingie - just allow all RFC1918 ips here - '4444': { + '4444/tcp': { '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', }, # For the occasional file-share using `python -m http.server` - '8000': {'*'}, + '8000/tcp': {'*'}, }, }, 'locale': { @@ -73,7 +73,6 @@ nodes['kunsi-t470'] = { '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', - 'ipv6', }, }, 'pacman': {