]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
tests: shell: add sample ruleset reproducer
authorFlorian Westphal <fw@strlen.de>
Tue, 12 Sep 2023 09:41:00 +0000 (11:41 +0200)
committerFlorian Westphal <fw@strlen.de>
Mon, 18 Sep 2023 10:00:37 +0000 (12:00 +0200)
Changes on kernel side no longer permit transactions that reference
a chain after it is bound.

This test case breaks when run with nftables 1.0.6 and earlier.
Keep this as a test case in tree to catch any future problems in
this area.

Link: https://lore.kernel.org/netfilter-devel/20230911213750.5B4B663206F5@dd20004.kasserver.com/
Signed-off-by: Florian Westphal <fw@strlen.de>
tests/shell/testcases/nft-f/dumps/sample-ruleset.nft [new file with mode: 0644]
tests/shell/testcases/nft-f/sample-ruleset [new file with mode: 0755]

diff --git a/tests/shell/testcases/nft-f/dumps/sample-ruleset.nft b/tests/shell/testcases/nft-f/dumps/sample-ruleset.nft
new file mode 100644 (file)
index 0000000..480b694
--- /dev/null
@@ -0,0 +1,239 @@
+table inet filter {
+       map if_input {
+               type ifname : verdict
+               elements = { "eth0" : jump public_input,
+                            "eth1" : jump home_input,
+                            "eth2.10" : jump home_input,
+                            "eth2.20" : jump home_input }
+       }
+
+       map if_forward {
+               type ifname : verdict
+               elements = { "eth0" : jump public_forward,
+                            "eth1" : jump trusted_forward,
+                            "eth2.10" : jump voip_forward,
+                            "eth2.20" : jump guest_forward }
+       }
+
+       map if_output {
+               type ifname : verdict
+               elements = { "eth0" : jump public_output,
+                            "eth1" : jump home_output,
+                            "eth2.10" : jump home_output,
+                            "eth2.20" : jump home_output }
+       }
+
+       set ipv4_blacklist {
+               type ipv4_addr
+               flags interval
+               auto-merge
+       }
+
+       set ipv6_blacklist {
+               type ipv6_addr
+               flags interval
+               auto-merge
+       }
+
+       set limit_src_ip {
+               type ipv4_addr
+               size 1024
+               flags dynamic,timeout
+       }
+
+       set limit_src_ip6 {
+               type ipv6_addr
+               size 1024
+               flags dynamic,timeout
+       }
+
+       chain PREROUTING_RAW {
+               type filter hook prerouting priority raw; policy accept;
+               meta l4proto != { icmp, tcp, udp, ipv6-icmp } counter packets 0 bytes 0 drop
+               tcp flags syn jump {
+                       tcp option maxseg size 1-500 counter packets 0 bytes 0 drop
+                       tcp sport 0 counter packets 0 bytes 0 drop
+               }
+               rt type 0 counter packets 0 bytes 0 drop
+       }
+
+       chain PREROUTING_MANGLE {
+               type filter hook prerouting priority mangle; policy accept;
+               ct state vmap { invalid : jump ct_invalid_pre, related : jump rpfilter, new : jump ct_new_pre, untracked : jump ct_untracked_pre }
+       }
+
+       chain ct_invalid_pre {
+               counter packets 0 bytes 0 drop
+       }
+
+       chain ct_untracked_pre {
+               icmpv6 type { mld-listener-query, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, mld2-listener-report } return
+               counter packets 0 bytes 0 drop
+       }
+
+       chain ct_new_pre {
+               jump rpfilter
+               tcp flags != syn / fin,syn,rst,ack counter packets 0 bytes 0 drop
+               iifname "eth0" meta nfproto vmap { ipv4 : jump blacklist_input_ipv4, ipv6 : jump blacklist_input_ipv6 }
+       }
+
+       chain rpfilter {
+               ip saddr 0.0.0.0 ip daddr 255.255.255.255 udp sport 68 udp dport 67 return
+               ip6 saddr :: ip6 daddr . icmpv6 type { ff02::1:ff00:0/104 . nd-neighbor-solicit, ff02::16 . mld2-listener-report } return
+               fib saddr . iif oif 0 counter packets 0 bytes 0 drop
+       }
+
+       chain blacklist_input_ipv4 {
+               ip saddr { 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/3 } counter packets 0 bytes 0 drop
+               ip saddr @ipv4_blacklist counter packets 0 bytes 0 drop
+       }
+
+       chain blacklist_input_ipv6 {
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 saddr fe80::/64 return
+               udp sport 547 ip6 saddr fe80::/64 return
+               ip6 saddr { ::/3, 2001::/32, 2001:2::/48, 2001:3::/32, 2001:10::-2001:2f:ffff:ffff:ffff:ffff:ffff:ffff, 2001:db8::/32, 2002::/16, 3000::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff } counter packets 0 bytes 0 drop
+               ip6 saddr @ipv6_blacklist counter packets 0 bytes 0 drop
+       }
+
+       chain INPUT {
+               type filter hook input priority filter; policy drop;
+               iif "lo" accept
+               ct state established,related accept
+               iifname vmap @if_input
+               log prefix "NFT REJECT IN " flags ip options flags ether limit rate 5/second burst 10 packets reject
+       }
+
+       chain public_input {
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 saddr fe80::/64 ip6 hoplimit 255 accept
+               udp sport 547 udp dport 546 ip6 saddr fe80::/64 accept
+               fib daddr type { broadcast, anycast, multicast } counter packets 0 bytes 0 drop
+               counter packets 0 bytes 0 drop
+       }
+
+       chain home_input {
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept
+               icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept
+               udp sport 68 udp dport 67 accept
+               udp sport 546 udp dport 547 iifname { "eth1", "eth2.10", "eth2.20" } accept
+               fib daddr type { broadcast, anycast, multicast } counter packets 0 bytes 0 drop
+               icmp type echo-request accept
+               icmpv6 type echo-request accept
+               tcp dport 22 iifname "eth1" accept
+               meta l4proto { tcp, udp } th dport 53 jump {
+                       ip6 saddr != { fd00::/8, fe80::/64 } counter packets 0 bytes 0 reject with icmpv6 port-unreachable
+                       accept
+               }
+               udp dport 123 accept
+               tcp dport 8443 accept
+       }
+
+       chain FORWARD_MANGLE {
+               type filter hook forward priority mangle; policy accept;
+               oifname "eth0" jump {
+                       ct state new meta nfproto vmap { ipv4 : jump blacklist_output_ipv4, ipv6 : jump blacklist_output_ipv6 }
+                       tcp flags syn / syn,rst tcp option maxseg size set rt mtu
+               }
+       }
+
+       chain blacklist_output_ipv4 {
+               ip daddr { 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/3 } goto log_blacklist
+               ip daddr @ipv4_blacklist goto log_blacklist
+       }
+
+       chain blacklist_output_ipv6 {
+               icmpv6 type . ip6 daddr { nd-router-solicit . ff02::2, nd-neighbor-solicit . ff02::1:ff00:0/104, nd-neighbor-advert . fe80::/64, nd-neighbor-advert . ff02::1, nd-neighbor-advert . ff02::1:ff00:0/104, mld2-listener-report . ff02::16 } return
+               udp dport 547 ip6 daddr ff02::1:2 return
+               ip6 daddr { ::/3, 2001::/32, 2001:2::/48, 2001:3::/32, 2001:10::-2001:2f:ffff:ffff:ffff:ffff:ffff:ffff, 2001:db8::/32, 2002::/16, 3000::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff } goto log_blacklist
+               ip6 daddr @ipv6_blacklist goto log_blacklist
+       }
+
+       chain log_blacklist {
+               log prefix "NFT BLACKLIST " flags ip options flags ether limit rate 5/minute burst 10 packets drop
+               counter packets 0 bytes 0 drop
+       }
+
+       chain FORWARD {
+               type filter hook forward priority filter; policy drop;
+               ct state established,related accept
+               fib daddr type { broadcast, anycast, multicast } counter packets 0 bytes 0 drop
+               iifname vmap @if_forward
+               log prefix "NFT REJECT FWD " flags ip options flags ether limit rate 5/second burst 10 packets reject
+       }
+
+       chain public_forward {
+               udp dport { 5060, 7078-7097 } oifname "eth2.10" jump {
+                       ip6 saddr { 2001:db8::1-2001:db8::2 } accept
+                       meta nfproto ipv6 log prefix "NFT DROP SIP " flags ip options flags ether limit rate 5/second burst 10 packets drop
+               }
+               counter packets 0 bytes 0 drop
+       }
+
+       chain trusted_forward {
+               oifname "eth0" accept
+               icmp type echo-request accept
+               icmpv6 type echo-request accept
+               ip daddr { 192.168.3.30, 192.168.4.40 } tcp dport vmap { 22 : accept, 80 : drop, 443 : accept }
+               ip daddr 192.168.2.20 jump {
+                       tcp dport { 80, 443, 515, 631, 9100 } accept
+                       udp dport 161 accept
+               }
+       }
+
+       chain voip_forward {
+               icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } oifname "eth0" accept
+               ip6 daddr { 2001:db8::1-2001:db8::2 } jump {
+                       udp dport { 3478, 5060 } accept
+                       udp sport 7078-7097 accept
+                       tcp dport 5061 accept
+               }
+               tcp dport 587 ip daddr 10.0.0.1 accept
+               tcp dport 80 oifname "eth0" counter packets 0 bytes 0 reject
+       }
+
+       chain guest_forward {
+               oifname "eth0" accept
+       }
+
+       chain OUTPUT {
+               type filter hook output priority filter; policy drop;
+               oif "lo" accept
+               ct state vmap { invalid : jump ct_invalid_out, established : accept, related : accept, untracked : jump ct_untracked_out }
+               oifname vmap @if_output
+               log prefix "NFT REJECT OUT " flags ip options flags ether limit rate 5/second burst 10 packets reject
+       }
+
+       chain ct_invalid_out {
+               counter packets 0 bytes 0 drop
+       }
+
+       chain ct_untracked_out {
+               icmpv6 type { mld-listener-query, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, mld2-listener-report } return
+               counter packets 0 bytes 0 drop
+       }
+
+       chain public_output {
+               ct state new meta nfproto vmap { ipv4 : jump blacklist_output_ipv4, ipv6 : jump blacklist_output_ipv6 }
+               icmp type { destination-unreachable, echo-request, time-exceeded, parameter-problem } accept
+               icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } accept
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept
+               icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept
+               udp dport 547 ip6 saddr fe80::/64 ip6 daddr ff02::1:2 accept
+               udp dport { 53, 123 } accept
+               tcp dport { 443, 587, 853 } accept
+       }
+
+       chain home_output {
+               icmp type { destination-unreachable, echo-request, time-exceeded, parameter-problem } accept
+               icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } accept
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept
+               icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept
+               udp sport 547 udp dport 546 ip6 saddr fe80::/64 oifname { "eth1", "eth2.10", "eth2.20" } accept
+               udp sport 67 udp dport 68 ip saddr { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } accept
+               tcp dport 22 ip daddr 192.168.1.10 accept
+       }
+
+       chain POSTROUTING_SRCNAT {
+               type nat hook postrouting priority srcnat; policy accept;
+               ip saddr { 192.168.1.0-192.168.4.255 } oifname "eth0" masquerade
+       }
+}
diff --git a/tests/shell/testcases/nft-f/sample-ruleset b/tests/shell/testcases/nft-f/sample-ruleset
new file mode 100755 (executable)
index 0000000..8cee74b
--- /dev/null
@@ -0,0 +1,262 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_chain_binding)
+
+$NFT -f /dev/stdin <<"EOF"
+define public_if = eth0
+define trusted_if = eth1
+define voip_if = eth2.10
+define guest_if = eth2.20
+define home_if = { $trusted_if, $voip_if, $guest_if }
+define home_ipv6_if = { $trusted_if, $voip_if, $guest_if }
+
+define masq_ip = { 192.168.1.0/24, 192.168.2.0/24, 192.168.3.0/24, 192.168.4.0/24 }
+define masq_if = $public_if
+
+define host1_ip = 192.168.1.10
+define host2_ip = 192.168.2.20
+define host3_ip = 192.168.3.30
+define host4_ip = 192.168.4.40
+
+define proxy_port = 8443
+
+define private_ip = { 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }
+define private_ip6 = { fe80::/64, fd00::/8 }
+define bogons_ip = { 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/3 }
+define bogons_ip6 = { ::/3, 2001:0002::/48, 2001:0003::/32, 2001:10::/28, 2001:20::/28, 2001::/32, 2001:db8::/32, 2002::/16, 3000::/4, 4000::/2, 8000::/1 }
+
+define sip_whitelist_ip6 = { 2001:db8::1/128, 2001:db8::2/128 }
+define smtps_whitelist_ip = 10.0.0.1
+define protocol_whitelist = { tcp, udp, icmp, ipv6-icmp }
+
+table inet filter {
+       map if_input {
+               type ifname : verdict;
+               elements = { $public_if : jump public_input, $trusted_if : jump home_input, $voip_if : jump home_input, $guest_if : jump home_input }
+       }
+       map if_forward {
+               type ifname : verdict;
+               elements = { $public_if : jump public_forward, $trusted_if : jump trusted_forward, $voip_if : jump voip_forward, $guest_if : jump guest_forward }
+       }
+       map if_output {
+               type ifname : verdict;
+               elements = { $public_if : jump public_output, $trusted_if : jump home_output, $voip_if : jump home_output, $guest_if : jump home_output }
+       }
+
+       set ipv4_blacklist { type ipv4_addr; flags interval; auto-merge; }
+       set ipv6_blacklist { type ipv6_addr; flags interval; auto-merge; }
+       set limit_src_ip { type ipv4_addr; flags dynamic, timeout; size 1024; }
+       set limit_src_ip6 { type ipv6_addr; flags dynamic, timeout; size 1024; }
+
+       chain PREROUTING_RAW {
+               type filter hook prerouting priority raw;
+
+               meta l4proto != $protocol_whitelist counter drop
+               tcp flags syn jump {
+                       tcp option maxseg size 1-500 counter drop
+                       tcp sport 0 counter drop
+               }
+               rt type 0 counter drop
+       }
+
+       chain PREROUTING_MANGLE {
+               type filter hook prerouting priority mangle;
+
+               ct state vmap { invalid : jump ct_invalid_pre, untracked : jump ct_untracked_pre, new : jump ct_new_pre, related : jump rpfilter }
+       }
+       chain ct_invalid_pre {
+               counter drop
+       }
+       chain ct_untracked_pre {
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, mld-listener-query, mld2-listener-report } return
+               counter drop
+       }
+       chain ct_new_pre {
+               jump rpfilter
+
+               tcp flags & (fin|syn|rst|ack) != syn counter drop
+
+               iifname $public_if meta nfproto vmap { ipv4 : jump blacklist_input_ipv4, ipv6 : jump blacklist_input_ipv6 }
+       }
+       chain rpfilter {
+               ip saddr 0.0.0.0 ip daddr 255.255.255.255 udp sport bootpc udp dport bootps return
+               ip6 saddr ::/128 ip6 daddr . icmpv6 type { ff02::1:ff00:0/104 . nd-neighbor-solicit, ff02::16 . mld2-listener-report } return
+
+               fib saddr . iif oif eq 0 counter drop
+       }
+       chain blacklist_input_ipv4{
+               ip saddr $bogons_ip counter drop
+               ip saddr @ipv4_blacklist counter drop
+       }
+       chain blacklist_input_ipv6{
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 saddr fe80::/64 return
+               udp sport dhcpv6-server ip6 saddr fe80::/64 return
+
+               ip6 saddr $bogons_ip6 counter drop
+               ip6 saddr @ipv6_blacklist counter drop
+       }
+
+       chain INPUT {
+               type filter hook input priority filter; policy drop;
+
+               iif lo accept
+
+               ct state established,related accept
+
+               iifname vmap @if_input
+
+               log prefix "NFT REJECT IN " flags ether flags ip options limit rate 5/second burst 10 packets reject
+       }
+       chain public_input {
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 saddr fe80::/64 ip6 hoplimit 255 accept
+
+               udp sport dhcpv6-server udp dport dhcpv6-client ip6 saddr fe80::/64 accept
+               fib daddr type { broadcast, multicast, anycast } counter drop
+
+               counter drop
+       }
+       chain home_input {
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept
+               icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept
+
+               udp sport bootpc udp dport bootps accept
+               udp sport dhcpv6-client udp dport dhcpv6-server iifname $home_ipv6_if accept
+
+               fib daddr type { broadcast, multicast, anycast } counter drop
+
+               icmp type echo-request accept
+               icmpv6 type echo-request accept
+
+               tcp dport ssh iifname $trusted_if accept
+
+               meta l4proto { tcp, udp } th dport domain jump {
+                       ip6 saddr != $private_ip6 counter reject
+                       accept
+               }
+
+               udp dport ntp accept
+
+               tcp dport $proxy_port accept
+       }
+
+       chain FORWARD_MANGLE {
+               type filter hook forward priority mangle;
+
+               oifname $public_if jump {
+                       ct state new meta nfproto vmap { ipv4 : jump blacklist_output_ipv4, ipv6 : jump blacklist_output_ipv6 }
+                       tcp flags & (syn|rst) == syn tcp option maxseg size set rt mtu
+               }
+       }
+       chain blacklist_output_ipv4 {
+               ip daddr $bogons_ip goto log_blacklist
+               ip daddr @ipv4_blacklist goto log_blacklist
+       }
+       chain blacklist_output_ipv6 {
+               icmpv6 type . ip6 daddr { nd-router-solicit . ff02::2/128, nd-neighbor-solicit . ff02::1:ff00:0/104, nd-neighbor-advert . fe80::/64, nd-neighbor-advert . ff02::1/128, nd-neighbor-advert . ff02::1:ff00:0/104, mld2-listener-report . ff02::16/128 } return
+               udp dport dhcpv6-server ip6 daddr ff02::1:2 return
+
+               ip6 daddr $bogons_ip6 goto log_blacklist
+               ip6 daddr @ipv6_blacklist goto log_blacklist
+       }
+       chain log_blacklist {
+               log prefix "NFT BLACKLIST " flags ether flags ip options limit rate 5/minute burst 10 packets drop
+               counter drop
+       }
+
+       chain FORWARD {
+               type filter hook forward priority filter; policy drop;
+
+               ct state established,related accept
+
+               fib daddr type { broadcast, multicast, anycast } counter drop
+
+               iifname vmap @if_forward
+
+               log prefix "NFT REJECT FWD " flags ether flags ip options limit rate 5/second burst 10 packets reject
+       }
+       chain public_forward {
+               udp dport { sip, 7078-7097 } oifname $voip_if jump {
+                       ip6 saddr $sip_whitelist_ip6 accept
+                       meta nfproto ipv6 log prefix "NFT DROP SIP " flags ether flags ip options limit rate 5/second burst 10 packets drop
+               }
+
+               counter drop
+       }
+       chain trusted_forward {
+               oifname $public_if accept
+
+               icmp type echo-request accept
+               icmpv6 type echo-request accept
+
+               ip daddr { $host3_ip, $host4_ip } tcp dport vmap { ssh : accept, https : accept, http : drop }
+
+               ip daddr $host2_ip jump {
+                       tcp dport { http, https, printer, ipp, 9100 } accept
+                       udp dport snmp accept
+               }
+       }
+       chain voip_forward {
+               icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } oifname $public_if accept
+
+               ip6 daddr $sip_whitelist_ip6 jump {
+                       udp dport { 3478, sip } accept
+                       udp sport { 7078-7097 } accept
+                       tcp dport 5061 accept
+               }
+
+               tcp dport 587 ip daddr $smtps_whitelist_ip accept
+               tcp dport http oifname $public_if counter reject
+       }
+       chain guest_forward {
+               oifname $public_if accept
+       }
+
+       chain OUTPUT {
+               type filter hook output priority filter; policy drop;
+
+               oif lo accept
+
+               ct state vmap { established : accept, related : accept, invalid : jump ct_invalid_out, untracked : jump ct_untracked_out }
+
+               oifname vmap @if_output
+
+               log prefix "NFT REJECT OUT " flags ether flags ip options limit rate 5/second burst 10 packets reject
+       }
+       chain ct_invalid_out {
+               counter drop
+       }
+       chain ct_untracked_out {
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, mld-listener-query, mld2-listener-report } return
+               counter drop
+       }
+       chain public_output {
+               ct state new meta nfproto vmap { ipv4 : jump blacklist_output_ipv4, ipv6 : jump blacklist_output_ipv6 }
+
+               icmp type { destination-unreachable, time-exceeded, parameter-problem, echo-request } accept
+               icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } accept
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept
+               icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept
+
+               udp dport dhcpv6-server ip6 saddr fe80::/64 ip6 daddr ff02::1:2 accept
+
+               udp dport { domain, ntp } accept
+               tcp dport { https, 587, domain-s } accept
+       }
+       chain home_output {
+               icmp type { destination-unreachable, time-exceeded, parameter-problem, echo-request } accept
+               icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } accept
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept
+               icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept
+
+               udp sport dhcpv6-server udp dport dhcpv6-client ip6 saddr fe80::/64 oifname $home_ipv6_if accept
+               udp sport bootps udp dport bootpc ip saddr $private_ip accept
+               tcp dport ssh ip daddr $host1_ip accept
+       }
+
+       chain POSTROUTING_SRCNAT {
+               type nat hook postrouting priority srcnat;
+
+               meta nfproto ipv4 ip saddr $masq_ip oifname $masq_if masquerade
+       }
+}
+EOF