Skip to content

Commit ec94288

Browse files
Florian Westphalsmb49
authored andcommitted
selftests: netfilter: check stateless nat udp checksum fixup
BugLink: https://bugs.launchpad.net/bugs/1966021 commit aad51ca upstream. Add a test that sends large udp packet (which is fragmented) via a stateless nft nat rule, i.e. 'ip saddr set 10.2.3.4' and check that the datagram is received by peer. On kernels without commit 4e1860a ("netfilter: nft_payload: do not update layer 4 checksum when mangling fragments")', this will fail with: cmp: EOF on /tmp/tmp.V1q0iXJyQF which is empty -rw------- 1 root root 4096 Jan 24 22:03 /tmp/tmp.Aaqnq4rBKS -rw------- 1 root root 0 Jan 24 22:03 /tmp/tmp.V1q0iXJyQF ERROR: in and output file mismatch when checking udp with stateless nat FAIL: nftables v1.0.0 (Fearless Fosdick #2) On patched kernels, this will show: PASS: IP statless for ns2-PFp89amx Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> Signed-off-by: Kamal Mostafa <[email protected]> Signed-off-by: Stefan Bader <[email protected]>
1 parent 8b56f5e commit ec94288

File tree

1 file changed

+153
-0
lines changed

1 file changed

+153
-0
lines changed

tools/testing/selftests/netfilter/nft_nat.sh

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,144 @@ EOF
742742
}
743743

744744

745+
test_stateless_nat_ip()
746+
{
747+
local lret=0
748+
749+
ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
750+
ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
751+
752+
ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
753+
if [ $? -ne 0 ] ; then
754+
echo "ERROR: cannot ping $ns1 from $ns2 before loading stateless rules"
755+
return 1
756+
fi
757+
758+
ip netns exec "$ns0" nft -f /dev/stdin <<EOF
759+
table ip stateless {
760+
map xlate_in {
761+
typeof meta iifname . ip saddr . ip daddr : ip daddr
762+
elements = {
763+
"veth1" . 10.0.2.99 . 10.0.1.99 : 10.0.2.2,
764+
}
765+
}
766+
map xlate_out {
767+
typeof meta iifname . ip saddr . ip daddr : ip daddr
768+
elements = {
769+
"veth0" . 10.0.1.99 . 10.0.2.2 : 10.0.2.99
770+
}
771+
}
772+
773+
chain prerouting {
774+
type filter hook prerouting priority -400; policy accept;
775+
ip saddr set meta iifname . ip saddr . ip daddr map @xlate_in
776+
ip daddr set meta iifname . ip saddr . ip daddr map @xlate_out
777+
}
778+
}
779+
EOF
780+
if [ $? -ne 0 ]; then
781+
echo "SKIP: Could not add ip statless rules"
782+
return $ksft_skip
783+
fi
784+
785+
reset_counters
786+
787+
ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
788+
if [ $? -ne 0 ] ; then
789+
echo "ERROR: cannot ping $ns1 from $ns2 with stateless rules"
790+
lret=1
791+
fi
792+
793+
# ns1 should have seen packets from .2.2, due to stateless rewrite.
794+
expect="packets 1 bytes 84"
795+
cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0insl | grep -q "$expect")
796+
if [ $? -ne 0 ]; then
797+
bad_counter "$ns1" ns0insl "$expect" "test_stateless 1"
798+
lret=1
799+
fi
800+
801+
for dir in "in" "out" ; do
802+
cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
803+
if [ $? -ne 0 ]; then
804+
bad_counter "$ns2" ns1$dir "$expect" "test_stateless 2"
805+
lret=1
806+
fi
807+
done
808+
809+
# ns1 should not have seen packets from ns2, due to masquerade
810+
expect="packets 0 bytes 0"
811+
for dir in "in" "out" ; do
812+
cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
813+
if [ $? -ne 0 ]; then
814+
bad_counter "$ns1" ns0$dir "$expect" "test_stateless 3"
815+
lret=1
816+
fi
817+
818+
cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
819+
if [ $? -ne 0 ]; then
820+
bad_counter "$ns0" ns1$dir "$expect" "test_stateless 4"
821+
lret=1
822+
fi
823+
done
824+
825+
reset_counters
826+
827+
socat -h > /dev/null 2>&1
828+
if [ $? -ne 0 ];then
829+
echo "SKIP: Could not run stateless nat frag test without socat tool"
830+
if [ $lret -eq 0 ]; then
831+
return $ksft_skip
832+
fi
833+
834+
ip netns exec "$ns0" nft delete table ip stateless
835+
return $lret
836+
fi
837+
838+
local tmpfile=$(mktemp)
839+
dd if=/dev/urandom of=$tmpfile bs=4096 count=1 2>/dev/null
840+
841+
local outfile=$(mktemp)
842+
ip netns exec "$ns1" timeout 3 socat -u UDP4-RECV:4233 OPEN:$outfile < /dev/null &
843+
sc_r=$!
844+
845+
sleep 1
846+
# re-do with large ping -> ip fragmentation
847+
ip netns exec "$ns2" timeout 3 socat - UDP4-SENDTO:"10.0.1.99:4233" < "$tmpfile" > /dev/null
848+
if [ $? -ne 0 ] ; then
849+
echo "ERROR: failed to test udp $ns1 to $ns2 with stateless ip nat" 1>&2
850+
lret=1
851+
fi
852+
853+
wait
854+
855+
cmp "$tmpfile" "$outfile"
856+
if [ $? -ne 0 ]; then
857+
ls -l "$tmpfile" "$outfile"
858+
echo "ERROR: in and output file mismatch when checking udp with stateless nat" 1>&2
859+
lret=1
860+
fi
861+
862+
rm -f "$tmpfile" "$outfile"
863+
864+
# ns1 should have seen packets from 2.2, due to stateless rewrite.
865+
expect="packets 3 bytes 4164"
866+
cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0insl | grep -q "$expect")
867+
if [ $? -ne 0 ]; then
868+
bad_counter "$ns1" ns0insl "$expect" "test_stateless 5"
869+
lret=1
870+
fi
871+
872+
ip netns exec "$ns0" nft delete table ip stateless
873+
if [ $? -ne 0 ]; then
874+
echo "ERROR: Could not delete table ip stateless" 1>&2
875+
lret=1
876+
fi
877+
878+
test $lret -eq 0 && echo "PASS: IP statless for $ns2"
879+
880+
return $lret
881+
}
882+
745883
# ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99
746884
for i in 0 1 2; do
747885
ip netns exec ns$i-$sfx nft -f /dev/stdin <<EOF
@@ -808,6 +946,19 @@ table inet filter {
808946
EOF
809947
done
810948

949+
# special case for stateless nat check, counter needs to
950+
# be done before (input) ip defragmentation
951+
ip netns exec ns1-$sfx nft -f /dev/stdin <<EOF
952+
table inet filter {
953+
counter ns0insl {}
954+
955+
chain pre {
956+
type filter hook prerouting priority -400; policy accept;
957+
ip saddr 10.0.2.2 counter name "ns0insl"
958+
}
959+
}
960+
EOF
961+
811962
sleep 3
812963
# test basic connectivity
813964
for i in 1 2; do
@@ -861,6 +1012,8 @@ reset_counters
8611012
$test_inet_nat && test_redirect inet
8621013
$test_inet_nat && test_redirect6 inet
8631014

1015+
+test_stateless_nat_ip
1016+
8641017
if [ $ret -ne 0 ];then
8651018
echo -n "FAIL: "
8661019
nft --version

0 commit comments

Comments
 (0)