From nobody Thu Aug 7 11:58:02 2025 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4byQf30QPKz64BcL; Thu, 07 Aug 2025 11:58:03 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4byQf25bNSz3njK; Thu, 07 Aug 2025 11:58:02 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1754567882; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=eyaMjITlu+Qqk0OWs1ibMYEjNd3z+RvXsv/b9KFcgLU=; b=VHHo+3u49oR9EhwAdZZg+35c7MzLjManc19s8pb6lHzkWhcsIMsAM/8m2ZiaQVL6A1nAZc FLO2N2kbRIxkkDhtUDMOv+0WIPbMeiZ9m4WZu4Eel51UU0+rS+a2Tx/JaFpzoZJP374pcG y3WvI6ySLrjs+Gawm6oh5FQWI0pd9osiLyzvn3uHeUBOryk6VbC8z0MhOBlEViiUyS6Cp3 wK+vSzNv9K9iAppkVmV5ZVxb0o3WJesnQvapW1r5Q1QFhmQmD/XROsQtvETcD7PDeWGep2 8lJRFlsUgv7qPMj2y4nD0rq+wSbFRAgykI/AaIXYpWt1K+h/8GhlMvot4gmjLQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1754567882; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=eyaMjITlu+Qqk0OWs1ibMYEjNd3z+RvXsv/b9KFcgLU=; b=r5gUH++veuTxUFa4/rUsU9iGWe92uxuCC9Id00ddG+MGeUbuAG4mAolKk4mFuKdRH3SNj+ edDFdhuOUD60iVdcHGrqn28/TIHaGum0l50IwEHeunxWFTHRrW4IqLGFG3VhBDgGOb4mJC W9Unbd/KWAwNaNpL+SfVn8Vgp7OWDqo2PTpwZo1ejJ7/A/k1SyTi9JnjPKduFmNR4RCC1B 5lgyE/unDNNlBiPHQgSy6i5TVjCkIFkdsI8CpUom4RTJTgqpAw4aphHPE4i0341vQXaNZ9 6U5L7CtSOIlLflDvlPCVZ4CuVKMHv8Cdal7K3QK3YLpZPrpu6mtcwwCVmp2X8A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1754567882; a=rsa-sha256; cv=none; b=Yo/jQ0m52rcQ3mpY0Z8+kZ2BBi2WkSvi16rjyYnMizJ9hPZO1iSXUpf0i74GALefVc60Xu t0AuiKGylXhlJVWwXLT9qtb1KhGJ1uG7KPvBfkz/SWJ0dQNTE0qAnjf15+586iXj9PS7ij znZxuryBIPybXcdej/fzUZEohWXGoEqH0Jg7Ff7D90wbpQIsbUDJAGLSCAUBFBokDiLO9v UI+B4aQAxouZZoqKVFQOeIpRGKHXyk5FjVn3dVpZ5WM+ARBQHKeI6LlHdZKX7M1xSW/D8/ qeH+YBW/hnfNmQ30naGCM1JGiEAB9glootsAR78uZd23PUl5Yosz7d88NLfpMg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4byQf24bYzz14T1; Thu, 07 Aug 2025 11:58:02 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 577Bw2IP048279; Thu, 7 Aug 2025 11:58:02 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 577Bw2BD048276; Thu, 7 Aug 2025 11:58:02 GMT (envelope-from git) Date: Thu, 7 Aug 2025 11:58:02 GMT Message-Id: <202508071158.577Bw2BD048276@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kajetan Staszkiewicz Subject: git: 5bbdd368c7b1 - main - pf tests: Improve tests for af-to List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: ks X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 5bbdd368c7b1afb4e06d8e0fe73ce8c4f4a1eacf Auto-Submitted: auto-generated The branch main has been updated by ks: URL: https://cgit.FreeBSD.org/src/commit/?id=5bbdd368c7b1afb4e06d8e0fe73ce8c4f4a1eacf commit 5bbdd368c7b1afb4e06d8e0fe73ce8c4f4a1eacf Author: Kajetan Staszkiewicz AuthorDate: 2025-07-28 18:43:07 +0000 Commit: Kajetan Staszkiewicz CommitDate: 2025-08-07 11:52:45 +0000 pf tests: Improve tests for af-to NAT64 performed on inbound direction bypasses outbound filtering and creates only a single state which is bound to the outbound interface. Extend TCP NAT64 tests to cover all combinations of inbound/outbound rule and floating/if-bound states. Reviewed by: kp Approved by: kp Sponsored by: InnoGames GmbH Differential Revision: https://reviews.freebsd.org/D51788 --- tests/sys/netpfil/pf/nat64.py | 6 +- tests/sys/netpfil/pf/nat64.sh | 170 +++++++++++++++++++++++++++++++++----- tests/sys/netpfil/pf/src_track.sh | 2 + 3 files changed, 156 insertions(+), 22 deletions(-) diff --git a/tests/sys/netpfil/pf/nat64.py b/tests/sys/netpfil/pf/nat64.py index 0908c90c34a0..705de72f5bc4 100644 --- a/tests/sys/netpfil/pf/nat64.py +++ b/tests/sys/netpfil/pf/nat64.py @@ -96,8 +96,10 @@ class TestNAT64(VnetTestTemplate): ToolsHelper.print_output("/sbin/route add default 192.0.2.2") ToolsHelper.print_output("/sbin/pfctl -e") ToolsHelper.pf_rules([ - "pass inet6 proto icmp6", - "pass in on %s inet6 af-to inet from 192.0.2.1" % ifname]) + "block", + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }", + "pass in on %s inet6 af-to inet from 192.0.2.1" % ifname, + ]) vnet.pipe.send(socket.if_nametoindex("pflog0")) diff --git a/tests/sys/netpfil/pf/nat64.sh b/tests/sys/netpfil/pf/nat64.sh index f92a69f2abce..4438ad6abb85 100644 --- a/tests/sys/netpfil/pf/nat64.sh +++ b/tests/sys/netpfil/pf/nat64.sh @@ -55,15 +55,19 @@ nat64_setup_base() nat64_setup_in() { + state_policy="${1:-if-bound}" nat64_setup_base pft_set_rules rtr \ "set reassemble yes" \ - "set state-policy if-bound" \ + "set state-policy ${state_policy}" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ "pass in on ${epair}b inet6 from any to 64:ff9b::/96 af-to inet from (${epair_link}a)" } nat64_setup_out() { + state_policy="${1:-if-bound}" nat64_setup_base jexec rtr sysctl net.inet6.ip6.forwarding=1 # AF translation happens post-routing, traffic must be directed @@ -72,11 +76,11 @@ nat64_setup_out() jexec rtr route add -inet6 64:ff9b::/96 -iface ${epair_link}a; pft_set_rules rtr \ "set reassemble yes" \ - "set state-policy if-bound" \ - "pass quick inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ - "pass in quick on ${epair}b from any to 64:ff9b::/96" \ - "pass out quick on ${epair_link}a from any to 64:ff9b::/96 af-to inet from (${epair_link}a)" \ - "block" + "set state-policy ${state_policy}" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ + "pass in on ${epair}b from any to 64:ff9b::/96" \ + "pass out on ${epair_link}a from any to 64:ff9b::/96 af-to inet from (${epair_link}a)" } atf_test_case "icmp_echo_in" "cleanup" @@ -185,14 +189,14 @@ fragmentation_out_cleanup() pft_cleanup } -atf_test_case "tcp_in" "cleanup" -tcp_in_head() +atf_test_case "tcp_in_if_bound" "cleanup" +tcp_in_if_bound_head() { - atf_set descr 'TCP NAT64 test on inbound interface' + atf_set descr 'TCP NAT64 test on inbound interface, if-bound states' atf_set require.user root } -tcp_in_body() +tcp_in_if_bound_body() { nat64_setup_in @@ -208,21 +212,32 @@ tcp_in_body() echo "rcv=${rcv}" atf_fail "Failed to connect to TCP server" fi + + # Interfaces of the state are reversed when doing inbound NAT64! + # FIXME: Packets counters seem wrong! + states=$(mktemp) || exit 1 + jexec rtr pfctl -qvvss | normalize_pfctl_s > $states + for state_regexp in \ + "${epair_link}a tcp 192.0.2.1:[0-9]+ \(2001:db8::2\[[0-9]+\]\) -> 192.0.2.2:1234 \(64:ff9b::c000:202\[1234\]\) .* 9:9 pkts.* rule 3 .* origif: ${epair}b" \ + ; do + grep -qE "${state_regexp}" $states || atf_fail "State not found for '${state_regexp}'" + done + [ $(cat $states | grep tcp | wc -l) -eq 1 ] || atf_fail "Not exactly 1 state found!" } -tcp_in_cleanup() +tcp_in_if_bound_cleanup() { pft_cleanup } -atf_test_case "tcp_out" "cleanup" -tcp_out_head() +atf_test_case "tcp_out_if_bound" "cleanup" +tcp_out_if_bound_head() { - atf_set descr 'TCP NAT64 test on outbound interface' + atf_set descr 'TCP NAT64 test on outbound interface, if-bound states' atf_set require.user root } -tcp_out_body() +tcp_out_if_bound_body() { nat64_setup_out @@ -238,9 +253,102 @@ tcp_out_body() echo "rcv=${rcv}" atf_fail "Failed to connect to TCP server" fi + + # Origif is not printed when identical as if. + states=$(mktemp) || exit 1 + jexec rtr pfctl -qvvss | normalize_pfctl_s > $states + for state_regexp in \ + "${epair}b tcp 64:ff9b::c000:202\[1234\] <- 2001:db8::2\[[0-9]+\] .* 5:4 pkts.* rule 3 .*creatorid" \ + "${epair_link}a tcp 192.0.2.1:[0-9]+ \(64:ff9b::c000:202\[1234\]\) -> 192.0.2.2:1234 \(2001:db8::2\[[0-9]+\]\).* 5:4 pkts.* rule 4 .*creatorid" \ + ; do + grep -qE "${state_regexp}" $states || atf_fail "State not found for '${state_regexp}'" + done + [ $(cat $states | grep tcp | wc -l) -eq 2 ] || atf_fail "Not exactly 2 states found!" } -tcp_out_cleanup() +tcp_out_if_bound_cleanup() +{ + pft_cleanup +} + +atf_test_case "tcp_in_floating" "cleanup" +tcp_in_floating_head() +{ + atf_set descr 'TCP NAT64 test on inbound interface, floating states' + atf_set require.user root +} + +tcp_in_floating_body() +{ + nat64_setup_in "floating" + + echo "foo" | jexec dst nc -l 1234 & + + # Sanity check & delay for nc startup + atf_check -s exit:0 -o ignore \ + ping6 -c 3 64:ff9b::192.0.2.2 + + rcv=$(nc -w 3 -6 64:ff9b::c000:202 1234) + if [ "${rcv}" != "foo" ]; + then + echo "rcv=${rcv}" + atf_fail "Failed to connect to TCP server" + fi + + # Interfaces of the state are reversed when doing inbound NAT64! + # FIXME: Packets counters seem wrong! + states=$(mktemp) || exit 1 + jexec rtr pfctl -qvvss | normalize_pfctl_s > $states + for state_regexp in \ + "all tcp 192.0.2.1:[0-9]+ \(2001:db8::2\[[0-9]+\]\) -> 192.0.2.2:1234 \(64:ff9b::c000:202\[1234\]\).* 9:9 pkts.* rule 3 .* origif: ${epair}b" \ + ; do + grep -qE "${state_regexp}" $states || atf_fail "State not found for '${state_regexp}'" + done + [ $(cat $states | grep tcp | wc -l) -eq 1 ] || atf_fail "Not exactly 1 state found!" +} + +tcp_in_floating_cleanup() +{ + pft_cleanup +} + +atf_test_case "tcp_out_floating" "cleanup" +tcp_out_floating_head() +{ + atf_set descr 'TCP NAT64 test on outbound interface, floating states' + atf_set require.user root +} + +tcp_out_floating_body() +{ + nat64_setup_out "floating" + + echo "foo" | jexec dst nc -l 1234 & + + # Sanity check & delay for nc startup + atf_check -s exit:0 -o ignore \ + ping6 -c 3 64:ff9b::192.0.2.2 + + rcv=$(nc -w 3 -6 64:ff9b::c000:202 1234) + if [ "${rcv}" != "foo" ]; + then + echo "rcv=${rcv}" + atf_fail "Failed to connect to TCP server" + fi + + # Origif is not printed when identical as if. + states=$(mktemp) || exit 1 + jexec rtr pfctl -qvvss | normalize_pfctl_s > $states + for state_regexp in \ + "all tcp 64:ff9b::c000:202\[1234\] <- 2001:db8::2\[[0-9]+\] .* 5:4 pkts,.* rule 3 .*creatorid"\ + "all tcp 192.0.2.1:[0-9]+ \(64:ff9b::c000:202\[1234\]\) -> 192.0.2.2:1234 \(2001:db8::2\[[0-9]+\]\) .* 5:4 pkts,.* rule 4 .*creatorid"\ + ; do + grep -qE "${state_regexp}" $states || atf_fail "State not found for '${state_regexp}'" + done + [ $(cat $states | grep tcp | wc -l) -eq 2 ] || atf_fail "Not exactly 2 states found!" +} + +tcp_out_floating_cleanup() { pft_cleanup } @@ -433,7 +541,9 @@ no_v4_body() jexec rtr pfctl -e pft_set_rules rtr \ - "pass in on ${epair}b inet6 from any to 64:ff9b::/96 af-to inet from (${epair_link}a)" + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ + "pass in on ${epair}b inet6 from any to 64:ff9b::/96 af-to inet from (${epair_link}a)" \ atf_check -s exit:2 -o ignore \ ping6 -c 3 64:ff9b::192.0.2.2 @@ -484,7 +594,9 @@ range_body() pft_set_rules rtr \ "set reassemble yes" \ "set state-policy if-bound" \ - "pass in on ${epair}b inet6 from any to 64:ff9b::/96 af-to inet from 192.0.2.2/31 round-robin" + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ + "pass in on ${epair}b inet6 from any to 64:ff9b::/96 af-to inet from 192.0.2.2/31 round-robin" \ # Use pf to count sources jexec dst pfctl -e @@ -545,6 +657,8 @@ pool_body() pft_set_rules rtr \ "set reassemble yes" \ "set state-policy if-bound" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ "pass in on ${epair}b inet6 from any to 64:ff9b::/96 af-to inet from { 192.0.2.1, 192.0.2.3, 192.0.2.4 } round-robin" # Use pf to count sources @@ -642,6 +756,8 @@ table_range_body() "set reassemble yes" \ "set state-policy if-bound" \ "table { 192.0.2.2/31 }" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ "pass in on ${epair}b inet6 from any to 64:ff9b::/96 af-to inet from round-robin" # Use pf to count sources @@ -699,6 +815,8 @@ table_common_body() "set reassemble yes" \ "set state-policy if-bound" \ "table { 192.0.2.1, 192.0.2.3, 192.0.2.4 }" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ "pass in on ${epair}b inet6 from any to 64:ff9b::/96 af-to inet from ${pool_type}" # Use pf to count sources @@ -798,6 +916,8 @@ dummynet_body() pft_set_rules rtr \ "set reassemble yes" \ "set state-policy if-bound" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ "pass in on ${epair}b inet6 from any to 64:ff9b::/96 dnpipe 1 af-to inet from (${epair_link}a)" # The ping request will pass, but take 1.2 seconds (.6 in, .6 out) @@ -860,6 +980,8 @@ gateway6_body() pft_set_rules rtr \ "set reassemble yes" \ "set state-policy if-bound" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ "pass in on ${epair_lan_link}b inet6 from any to 64:ff9b::/96 af-to inet from (${epair_link}a)" # One ping @@ -912,6 +1034,8 @@ route_to_body() pft_set_rules rtr \ "set reassemble yes" \ "set state-policy if-bound" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ "pass in on ${epair}b route-to (${epair_link}a 192.0.2.2) inet6 from any to 64:ff9b::/96 af-to inet from (${epair_link}a)" atf_check -s exit:0 -o ignore \ @@ -965,6 +1089,8 @@ reply_to_body() pft_set_rules rtr \ "set reassemble yes" \ "set state-policy if-bound" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ "pass in on ${epair}b reply-to (${epair}b 2001:db8::2) inet6 from any to 64:ff9b::/96 af-to inet from 192.0.2.1" atf_check -s exit:0 -o ignore \ @@ -1024,6 +1150,8 @@ v6_gateway_body() pft_set_rules rtr \ "set reassemble yes" \ "set state-policy if-bound" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ "pass in on ${epair_lan}b inet6 from any to 64:ff9b::/96 af-to inet from (${epair_wan_one}a)" atf_check -s exit:0 -o ignore \ @@ -1043,8 +1171,10 @@ atf_init_test_cases() atf_add_test_case "icmp_echo_out" atf_add_test_case "fragmentation_in" atf_add_test_case "fragmentation_out" - atf_add_test_case "tcp_in" - atf_add_test_case "tcp_out" + atf_add_test_case "tcp_in_if_bound" + atf_add_test_case "tcp_out_if_bound" + atf_add_test_case "tcp_in_floating" + atf_add_test_case "tcp_out_floating" atf_add_test_case "udp_in" atf_add_test_case "udp_out" atf_add_test_case "sctp_in" diff --git a/tests/sys/netpfil/pf/src_track.sh b/tests/sys/netpfil/pf/src_track.sh index 68e7e72f5018..ae60a5df809b 100755 --- a/tests/sys/netpfil/pf/src_track.sh +++ b/tests/sys/netpfil/pf/src_track.sh @@ -523,6 +523,8 @@ mixed_af_body() pft_set_rules router \ "set reassemble yes" \ "set state-policy if-bound" \ + "block" \ + "pass inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ "pass in on ${epair_tester}b \ route-to { (${epair_server1}a ${net_server1_4_host_server}) \ } sticky-address \