Skip to content

Commit aad51ca

Browse files
Florian Westphalummakynes
Florian Westphal
authored andcommitted
selftests: netfilter: check stateless nat udp checksum fixup
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]>
1 parent c858620 commit aad51ca

File tree

1 file changed

+152
-0
lines changed

1 file changed

+152
-0
lines changed

tools/testing/selftests/netfilter/nft_nat.sh

+152
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,144 @@ EOF
899899
ip netns exec "$ns0" nft delete table $family nat
900900
}
901901

902+
test_stateless_nat_ip()
903+
{
904+
local lret=0
905+
906+
ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
907+
ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
908+
909+
ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
910+
if [ $? -ne 0 ] ; then
911+
echo "ERROR: cannot ping $ns1 from $ns2 before loading stateless rules"
912+
return 1
913+
fi
914+
915+
ip netns exec "$ns0" nft -f /dev/stdin <<EOF
916+
table ip stateless {
917+
map xlate_in {
918+
typeof meta iifname . ip saddr . ip daddr : ip daddr
919+
elements = {
920+
"veth1" . 10.0.2.99 . 10.0.1.99 : 10.0.2.2,
921+
}
922+
}
923+
map xlate_out {
924+
typeof meta iifname . ip saddr . ip daddr : ip daddr
925+
elements = {
926+
"veth0" . 10.0.1.99 . 10.0.2.2 : 10.0.2.99
927+
}
928+
}
929+
930+
chain prerouting {
931+
type filter hook prerouting priority -400; policy accept;
932+
ip saddr set meta iifname . ip saddr . ip daddr map @xlate_in
933+
ip daddr set meta iifname . ip saddr . ip daddr map @xlate_out
934+
}
935+
}
936+
EOF
937+
if [ $? -ne 0 ]; then
938+
echo "SKIP: Could not add ip statless rules"
939+
return $ksft_skip
940+
fi
941+
942+
reset_counters
943+
944+
ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
945+
if [ $? -ne 0 ] ; then
946+
echo "ERROR: cannot ping $ns1 from $ns2 with stateless rules"
947+
lret=1
948+
fi
949+
950+
# ns1 should have seen packets from .2.2, due to stateless rewrite.
951+
expect="packets 1 bytes 84"
952+
cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0insl | grep -q "$expect")
953+
if [ $? -ne 0 ]; then
954+
bad_counter "$ns1" ns0insl "$expect" "test_stateless 1"
955+
lret=1
956+
fi
957+
958+
for dir in "in" "out" ; do
959+
cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
960+
if [ $? -ne 0 ]; then
961+
bad_counter "$ns2" ns1$dir "$expect" "test_stateless 2"
962+
lret=1
963+
fi
964+
done
965+
966+
# ns1 should not have seen packets from ns2, due to masquerade
967+
expect="packets 0 bytes 0"
968+
for dir in "in" "out" ; do
969+
cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
970+
if [ $? -ne 0 ]; then
971+
bad_counter "$ns1" ns0$dir "$expect" "test_stateless 3"
972+
lret=1
973+
fi
974+
975+
cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
976+
if [ $? -ne 0 ]; then
977+
bad_counter "$ns0" ns1$dir "$expect" "test_stateless 4"
978+
lret=1
979+
fi
980+
done
981+
982+
reset_counters
983+
984+
socat -h > /dev/null 2>&1
985+
if [ $? -ne 0 ];then
986+
echo "SKIP: Could not run stateless nat frag test without socat tool"
987+
if [ $lret -eq 0 ]; then
988+
return $ksft_skip
989+
fi
990+
991+
ip netns exec "$ns0" nft delete table ip stateless
992+
return $lret
993+
fi
994+
995+
local tmpfile=$(mktemp)
996+
dd if=/dev/urandom of=$tmpfile bs=4096 count=1 2>/dev/null
997+
998+
local outfile=$(mktemp)
999+
ip netns exec "$ns1" timeout 3 socat -u UDP4-RECV:4233 OPEN:$outfile < /dev/null &
1000+
sc_r=$!
1001+
1002+
sleep 1
1003+
# re-do with large ping -> ip fragmentation
1004+
ip netns exec "$ns2" timeout 3 socat - UDP4-SENDTO:"10.0.1.99:4233" < "$tmpfile" > /dev/null
1005+
if [ $? -ne 0 ] ; then
1006+
echo "ERROR: failed to test udp $ns1 to $ns2 with stateless ip nat" 1>&2
1007+
lret=1
1008+
fi
1009+
1010+
wait
1011+
1012+
cmp "$tmpfile" "$outfile"
1013+
if [ $? -ne 0 ]; then
1014+
ls -l "$tmpfile" "$outfile"
1015+
echo "ERROR: in and output file mismatch when checking udp with stateless nat" 1>&2
1016+
lret=1
1017+
fi
1018+
1019+
rm -f "$tmpfile" "$outfile"
1020+
1021+
# ns1 should have seen packets from 2.2, due to stateless rewrite.
1022+
expect="packets 3 bytes 4164"
1023+
cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0insl | grep -q "$expect")
1024+
if [ $? -ne 0 ]; then
1025+
bad_counter "$ns1" ns0insl "$expect" "test_stateless 5"
1026+
lret=1
1027+
fi
1028+
1029+
ip netns exec "$ns0" nft delete table ip stateless
1030+
if [ $? -ne 0 ]; then
1031+
echo "ERROR: Could not delete table ip stateless" 1>&2
1032+
lret=1
1033+
fi
1034+
1035+
test $lret -eq 0 && echo "PASS: IP statless for $ns2"
1036+
1037+
return $lret
1038+
}
1039+
9021040
# ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99
9031041
for i in 0 1 2; do
9041042
ip netns exec ns$i-$sfx nft -f /dev/stdin <<EOF
@@ -965,6 +1103,19 @@ table inet filter {
9651103
EOF
9661104
done
9671105

1106+
# special case for stateless nat check, counter needs to
1107+
# be done before (input) ip defragmentation
1108+
ip netns exec ns1-$sfx nft -f /dev/stdin <<EOF
1109+
table inet filter {
1110+
counter ns0insl {}
1111+
1112+
chain pre {
1113+
type filter hook prerouting priority -400; policy accept;
1114+
ip saddr 10.0.2.2 counter name "ns0insl"
1115+
}
1116+
}
1117+
EOF
1118+
9681119
sleep 3
9691120
# test basic connectivity
9701121
for i in 1 2; do
@@ -1019,6 +1170,7 @@ $test_inet_nat && test_redirect inet
10191170
$test_inet_nat && test_redirect6 inet
10201171

10211172
test_port_shadowing
1173+
test_stateless_nat_ip
10221174

10231175
if [ $ret -ne 0 ];then
10241176
echo -n "FAIL: "

0 commit comments

Comments
 (0)