diff options
author | Florian Westphal <fw@strlen.de> | 2024-04-12 01:36:06 +0200 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2024-04-12 17:51:23 -0700 |
commit | 3f189349e52ac69a8c4fffef339c5fe177d618f7 (patch) | |
tree | 47a5995742107ef55288ab3ecae650a4900116f8 /tools/testing/selftests/netfilter/nft_nat.sh | |
parent | 982a73c7c594d553a688353c6ae43560542c4cd2 (diff) |
selftests: netfilter: move to net subdir
.. so this can start re-using existing lib.sh infra in next patches.
Several of these scripts will not work, e.g. because they assume
rp_filter is disabled, or reliance on a particular version/flavor
of "netcat" tool.
Add config settings for them.
nft_trans_stress.sh script is removed, it also exists in the nftables
userspace selftests. I do not see a reason to keep two versions in
different repositories/projects.
The settings file is removed for now:
It was used to increase the timeout to avoid slow scripts from getting
zapped by the 45s timeout, but some of the slow scripts can be sped up.
Re-add it later for scripts that cannot be sped up easily.
Update MAINTAINERS to reflect that future updates to netfilter
scripts should go through netfilter-devel@.
Signed-off-by: Florian Westphal <fw@strlen.de>
Link: https://lore.kernel.org/r/20240411233624.8129-2-fw@strlen.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'tools/testing/selftests/netfilter/nft_nat.sh')
-rwxr-xr-x | tools/testing/selftests/netfilter/nft_nat.sh | 1224 |
1 files changed, 0 insertions, 1224 deletions
diff --git a/tools/testing/selftests/netfilter/nft_nat.sh b/tools/testing/selftests/netfilter/nft_nat.sh deleted file mode 100755 index dd40d9f6f259..000000000000 --- a/tools/testing/selftests/netfilter/nft_nat.sh +++ /dev/null @@ -1,1224 +0,0 @@ -#!/bin/bash -# -# This test is for basic NAT functionality: snat, dnat, redirect, masquerade. -# - -# Kselftest framework requirement - SKIP code is 4. -ksft_skip=4 -ret=0 -test_inet_nat=true - -sfx=$(mktemp -u "XXXXXXXX") -ns0="ns0-$sfx" -ns1="ns1-$sfx" -ns2="ns2-$sfx" - -cleanup() -{ - for i in 0 1 2; do ip netns del ns$i-"$sfx";done -} - -nft --version > /dev/null 2>&1 -if [ $? -ne 0 ];then - echo "SKIP: Could not run test without nft tool" - exit $ksft_skip -fi - -ip -Version > /dev/null 2>&1 -if [ $? -ne 0 ];then - echo "SKIP: Could not run test without ip tool" - exit $ksft_skip -fi - -ip netns add "$ns0" -if [ $? -ne 0 ];then - echo "SKIP: Could not create net namespace $ns0" - exit $ksft_skip -fi - -trap cleanup EXIT - -ip netns add "$ns1" -if [ $? -ne 0 ];then - echo "SKIP: Could not create net namespace $ns1" - exit $ksft_skip -fi - -ip netns add "$ns2" -if [ $? -ne 0 ];then - echo "SKIP: Could not create net namespace $ns2" - exit $ksft_skip -fi - -ip link add veth0 netns "$ns0" type veth peer name eth0 netns "$ns1" > /dev/null 2>&1 -if [ $? -ne 0 ];then - echo "SKIP: No virtual ethernet pair device support in kernel" - exit $ksft_skip -fi -ip link add veth1 netns "$ns0" type veth peer name eth0 netns "$ns2" - -ip -net "$ns0" link set lo up -ip -net "$ns0" link set veth0 up -ip -net "$ns0" addr add 10.0.1.1/24 dev veth0 -ip -net "$ns0" addr add dead:1::1/64 dev veth0 - -ip -net "$ns0" link set veth1 up -ip -net "$ns0" addr add 10.0.2.1/24 dev veth1 -ip -net "$ns0" addr add dead:2::1/64 dev veth1 - -for i in 1 2; do - ip -net ns$i-$sfx link set lo up - ip -net ns$i-$sfx link set eth0 up - ip -net ns$i-$sfx addr add 10.0.$i.99/24 dev eth0 - ip -net ns$i-$sfx route add default via 10.0.$i.1 - ip -net ns$i-$sfx addr add dead:$i::99/64 dev eth0 - ip -net ns$i-$sfx route add default via dead:$i::1 -done - -bad_counter() -{ - local ns=$1 - local counter=$2 - local expect=$3 - local tag=$4 - - echo "ERROR: $counter counter in $ns has unexpected value (expected $expect) at $tag" 1>&2 - ip netns exec $ns nft list counter inet filter $counter 1>&2 -} - -check_counters() -{ - ns=$1 - local lret=0 - - cnt=$(ip netns exec $ns nft list counter inet filter ns0in | grep -q "packets 1 bytes 84") - if [ $? -ne 0 ]; then - bad_counter $ns ns0in "packets 1 bytes 84" "check_counters 1" - lret=1 - fi - cnt=$(ip netns exec $ns nft list counter inet filter ns0out | grep -q "packets 1 bytes 84") - if [ $? -ne 0 ]; then - bad_counter $ns ns0out "packets 1 bytes 84" "check_counters 2" - lret=1 - fi - - expect="packets 1 bytes 104" - cnt=$(ip netns exec $ns nft list counter inet filter ns0in6 | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter $ns ns0in6 "$expect" "check_counters 3" - lret=1 - fi - cnt=$(ip netns exec $ns nft list counter inet filter ns0out6 | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter $ns ns0out6 "$expect" "check_counters 4" - lret=1 - fi - - return $lret -} - -check_ns0_counters() -{ - local ns=$1 - local lret=0 - - cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0in | grep -q "packets 0 bytes 0") - if [ $? -ne 0 ]; then - bad_counter "$ns0" ns0in "packets 0 bytes 0" "check_ns0_counters 1" - lret=1 - fi - - cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0in6 | grep -q "packets 0 bytes 0") - if [ $? -ne 0 ]; then - bad_counter "$ns0" ns0in6 "packets 0 bytes 0" - lret=1 - fi - - cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0out | grep -q "packets 0 bytes 0") - if [ $? -ne 0 ]; then - bad_counter "$ns0" ns0out "packets 0 bytes 0" "check_ns0_counters 2" - lret=1 - fi - cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0out6 | grep -q "packets 0 bytes 0") - if [ $? -ne 0 ]; then - bad_counter "$ns0" ns0out6 "packets 0 bytes 0" "check_ns0_counters3 " - lret=1 - fi - - for dir in "in" "out" ; do - expect="packets 1 bytes 84" - cnt=$(ip netns exec "$ns0" nft list counter inet filter ${ns}${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns0" $ns$dir "$expect" "check_ns0_counters 4" - lret=1 - fi - - expect="packets 1 bytes 104" - cnt=$(ip netns exec "$ns0" nft list counter inet filter ${ns}${dir}6 | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns0" $ns$dir6 "$expect" "check_ns0_counters 5" - lret=1 - fi - done - - return $lret -} - -reset_counters() -{ - for i in 0 1 2;do - ip netns exec ns$i-$sfx nft reset counters inet > /dev/null - done -} - -test_local_dnat6() -{ - local family=$1 - local lret=0 - local IPF="" - - if [ $family = "inet" ];then - IPF="ip6" - fi - -ip netns exec "$ns0" nft -f /dev/stdin <<EOF -table $family nat { - chain output { - type nat hook output priority 0; policy accept; - ip6 daddr dead:1::99 dnat $IPF to dead:2::99 - } -} -EOF - if [ $? -ne 0 ]; then - echo "SKIP: Could not add add $family dnat hook" - return $ksft_skip - fi - - # ping netns1, expect rewrite to netns2 - ip netns exec "$ns0" ping -q -c 1 dead:1::99 > /dev/null - if [ $? -ne 0 ]; then - lret=1 - echo "ERROR: ping6 failed" - return $lret - fi - - expect="packets 0 bytes 0" - for dir in "in6" "out6" ; do - cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns0" ns1$dir "$expect" "test_local_dnat6 1" - lret=1 - fi - done - - expect="packets 1 bytes 104" - for dir in "in6" "out6" ; do - cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns0" ns2$dir "$expect" "test_local_dnat6 2" - lret=1 - fi - done - - # expect 0 count in ns1 - expect="packets 0 bytes 0" - for dir in "in6" "out6" ; do - cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns1" ns0$dir "$expect" "test_local_dnat6 3" - lret=1 - fi - done - - # expect 1 packet in ns2 - expect="packets 1 bytes 104" - for dir in "in6" "out6" ; do - cnt=$(ip netns exec "$ns2" nft list counter inet filter ns0${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns2" ns0$dir "$expect" "test_local_dnat6 4" - lret=1 - fi - done - - test $lret -eq 0 && echo "PASS: ipv6 ping to $ns1 was $family NATted to $ns2" - ip netns exec "$ns0" nft flush chain ip6 nat output - - return $lret -} - -test_local_dnat() -{ - local family=$1 - local lret=0 - local IPF="" - - if [ $family = "inet" ];then - IPF="ip" - fi - -ip netns exec "$ns0" nft -f /dev/stdin <<EOF 2>/dev/null -table $family nat { - chain output { - type nat hook output priority 0; policy accept; - ip daddr 10.0.1.99 dnat $IPF to 10.0.2.99 - } -} -EOF - if [ $? -ne 0 ]; then - if [ $family = "inet" ];then - echo "SKIP: inet nat tests" - test_inet_nat=false - return $ksft_skip - fi - echo "SKIP: Could not add add $family dnat hook" - return $ksft_skip - fi - - # ping netns1, expect rewrite to netns2 - ip netns exec "$ns0" ping -q -c 1 10.0.1.99 > /dev/null - if [ $? -ne 0 ]; then - lret=1 - echo "ERROR: ping failed" - return $lret - fi - - expect="packets 0 bytes 0" - for dir in "in" "out" ; do - cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns0" ns1$dir "$expect" "test_local_dnat 1" - lret=1 - fi - done - - expect="packets 1 bytes 84" - for dir in "in" "out" ; do - cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns0" ns2$dir "$expect" "test_local_dnat 2" - lret=1 - fi - done - - # expect 0 count in ns1 - expect="packets 0 bytes 0" - for dir in "in" "out" ; do - cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns1" ns0$dir "$expect" "test_local_dnat 3" - lret=1 - fi - done - - # expect 1 packet in ns2 - expect="packets 1 bytes 84" - for dir in "in" "out" ; do - cnt=$(ip netns exec "$ns2" nft list counter inet filter ns0${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns2" ns0$dir "$expect" "test_local_dnat 4" - lret=1 - fi - done - - test $lret -eq 0 && echo "PASS: ping to $ns1 was $family NATted to $ns2" - - ip netns exec "$ns0" nft flush chain $family nat output - - reset_counters - ip netns exec "$ns0" ping -q -c 1 10.0.1.99 > /dev/null - if [ $? -ne 0 ]; then - lret=1 - echo "ERROR: ping failed" - return $lret - fi - - expect="packets 1 bytes 84" - for dir in "in" "out" ; do - cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns1" ns1$dir "$expect" "test_local_dnat 5" - lret=1 - fi - done - expect="packets 0 bytes 0" - for dir in "in" "out" ; do - cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns0" ns2$dir "$expect" "test_local_dnat 6" - lret=1 - fi - done - - # expect 1 count in ns1 - expect="packets 1 bytes 84" - for dir in "in" "out" ; do - cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns0" ns0$dir "$expect" "test_local_dnat 7" - lret=1 - fi - done - - # expect 0 packet in ns2 - expect="packets 0 bytes 0" - for dir in "in" "out" ; do - cnt=$(ip netns exec "$ns2" nft list counter inet filter ns0${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns2" ns0$dir "$expect" "test_local_dnat 8" - lret=1 - fi - done - - test $lret -eq 0 && echo "PASS: ping to $ns1 OK after $family nat output chain flush" - - return $lret -} - -test_local_dnat_portonly() -{ - local family=$1 - local daddr=$2 - local lret=0 - local sr_s - local sr_r - -ip netns exec "$ns0" nft -f /dev/stdin <<EOF -table $family nat { - chain output { - type nat hook output priority 0; policy accept; - meta l4proto tcp dnat to :2000 - - } -} -EOF - if [ $? -ne 0 ]; then - if [ $family = "inet" ];then - echo "SKIP: inet port test" - test_inet_nat=false - return - fi - echo "SKIP: Could not add $family dnat hook" - return - fi - - echo SERVER-$family | ip netns exec "$ns1" timeout 5 socat -u STDIN TCP-LISTEN:2000 & - sc_s=$! - - sleep 1 - - result=$(ip netns exec "$ns0" timeout 1 socat TCP:$daddr:2000 STDOUT) - - if [ "$result" = "SERVER-inet" ];then - echo "PASS: inet port rewrite without l3 address" - else - echo "ERROR: inet port rewrite" - ret=1 - fi -} - -test_masquerade6() -{ - local family=$1 - local natflags=$2 - local lret=0 - - ip netns exec "$ns0" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null - - ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 - if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping $ns1 from $ns2 via ipv6" - return 1 - lret=1 - fi - - expect="packets 1 bytes 104" - for dir in "in6" "out6" ; do - cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns1" ns2$dir "$expect" "test_masquerade6 1" - lret=1 - fi - - cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns2" ns1$dir "$expect" "test_masquerade6 2" - lret=1 - fi - done - - reset_counters - -# add masquerading rule -ip netns exec "$ns0" nft -f /dev/stdin <<EOF -table $family nat { - chain postrouting { - type nat hook postrouting priority 0; policy accept; - meta oif veth0 masquerade $natflags - } -} -EOF - if [ $? -ne 0 ]; then - echo "SKIP: Could not add add $family masquerade hook" - return $ksft_skip - fi - - ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 - if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping $ns1 from $ns2 with active $family masquerade $natflags" - lret=1 - fi - - # ns1 should have seen packets from ns0, due to masquerade - expect="packets 1 bytes 104" - for dir in "in6" "out6" ; do - cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns1" ns0$dir "$expect" "test_masquerade6 3" - lret=1 - fi - - cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns2" ns1$dir "$expect" "test_masquerade6 4" - lret=1 - fi - done - - # ns1 should not have seen packets from ns2, due to masquerade - expect="packets 0 bytes 0" - for dir in "in6" "out6" ; do - cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns1" ns0$dir "$expect" "test_masquerade6 5" - lret=1 - fi - - cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns0" ns1$dir "$expect" "test_masquerade6 6" - lret=1 - fi - done - - ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 - if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping $ns1 from $ns2 with active ipv6 masquerade $natflags (attempt 2)" - lret=1 - fi - - ip netns exec "$ns0" nft flush chain $family nat postrouting - if [ $? -ne 0 ]; then - echo "ERROR: Could not flush $family nat postrouting" 1>&2 - lret=1 - fi - - test $lret -eq 0 && echo "PASS: $family IPv6 masquerade $natflags for $ns2" - - return $lret -} - -test_masquerade() -{ - local family=$1 - local natflags=$2 - local lret=0 - - ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null - ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null - - ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 - if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping $ns1 from "$ns2" $natflags" - lret=1 - fi - - expect="packets 1 bytes 84" - for dir in "in" "out" ; do - cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns1" ns2$dir "$expect" "test_masquerade 1" - lret=1 - fi - - cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns2" ns1$dir "$expect" "test_masquerade 2" - lret=1 - fi - done - - reset_counters - -# add masquerading rule -ip netns exec "$ns0" nft -f /dev/stdin <<EOF -table $family nat { - chain postrouting { - type nat hook postrouting priority 0; policy accept; - meta oif veth0 masquerade $natflags - } -} -EOF - if [ $? -ne 0 ]; then - echo "SKIP: Could not add add $family masquerade hook" - return $ksft_skip - fi - - ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 - if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping $ns1 from $ns2 with active $family masquerade $natflags" - lret=1 - fi - - # ns1 should have seen packets from ns0, due to masquerade - expect="packets 1 bytes 84" - for dir in "in" "out" ; do - cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns1" ns0$dir "$expect" "test_masquerade 3" - lret=1 - fi - - cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns2" ns1$dir "$expect" "test_masquerade 4" - lret=1 - fi - done - - # ns1 should not have seen packets from ns2, due to masquerade - expect="packets 0 bytes 0" - for dir in "in" "out" ; do - cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns1" ns0$dir "$expect" "test_masquerade 5" - lret=1 - fi - - cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns0" ns1$dir "$expect" "test_masquerade 6" - lret=1 - fi - done - - ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 - if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping $ns1 from $ns2 with active ip masquerade $natflags (attempt 2)" - lret=1 - fi - - ip netns exec "$ns0" nft flush chain $family nat postrouting - if [ $? -ne 0 ]; then - echo "ERROR: Could not flush $family nat postrouting" 1>&2 - lret=1 - fi - - test $lret -eq 0 && echo "PASS: $family IP masquerade $natflags for $ns2" - - return $lret -} - -test_redirect6() -{ - local family=$1 - local lret=0 - - ip netns exec "$ns0" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null - - ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 - if [ $? -ne 0 ] ; then - echo "ERROR: cannnot ping $ns1 from $ns2 via ipv6" - lret=1 - fi - - expect="packets 1 bytes 104" - for dir in "in6" "out6" ; do - cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns1" ns2$dir "$expect" "test_redirect6 1" - lret=1 - fi - - cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns2" ns1$dir "$expect" "test_redirect6 2" - lret=1 - fi - done - - reset_counters - -# add redirect rule -ip netns exec "$ns0" nft -f /dev/stdin <<EOF -table $family nat { - chain prerouting { - type nat hook prerouting priority 0; policy accept; - meta iif veth1 meta l4proto icmpv6 ip6 saddr dead:2::99 ip6 daddr dead:1::99 redirect - } -} -EOF - if [ $? -ne 0 ]; then - echo "SKIP: Could not add add $family redirect hook" - return $ksft_skip - fi - - ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 - if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping $ns1 from $ns2 via ipv6 with active $family redirect" - lret=1 - fi - - # ns1 should have seen no packets from ns2, due to redirection - expect="packets 0 bytes 0" - for dir in "in6" "out6" ; do - cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns1" ns0$dir "$expect" "test_redirect6 3" - lret=1 - fi - done - - # ns0 should have seen packets from ns2, due to masquerade - expect="packets 1 bytes 104" - for dir in "in6" "out6" ; do - cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns1" ns0$dir "$expect" "test_redirect6 4" - lret=1 - fi - done - - ip netns exec "$ns0" nft delete table $family nat - if [ $? -ne 0 ]; then - echo "ERROR: Could not delete $family nat table" 1>&2 - lret=1 - fi - - test $lret -eq 0 && echo "PASS: $family IPv6 redirection for $ns2" - - return $lret -} - -test_redirect() -{ - local family=$1 - local lret=0 - - ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null - ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null - - ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 - if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping $ns1 from $ns2" - lret=1 - fi - - expect="packets 1 bytes 84" - for dir in "in" "out" ; do - cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns1" $ns2$dir "$expect" "test_redirect 1" - lret=1 - fi - - cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns2" ns1$dir "$expect" "test_redirect 2" - lret=1 - fi - done - - reset_counters - -# add redirect rule -ip netns exec "$ns0" nft -f /dev/stdin <<EOF -table $family nat { - chain prerouting { - type nat hook prerouting priority 0; policy accept; - meta iif veth1 ip protocol icmp ip saddr 10.0.2.99 ip daddr 10.0.1.99 redirect - } -} -EOF - if [ $? -ne 0 ]; then - echo "SKIP: Could not add add $family redirect hook" - return $ksft_skip - fi - - ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 - if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping $ns1 from $ns2 with active $family ip redirect" - lret=1 - fi - - # ns1 should have seen no packets from ns2, due to redirection - expect="packets 0 bytes 0" - for dir in "in" "out" ; do - - cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns1" ns0$dir "$expect" "test_redirect 3" - lret=1 - fi - done - - # ns0 should have seen packets from ns2, due to masquerade - expect="packets 1 bytes 84" - for dir in "in" "out" ; do - cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns0" ns0$dir "$expect" "test_redirect 4" - lret=1 - fi - done - - ip netns exec "$ns0" nft delete table $family nat - if [ $? -ne 0 ]; then - echo "ERROR: Could not delete $family nat table" 1>&2 - lret=1 - fi - - test $lret -eq 0 && echo "PASS: $family IP redirection for $ns2" - - return $lret -} - -# test port shadowing. -# create two listening services, one on router (ns0), one -# on client (ns2), which is masqueraded from ns1 point of view. -# ns2 sends udp packet coming from service port to ns1, on a highport. -# Later, if n1 uses same highport to connect to ns0:service, packet -# might be port-forwarded to ns2 instead. - -# second argument tells if we expect the 'fake-entry' to take effect -# (CLIENT) or not (ROUTER). -test_port_shadow() -{ - local test=$1 - local expect=$2 - local daddrc="10.0.1.99" - local daddrs="10.0.1.1" - local result="" - local logmsg="" - - # make shadow entry, from client (ns2), going to (ns1), port 41404, sport 1405. - echo "fake-entry" | ip netns exec "$ns2" timeout 1 socat -u STDIN UDP:"$daddrc":41404,sourceport=1405 - - echo ROUTER | ip netns exec "$ns0" timeout 5 socat -u STDIN UDP4-LISTEN:1405 & - sc_r=$! - - echo CLIENT | ip netns exec "$ns2" timeout 5 socat -u STDIN UDP4-LISTEN:1405,reuseport & - sc_c=$! - - sleep 0.3 - - # ns1 tries to connect to ns0:1405. With default settings this should connect - # to client, it matches the conntrack entry created above. - - result=$(echo "data" | ip netns exec "$ns1" timeout 1 socat - UDP:"$daddrs":1405,sourceport=41404) - - if [ "$result" = "$expect" ] ;then - echo "PASS: portshadow test $test: got reply from ${expect}${logmsg}" - else - echo "ERROR: portshadow test $test: got reply from \"$result\", not $expect as intended" - ret=1 - fi - - kill $sc_r $sc_c 2>/dev/null - - # flush udp entries for next test round, if any - ip netns exec "$ns0" conntrack -F >/dev/null 2>&1 -} - -# This prevents port shadow of router service via packet filter, -# packets claiming to originate from service port from internal -# network are dropped. -test_port_shadow_filter() -{ - local family=$1 - -ip netns exec "$ns0" nft -f /dev/stdin <<EOF -table $family filter { - chain forward { - type filter hook forward priority 0; policy accept; - meta iif veth1 udp sport 1405 drop - } -} -EOF - test_port_shadow "port-filter" "ROUTER" - - ip netns exec "$ns0" nft delete table $family filter -} - -# This prevents port shadow of router service via notrack. -test_port_shadow_notrack() -{ - local family=$1 - -ip netns exec "$ns0" nft -f /dev/stdin <<EOF -table $family raw { - chain prerouting { - type filter hook prerouting priority -300; policy accept; - meta iif veth0 udp dport 1405 notrack - } - chain output { - type filter hook output priority -300; policy accept; - meta oif veth0 udp sport 1405 notrack - } -} -EOF - test_port_shadow "port-notrack" "ROUTER" - - ip netns exec "$ns0" nft delete table $family raw -} - -# This prevents port shadow of router service via sport remap. -test_port_shadow_pat() -{ - local family=$1 - -ip netns exec "$ns0" nft -f /dev/stdin <<EOF -table $family pat { - chain postrouting { - type nat hook postrouting priority -1; policy accept; - meta iif veth1 udp sport <= 1405 masquerade to : 1406-65535 random - } -} -EOF - test_port_shadow "pat" "ROUTER" - - ip netns exec "$ns0" nft delete table $family pat -} - -test_port_shadowing() -{ - local family="ip" - - conntrack -h >/dev/null 2>&1 - if [ $? -ne 0 ];then - echo "SKIP: Could not run nat port shadowing test without conntrack tool" - return - fi - - socat -h > /dev/null 2>&1 - if [ $? -ne 0 ];then - echo "SKIP: Could not run nat port shadowing test without socat tool" - return - fi - - ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null - ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null - - ip netns exec "$ns0" nft -f /dev/stdin <<EOF -table $family nat { - chain postrouting { - type nat hook postrouting priority 0; policy accept; - meta oif veth0 masquerade - } -} -EOF - if [ $? -ne 0 ]; then - echo "SKIP: Could not add add $family masquerade hook" - return $ksft_skip - fi - - # test default behaviour. Packet from ns1 to ns0 is redirected to ns2. - test_port_shadow "default" "CLIENT" - - # test packet filter based mitigation: prevent forwarding of - # packets claiming to come from the service port. - test_port_shadow_filter "$family" - - # test conntrack based mitigation: connections going or coming - # from router:service bypass connection tracking. - test_port_shadow_notrack "$family" - - # test nat based mitigation: fowarded packets coming from service port - # are masqueraded with random highport. - test_port_shadow_pat "$family" - - ip netns exec "$ns0" nft delete table $family nat -} - -test_stateless_nat_ip() -{ - local lret=0 - - ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null - ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null - - ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 - if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping $ns1 from $ns2 before loading stateless rules" - return 1 - fi - -ip netns exec "$ns0" nft -f /dev/stdin <<EOF -table ip stateless { - map xlate_in { - typeof meta iifname . ip saddr . ip daddr : ip daddr - elements = { - "veth1" . 10.0.2.99 . 10.0.1.99 : 10.0.2.2, - } - } - map xlate_out { - typeof meta iifname . ip saddr . ip daddr : ip daddr - elements = { - "veth0" . 10.0.1.99 . 10.0.2.2 : 10.0.2.99 - } - } - - chain prerouting { - type filter hook prerouting priority -400; policy accept; - ip saddr set meta iifname . ip saddr . ip daddr map @xlate_in - ip daddr set meta iifname . ip saddr . ip daddr map @xlate_out - } -} -EOF - if [ $? -ne 0 ]; then - echo "SKIP: Could not add ip statless rules" - return $ksft_skip - fi - - reset_counters - - ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 - if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping $ns1 from $ns2 with stateless rules" - lret=1 - fi - - # ns1 should have seen packets from .2.2, due to stateless rewrite. - expect="packets 1 bytes 84" - cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0insl | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns1" ns0insl "$expect" "test_stateless 1" - lret=1 - fi - - for dir in "in" "out" ; do - cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns2" ns1$dir "$expect" "test_stateless 2" - lret=1 - fi - done - - # ns1 should not have seen packets from ns2, due to masquerade - expect="packets 0 bytes 0" - for dir in "in" "out" ; do - cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns1" ns0$dir "$expect" "test_stateless 3" - lret=1 - fi - - cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns0" ns1$dir "$expect" "test_stateless 4" - lret=1 - fi - done - - reset_counters - - socat -h > /dev/null 2>&1 - if [ $? -ne 0 ];then - echo "SKIP: Could not run stateless nat frag test without socat tool" - if [ $lret -eq 0 ]; then - return $ksft_skip - fi - - ip netns exec "$ns0" nft delete table ip stateless - return $lret - fi - - local tmpfile=$(mktemp) - dd if=/dev/urandom of=$tmpfile bs=4096 count=1 2>/dev/null - - local outfile=$(mktemp) - ip netns exec "$ns1" timeout 3 socat -u UDP4-RECV:4233 OPEN:$outfile < /dev/null & - sc_r=$! - - sleep 1 - # re-do with large ping -> ip fragmentation - ip netns exec "$ns2" timeout 3 socat - UDP4-SENDTO:"10.0.1.99:4233" < "$tmpfile" > /dev/null - if [ $? -ne 0 ] ; then - echo "ERROR: failed to test udp $ns1 to $ns2 with stateless ip nat" 1>&2 - lret=1 - fi - - wait - - cmp "$tmpfile" "$outfile" - if [ $? -ne 0 ]; then - ls -l "$tmpfile" "$outfile" - echo "ERROR: in and output file mismatch when checking udp with stateless nat" 1>&2 - lret=1 - fi - - rm -f "$tmpfile" "$outfile" - - # ns1 should have seen packets from 2.2, due to stateless rewrite. - expect="packets 3 bytes 4164" - cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0insl | grep -q "$expect") - if [ $? -ne 0 ]; then - bad_counter "$ns1" ns0insl "$expect" "test_stateless 5" - lret=1 - fi - - ip netns exec "$ns0" nft delete table ip stateless - if [ $? -ne 0 ]; then - echo "ERROR: Could not delete table ip stateless" 1>&2 - lret=1 - fi - - test $lret -eq 0 && echo "PASS: IP statless for $ns2" - - return $lret -} - -# ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99 -for i in 0 1 2; do -ip netns exec ns$i-$sfx nft -f /dev/stdin <<EOF -table inet filter { - counter ns0in {} - counter ns1in {} - counter ns2in {} - - counter ns0out {} - counter ns1out {} - counter ns2out {} - - counter ns0in6 {} - counter ns1in6 {} - counter ns2in6 {} - - counter ns0out6 {} - counter ns1out6 {} - counter ns2out6 {} - - map nsincounter { - type ipv4_addr : counter - elements = { 10.0.1.1 : "ns0in", - 10.0.2.1 : "ns0in", - 10.0.1.99 : "ns1in", - 10.0.2.99 : "ns2in" } - } - - map nsincounter6 { - type ipv6_addr : counter - elements = { dead:1::1 : "ns0in6", - dead:2::1 : "ns0in6", - dead:1::99 : "ns1in6", - dead:2::99 : "ns2in6" } - } - - map nsoutcounter { - type ipv4_addr : counter - elements = { 10.0.1.1 : "ns0out", - 10.0.2.1 : "ns0out", - 10.0.1.99: "ns1out", - 10.0.2.99: "ns2out" } - } - - map nsoutcounter6 { - type ipv6_addr : counter - elements = { dead:1::1 : "ns0out6", - dead:2::1 : "ns0out6", - dead:1::99 : "ns1out6", - dead:2::99 : "ns2out6" } - } - - chain input { - type filter hook input priority 0; policy accept; - counter name ip saddr map @nsincounter - icmpv6 type { "echo-request", "echo-reply" } counter name ip6 saddr map @nsincounter6 - } - chain output { - type filter hook output priority 0; policy accept; - counter name ip daddr map @nsoutcounter - icmpv6 type { "echo-request", "echo-reply" } counter name ip6 daddr map @nsoutcounter6 - } -} -EOF -done - -# special case for stateless nat check, counter needs to -# be done before (input) ip defragmentation -ip netns exec ns1-$sfx nft -f /dev/stdin <<EOF -table inet filter { - counter ns0insl {} - - chain pre { - type filter hook prerouting priority -400; policy accept; - ip saddr 10.0.2.2 counter name "ns0insl" - } -} -EOF - -sleep 3 -# test basic connectivity -for i in 1 2; do - ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99 > /dev/null - if [ $? -ne 0 ];then - echo "ERROR: Could not reach other namespace(s)" 1>&2 - ret=1 - fi - - ip netns exec "$ns0" ping -c 1 -q dead:$i::99 > /dev/null - if [ $? -ne 0 ];then - echo "ERROR: Could not reach other namespace(s) via ipv6" 1>&2 - ret=1 - fi - check_counters ns$i-$sfx - if [ $? -ne 0 ]; then - ret=1 - fi - - check_ns0_counters ns$i - if [ $? -ne 0 ]; then - ret=1 - fi - reset_counters -done - -if [ $ret -eq 0 ];then - echo "PASS: netns routing/connectivity: $ns0 can reach $ns1 and $ns2" -fi - -reset_counters -test_local_dnat ip -test_local_dnat6 ip6 - -reset_counters -test_local_dnat_portonly inet 10.0.1.99 - -reset_counters -$test_inet_nat && test_local_dnat inet -$test_inet_nat && test_local_dnat6 inet - -for flags in "" "fully-random"; do -reset_counters -test_masquerade ip $flags -test_masquerade6 ip6 $flags -reset_counters -$test_inet_nat && test_masquerade inet $flags -$test_inet_nat && test_masquerade6 inet $flags -done - -reset_counters -test_redirect ip -test_redirect6 ip6 -reset_counters -$test_inet_nat && test_redirect inet -$test_inet_nat && test_redirect6 inet - -test_port_shadowing -test_stateless_nat_ip - -if [ $ret -ne 0 ];then - echo -n "FAIL: " - nft --version -fi - -exit $ret |