diff options
Diffstat (limited to 'tests/sys/netpfil/pf/pfsync.sh')
-rw-r--r-- | tests/sys/netpfil/pf/pfsync.sh | 466 |
1 files changed, 459 insertions, 7 deletions
diff --git a/tests/sys/netpfil/pf/pfsync.sh b/tests/sys/netpfil/pf/pfsync.sh index 3be4a3024393..9843c470c06f 100644 --- a/tests/sys/netpfil/pf/pfsync.sh +++ b/tests/sys/netpfil/pf/pfsync.sh @@ -921,6 +921,8 @@ rtable_cleanup() route_to_common_head() { + # TODO: Extend setup_router_server_nat64 to create a 2nd router + pfsync_version=$1 shift @@ -937,11 +939,16 @@ route_to_common_head() # pfsync interface jexec one ifconfig ${epair_sync}a 192.0.2.1/24 up - jexec one ifconfig ${epair_one}a 198.51.100.1/24 up + jexec one ifconfig ${epair_one}a 198.51.100.1/28 up + jexec one ifconfig ${epair_one}a inet6 2001:db8:4211::1/64 no_dad + jexec one ifconfig ${epair_one}a name inif jexec one ifconfig ${epair_out_one}a 203.0.113.1/24 up + jexec one ifconfig ${epair_out_one}a inet6 2001:db8:4200::1/64 no_dad jexec one ifconfig ${epair_out_one}a name outif jexec one sysctl net.inet.ip.forwarding=1 - jexec one arp -s 203.0.113.254 00:01:02:03:04:05 + jexec one sysctl net.inet6.ip6.forwarding=1 + jexec one arp -s 203.0.113.254 00:01:02:00:00:04 + jexec one ndp -s 2001:db8:4200::fe 00:01:02:00:00:06 jexec one ifconfig pfsync0 \ syncdev ${epair_sync}a \ maxupd 1 \ @@ -949,20 +956,30 @@ route_to_common_head() up jexec two ifconfig ${epair_sync}b 192.0.2.2/24 up - jexec two ifconfig ${epair_two}a 198.51.100.2/24 up - jexec two ifconfig ${epair_out_two}a 203.0.113.2/24 up + jexec two ifconfig ${epair_two}a 198.51.100.17/28 up + jexec two ifconfig ${epair_two}a inet6 2001:db8:4212::1/64 no_dad + jexec two ifconfig ${epair_two}a name inif + jexec two ifconfig ${epair_out_two}a 203.0.113.1/24 up + jexec two ifconfig ${epair_out_two}a inet6 2001:db8:4200::2/64 no_dad jexec two ifconfig ${epair_out_two}a name outif jexec two sysctl net.inet.ip.forwarding=1 - jexec two arp -s 203.0.113.254 00:01:02:03:04:05 + jexec two sysctl net.inet6.ip6.forwarding=1 + jexec two arp -s 203.0.113.254 00:01:02:00:00:04 + jexec two ndp -s 2001:db8:4200::fe 00:01:02:00:00:06 jexec two ifconfig pfsync0 \ syncdev ${epair_sync}b \ maxupd 1 \ version $pfsync_version \ up - ifconfig ${epair_one}b 198.51.100.254/24 up - ifconfig ${epair_two}b 198.51.100.253/24 up + ifconfig ${epair_one}b 198.51.100.2/28 up + ifconfig ${epair_one}b inet6 2001:db8:4211::2/64 no_dad + ifconfig ${epair_two}b 198.51.100.18/28 up + ifconfig ${epair_two}b inet6 2001:db8:4212::2/64 no_dad + # Target is behind router "one" route add -net 203.0.113.0/24 198.51.100.1 + route add -inet6 -net 64:ff9b::/96 2001:db8:4211::1 + ifconfig ${epair_two}b up ifconfig ${epair_out_one}b up ifconfig ${epair_out_two}b up @@ -1206,6 +1223,435 @@ route_to_1400_bad_ifname_cleanup() pfsynct_cleanup } +atf_test_case "af_to_in_floating" "cleanup" +af_to_in_floating_head() +{ + atf_set descr 'Test syncing of states created by inbound af-to rules with floating states' + atf_set require.user root + atf_set require.progs python3 scapy +} + +af_to_in_floating_body() +{ + route_to_common_head 1500 + + jexec one pfctl -e + pft_set_rules one \ + "set state-policy floating" \ + "set skip on ${epair_sync}a" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv } keep state (no-sync)" \ + "pass in on inif to 64:ff9b::/96 af-to inet from (outif) keep state" + + jexec two pfctl -e + pft_set_rules two \ + "set skip on ${epair_sync}b" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv } keep state (no-sync)" + + # ptf_ping can't deal with nat64, this test will fail but generate states + atf_check -s exit:1 env PYTHONPATH=${common_dir} \ + ${common_dir}/pft_ping.py \ + --sendif ${epair_one}b \ + --fromaddr 2001:db8:4201::fe \ + --to 64:ff9b::203.0.113.254 \ + --recvif ${epair_out_one}b + + # Allow time for sync + sleep 2 + + states_one=$(mktemp) + states_two=$(mktemp) + jexec one pfctl -qvvss | normalize_pfctl_s > $states_one + jexec two pfctl -qvvss | normalize_pfctl_s > $states_two + + # Sanity check + grep -qE 'all ipv6-icmp 203.0.113.1 \(2001:db8:4201::fe\) -> 203.0.113.254:8 \(64:ff9b::cb00:71fe) .* rule 3 .* origif: inif' $states_one || + atf_fail "State missing on router one" + + grep -qE 'all ipv6-icmp 203.0.113.1 \(2001:db8:4201::fe\) -> 203.0.113.254:8 \(64:ff9b::cb00:71fe) .* origif: inif' $states_two || + atf_fail "State missing on router two" +} + +af_to_in_floating_cleanup() +{ + pfsynct_cleanup +} + +atf_test_case "af_to_in_if_bound" "cleanup" +af_to_in_if_bound_head() +{ + atf_set descr 'Test syncing of states created by inbound af-to rules with if-bound states' + atf_set require.user root + atf_set require.progs python3 scapy +} + +af_to_in_if_bound_body() +{ + route_to_common_head 1500 + + jexec one pfctl -e + pft_set_rules one \ + "set state-policy if-bound" \ + "set skip on ${epair_sync}a" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv } keep state (no-sync)" \ + "pass in on inif to 64:ff9b::/96 af-to inet from (outif) keep state" + + jexec two pfctl -e + pft_set_rules two \ + "set skip on ${epair_sync}b" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv } keep state (no-sync)" + + # ptf_ping can't deal with nat64, this test will fail but generate states + atf_check -s exit:1 env PYTHONPATH=${common_dir} \ + ${common_dir}/pft_ping.py \ + --sendif ${epair_one}b \ + --fromaddr 2001:db8:4201::fe \ + --to 64:ff9b::203.0.113.254 \ + --recvif ${epair_out_one}b + + # Allow time for sync + sleep 2 + + states_one=$(mktemp) + states_two=$(mktemp) + jexec one pfctl -qvvss | normalize_pfctl_s > $states_one + jexec two pfctl -qvvss | normalize_pfctl_s > $states_two + + # Sanity check + grep -qE 'outif ipv6-icmp 203.0.113.1 \(2001:db8:4201::fe\) -> 203.0.113.254:8 \(64:ff9b::cb00:71fe) .* rule 3 .* origif: inif' $states_one || + atf_fail "State missing on router one" + + grep -qE 'outif ipv6-icmp 203.0.113.1 \(2001:db8:4201::fe\) -> 203.0.113.254:8 \(64:ff9b::cb00:71fe) .* origif: inif' $states_two || + atf_fail "State missing on router two" +} + +af_to_in_if_bound_cleanup() +{ + pfsynct_cleanup +} + +atf_test_case "af_to_out_if_bound" "cleanup" +af_to_out_if_bound_head() +{ + atf_set descr 'Test syncing of states created by outbound af-to rules with if-bound states' + atf_set require.user root + atf_set require.progs python3 scapy +} + +af_to_out_if_bound_body() +{ + route_to_common_head 1500 + + jexec one route add -inet6 -net 64:ff9b::/96 -iface outif + jexec one sysctl net.inet6.ip6.forwarding=1 + + jexec one pfctl -e + pft_set_rules one \ + "set state-policy if-bound" \ + "set skip on ${epair_sync}a" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv } keep state (no-sync)" \ + "pass in on inif to 64:ff9b::/96 keep state" \ + "pass out on outif to 64:ff9b::/96 af-to inet from (outif) keep state" + + jexec two pfctl -e + pft_set_rules two \ + "set skip on ${epair_sync}b" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv } keep state (no-sync)" + + # ptf_ping can't deal with nat64, this test will fail but generate states + atf_check -s exit:1 env PYTHONPATH=${common_dir} \ + ${common_dir}/pft_ping.py \ + --sendif ${epair_one}b \ + --fromaddr 2001:db8:4201::fe \ + --to 64:ff9b::203.0.113.254 \ + --recvif ${epair_out_one}b + + # Allow time for sync + sleep 2 + + states_one=$(mktemp) + states_two=$(mktemp) + jexec one pfctl -qvvss | normalize_pfctl_s > $states_one + jexec two pfctl -qvvss | normalize_pfctl_s > $states_two + + # Sanity check + # st->orig_kif is the same as st->kif, so st->orig_kif is not printed. + for state_regexp in \ + "inif ipv6-icmp 64:ff9b::cb00:71fe\[128\] <- 2001:db8:4201::fe .* rule 3 .* creatorid: [0-9a-f]+" \ + "outif icmp 203.0.113.1 \(64:ff9b::cb00:71fe\[8\]\) -> 203.0.113.254:8 \(2001:db8:4201::fe\) .* rule 4 .* creatorid: [0-9a-f]+" \ + ; do + grep -qE "${state_regexp}" $states_one || atf_fail "State not found for '${state_regexp}'" + done + + for state_regexp in \ + "inif ipv6-icmp 64:ff9b::cb00:71fe\[128\] <- 2001:db8:4201::fe .* creatorid: [0-9a-f]+" \ + "outif icmp 203.0.113.1 \(64:ff9b::cb00:71fe\[8\]\) -> 203.0.113.254:8 \(2001:db8:4201::fe\) .* creatorid: [0-9a-f]+" \ + ; do + grep -qE "${state_regexp}" $states_two || atf_fail "State not found for '${state_regexp}'" + done +} + +af_to_out_if_bound_cleanup() +{ + pfsynct_cleanup +} + +atf_test_case "tag" "cleanup" +tag_head() +{ + atf_set descr 'Test if the pf tag is synced' + atf_set require.user root + atf_set require.progs python3 scapy +} + +tag_body() +{ + route_to_common_head 1500 + + jexec one pfctl -e + pft_set_rules one \ + "set skip on ${epair_sync}a" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv } keep state (no-sync)" \ + "pass in on inif inet proto udp tag sometag keep state" \ + "pass out on outif tagged sometag keep state (no-sync)" + + jexec two pfctl -e + pft_set_rules two \ + "set debug loud" \ + "set skip on ${epair_sync}b" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv } keep state (no-sync)" \ + "block tagged othertag" \ + "pass out on outif tagged sometag keep state (no-sync)" + + atf_check -s exit:0 env PYTHONPATH=${common_dir} \ + ${common_dir}/pft_ping.py \ + --ping-type=udp \ + --sendif ${epair_one}b \ + --fromaddr 198.51.100.254 \ + --to 203.0.113.254 \ + --recvif ${epair_out_one}b + + # Allow time for sync + sleep 2 + + # Force the next request to go through the 2nd router + route change -net 203.0.113.0/24 198.51.100.17 + + atf_check -s exit:0 env PYTHONPATH=${common_dir} \ + ${common_dir}/pft_ping.py \ + --ping-type=udp \ + --sendif ${epair_two}b \ + --fromaddr 198.51.100.254 \ + --to 203.0.113.254 \ + --recvif ${epair_out_two}b +} + +tag_cleanup() +{ + pfsynct_cleanup +} + +atf_test_case "altq_queues" "cleanup" +altq_queues_head() +{ + atf_set descr 'Test if the altq queues are synced' + atf_set require.user root + atf_set require.progs python3 scapy +} + +altq_queues_body() +{ + route_to_common_head 1500 + altq_init + is_altq_supported hfsc + + jexec one pfctl -e + pft_set_rules one \ + "set skip on ${epair_sync}a" \ + "altq on outif bandwidth 30000b hfsc queue { default other1 other2 }" \ + "queue default hfsc(linkshare 10000b default)" \ + "queue other1 hfsc(linkshare 10000b)" \ + "queue other2 hfsc(linkshare 10000b)" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv } keep state (no-sync)" \ + "pass in on inif inet proto udp queue other1 keep state" \ + "pass out on outif inet proto udp keep state" + + jexec two pfctl -e + pft_set_rules two \ + "set debug loud" \ + "set skip on ${epair_sync}b" \ + "altq on outif bandwidth 30000b hfsc queue { default other2 other1 }" \ + "queue default hfsc(linkshare 10000b default)" \ + "queue other2 hfsc(linkshare 10000b)" \ + "queue other1 hfsc(linkshare 10000b)" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv } keep state (no-sync)" \ + "pass out on outif inet proto udp keep state" + + atf_check -s exit:0 env PYTHONPATH=${common_dir} \ + ${common_dir}/pft_ping.py \ + --ping-type=udp \ + --sendif ${epair_one}b \ + --fromaddr 198.51.100.254 \ + --to 203.0.113.254 \ + --recvif ${epair_out_one}b + + queues_one=$(mktemp) + jexec one pfctl -qvsq | normalize_pfctl_s > $queues_one + echo " === queues one === " + cat $queues_one + grep -qE 'queue other1 on outif .* pkts: 1 ' $queues_one || atf_fail 'Packets not sent through queue "other1"' + + # Allow time for sync + sleep 2 + + # Force the next request to go through the 2nd router + route change -net 203.0.113.0/24 198.51.100.17 + + # Send a packet through router "two". It lacks the inbound rule + # but the inbound state should have been pfsynced from router "one" + # including altq queuing information. However the queues are created + # on router "two" in different order and we only sync queue index, + # so the packet ends up in a different queue. One must have identical + # queue set on both routers! + atf_check -s exit:0 env PYTHONPATH=${common_dir} \ + ${common_dir}/pft_ping.py \ + --ping-type=udp \ + --sendif ${epair_two}b \ + --fromaddr 198.51.100.254 \ + --to 203.0.113.254 \ + --recvif ${epair_out_two}b + + queues_two=$(mktemp) + jexec two pfctl -qvsq | normalize_pfctl_s > $queues_two + echo " === queues two === " + cat $queues_two + grep -qE 'queue other2 on outif .* pkts: 1 ' $queues_two || atf_fail 'Packets not sent through queue "other2"' +} + +altq_queues_cleanup() +{ + # Interface detaching seems badly broken in altq. If interfaces are + # destroyed when shutting down the vnet and then pf is unloaded, it will + # cause a kernel crash. Work around the issue by first flushing the + # pf rulesets + jexec one pfctl -F all + jexec two pfctl -F all + pfsynct_cleanup +} + +atf_test_case "rt_af" "cleanup" +rt_af_head() +{ + atf_set descr 'Test if the rt_af is synced' + atf_set require.user root + atf_set require.progs python3 scapy +} + +rt_af_body() +{ + route_to_common_head 1500 + + jexec one pfctl -e + pft_set_rules one \ + "set skip on ${epair_sync}a" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv } keep state (no-sync)" \ + "pass in on inif \ + route-to (outif 203.0.113.254) prefer-ipv6-nexthop \ + inet proto udp \ + to 203.0.113.241 \ + keep state" \ + "pass in on inif \ + route-to (outif 2001:db8:4200::fe) prefer-ipv6-nexthop \ + inet proto udp \ + to 203.0.113.242 \ + keep state" \ + "pass in on inif \ + route-to (outif 2001:db8:4200::fe) prefer-ipv6-nexthop \ + inet6 proto udp \ + to 2001:db8:4200::f3 \ + keep state" \ + "pass out on outif inet proto udp keep state (no-sync)" \ + "pass out on outif inet6 proto udp keep state (no-sync)" + + jexec two pfctl -e + pft_set_rules two \ + "set debug loud" \ + "set skip on ${epair_sync}b" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv } keep state (no-sync)" \ + + # IPv4 packet over IPv4 gateway + atf_check -s exit:0 env PYTHONPATH=${common_dir} \ + ${common_dir}/pft_ping.py \ + --ping-type=udp \ + --sendif ${epair_one}b \ + --fromaddr 198.51.100.254 \ + --to 203.0.113.241 \ + --recvif ${epair_out_one}b + + # FIXME: Routing IPv4 packets over IPv6 gateways with gateway added + # with `ndp -s` causes the static NDP entry to become expired. + # Pfsync tests don't use "servers" which can reply to ARP and NDP, + # but such static entry for gateway and only check if a stateless + # ICMP or UDP packet is forward through. + # + # IPv4 packert over IPv6 gateway + #atf_check -s exit:0 env PYTHONPATH=${common_dir} \ + # ${common_dir}/pft_ping.py \ + # --ping-type=udp \ + # --sendif ${epair_one}b \ + # --fromaddr 198.51.100.254 \ + # --to 203.0.113.242 \ + # --recvif ${epair_out_one}b + + # IPv6 packet over IPv6 gateway + atf_check -s exit:0 env PYTHONPATH=${common_dir} \ + ${common_dir}/pft_ping.py \ + --ping-type=udp \ + --sendif ${epair_one}b \ + --fromaddr 2001:db8:4211::fe \ + --to 2001:db8:4200::f3 \ + --recvif ${epair_out_one}b + + sleep 5 # Wait for pfsync + + states_one=$(mktemp) + states_two=$(mktemp) + jexec one pfctl -qvvss | normalize_pfctl_s > $states_one + jexec two pfctl -qvvss | normalize_pfctl_s > $states_two + + echo " === states one === " + cat $states_one + echo " === states two === " + cat $states_two + + for state_regexp in \ + "all udp 203.0.113.241:9 <- 198.51.100.254 .* route-to: 203.0.113.254@outif origif: inif" \ + "all udp 2001:db8:4200::f3\[9\] <- 2001:db8:4211::fe .* route-to: 2001:db8:4200::fe@outif origif: inif" \ + ; do + grep -qE "${state_regexp}" $states_two || atf_fail "State not found for '${state_regexp}' on router two" + done +} + +rt_af_cleanup() +{ + jexec one pfctl -qvvsr + jexec one pfctl -qvvss + jexec one arp -an + jexec one ndp -an + pfsynct_cleanup +} + atf_init_test_cases() { atf_add_test_case "basic" @@ -1224,4 +1670,10 @@ atf_init_test_cases() atf_add_test_case "route_to_1301_bad_rpool" atf_add_test_case "route_to_1400_bad_ruleset" atf_add_test_case "route_to_1400_bad_ifname" + atf_add_test_case "af_to_in_floating" + atf_add_test_case "af_to_in_if_bound" + atf_add_test_case "af_to_out_if_bound" + atf_add_test_case "tag" + atf_add_test_case "altq_queues" + atf_add_test_case "rt_af" } |