Skip to content

Commit 3853c4e

Browse files
Florian Westphalgregkh
authored andcommitted
selftests: netfilter: check stateless nat udp checksum fixup
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 <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent b847532 commit 3853c4e

1 file changed

Lines changed: 152 additions & 0 deletions

File tree

tools/testing/selftests/netfilter/nft_nat.sh

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,144 @@ EOF
885885
ip netns exec "$ns0" nft delete table $family nat
886886
}
887887

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

1092+
# special case for stateless nat check, counter needs to
1093+
# be done before (input) ip defragmentation
1094+
ip netns exec ns1-$sfx nft -f /dev/stdin <<EOF
1095+
table inet filter {
1096+
counter ns0insl {}
1097+
1098+
chain pre {
1099+
type filter hook prerouting priority -400; policy accept;
1100+
ip saddr 10.0.2.2 counter name "ns0insl"
1101+
}
1102+
}
1103+
EOF
1104+
9541105
sleep 3
9551106
# test basic connectivity
9561107
for i in 1 2; do
@@ -1005,6 +1156,7 @@ $test_inet_nat && test_redirect inet
10051156
$test_inet_nat && test_redirect6 inet
10061157

10071158
test_port_shadowing
1159+
test_stateless_nat_ip
10081160

10091161
if [ $ret -ne 0 ];then
10101162
echo -n "FAIL: "

0 commit comments

Comments
 (0)