3 # This test is for basic NAT functionality: snat, dnat, redirect, masquerade.
6 # Kselftest framework requirement - SKIP code is 4.
11 sfx=$(mktemp -u "XXXXXXXX")
18 for i in 0 1 2; do ip netns del ns$i-"$sfx";done
21 nft --version > /dev/null 2>&1
23 echo "SKIP: Could not run test without nft tool"
27 ip -Version > /dev/null 2>&1
29 echo "SKIP: Could not run test without ip tool"
35 echo "SKIP: Could not create net namespace $ns0"
43 echo "SKIP: Could not create net namespace $ns1"
49 echo "SKIP: Could not create net namespace $ns2"
53 ip link add veth0 netns "$ns0" type veth peer name eth0 netns "$ns1" > /dev/null 2>&1
55 echo "SKIP: No virtual ethernet pair device support in kernel"
58 ip link add veth1 netns "$ns0" type veth peer name eth0 netns "$ns2"
60 ip -net "$ns0" link set lo up
61 ip -net "$ns0" link set veth0 up
62 ip -net "$ns0" addr add 10.0.1.1/24 dev veth0
63 ip -net "$ns0" addr add dead:1::1/64 dev veth0
65 ip -net "$ns0" link set veth1 up
66 ip -net "$ns0" addr add 10.0.2.1/24 dev veth1
67 ip -net "$ns0" addr add dead:2::1/64 dev veth1
70 ip -net ns$i-$sfx link set lo up
71 ip -net ns$i-$sfx link set eth0 up
72 ip -net ns$i-$sfx addr add 10.0.$i.99/24 dev eth0
73 ip -net ns$i-$sfx route add default via 10.0.$i.1
74 ip -net ns$i-$sfx addr add dead:$i::99/64 dev eth0
75 ip -net ns$i-$sfx route add default via dead:$i::1
85 echo "ERROR: $counter counter in $ns has unexpected value (expected $expect) at $tag" 1>&2
86 ip netns exec $ns nft list counter inet filter $counter 1>&2
94 cnt=$(ip netns exec $ns nft list counter inet filter ns0in | grep -q "packets 1 bytes 84")
96 bad_counter $ns ns0in "packets 1 bytes 84" "check_counters 1"
99 cnt=$(ip netns exec $ns nft list counter inet filter ns0out | grep -q "packets 1 bytes 84")
100 if [ $? -ne 0 ]; then
101 bad_counter $ns ns0out "packets 1 bytes 84" "check_counters 2"
105 expect="packets 1 bytes 104"
106 cnt=$(ip netns exec $ns nft list counter inet filter ns0in6 | grep -q "$expect")
107 if [ $? -ne 0 ]; then
108 bad_counter $ns ns0in6 "$expect" "check_counters 3"
111 cnt=$(ip netns exec $ns nft list counter inet filter ns0out6 | grep -q "$expect")
112 if [ $? -ne 0 ]; then
113 bad_counter $ns ns0out6 "$expect" "check_counters 4"
125 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0in | grep -q "packets 0 bytes 0")
126 if [ $? -ne 0 ]; then
127 bad_counter "$ns0" ns0in "packets 0 bytes 0" "check_ns0_counters 1"
131 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0in6 | grep -q "packets 0 bytes 0")
132 if [ $? -ne 0 ]; then
133 bad_counter "$ns0" ns0in6 "packets 0 bytes 0"
137 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0out | grep -q "packets 0 bytes 0")
138 if [ $? -ne 0 ]; then
139 bad_counter "$ns0" ns0out "packets 0 bytes 0" "check_ns0_counters 2"
142 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0out6 | grep -q "packets 0 bytes 0")
143 if [ $? -ne 0 ]; then
144 bad_counter "$ns0" ns0out6 "packets 0 bytes 0" "check_ns0_counters3 "
148 for dir in "in" "out" ; do
149 expect="packets 1 bytes 84"
150 cnt=$(ip netns exec "$ns0" nft list counter inet filter ${ns}${dir} | grep -q "$expect")
151 if [ $? -ne 0 ]; then
152 bad_counter "$ns0" $ns$dir "$expect" "check_ns0_counters 4"
156 expect="packets 1 bytes 104"
157 cnt=$(ip netns exec "$ns0" nft list counter inet filter ${ns}${dir}6 | grep -q "$expect")
158 if [ $? -ne 0 ]; then
159 bad_counter "$ns0" $ns$dir6 "$expect" "check_ns0_counters 5"
170 ip netns exec ns$i-$sfx nft reset counters inet > /dev/null
180 if [ $family = "inet" ];then
184 ip netns exec "$ns0" nft -f /dev/stdin <<EOF
187 type nat hook output priority 0; policy accept;
188 ip6 daddr dead:1::99 dnat $IPF to dead:2::99
192 if [ $? -ne 0 ]; then
193 echo "SKIP: Could not add add $family dnat hook"
197 # ping netns1, expect rewrite to netns2
198 ip netns exec "$ns0" ping -q -c 1 dead:1::99 > /dev/null
199 if [ $? -ne 0 ]; then
201 echo "ERROR: ping6 failed"
205 expect="packets 0 bytes 0"
206 for dir in "in6" "out6" ; do
207 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
208 if [ $? -ne 0 ]; then
209 bad_counter "$ns0" ns1$dir "$expect" "test_local_dnat6 1"
214 expect="packets 1 bytes 104"
215 for dir in "in6" "out6" ; do
216 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect")
217 if [ $? -ne 0 ]; then
218 bad_counter "$ns0" ns2$dir "$expect" "test_local_dnat6 2"
223 # expect 0 count in ns1
224 expect="packets 0 bytes 0"
225 for dir in "in6" "out6" ; do
226 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect")
227 if [ $? -ne 0 ]; then
228 bad_counter "$ns1" ns0$dir "$expect" "test_local_dnat6 3"
233 # expect 1 packet in ns2
234 expect="packets 1 bytes 104"
235 for dir in "in6" "out6" ; do
236 cnt=$(ip netns exec "$ns2" nft list counter inet filter ns0${dir} | grep -q "$expect")
237 if [ $? -ne 0 ]; then
238 bad_counter "$ns2" ns0$dir "$expect" "test_local_dnat6 4"
243 test $lret -eq 0 && echo "PASS: ipv6 ping to $ns1 was $family NATted to $ns2"
244 ip netns exec "$ns0" nft flush chain ip6 nat output
255 if [ $family = "inet" ];then
259 ip netns exec "$ns0" nft -f /dev/stdin <<EOF 2>/dev/null
262 type nat hook output priority 0; policy accept;
263 ip daddr 10.0.1.99 dnat $IPF to 10.0.2.99
267 if [ $? -ne 0 ]; then
268 if [ $family = "inet" ];then
269 echo "SKIP: inet nat tests"
273 echo "SKIP: Could not add add $family dnat hook"
277 # ping netns1, expect rewrite to netns2
278 ip netns exec "$ns0" ping -q -c 1 10.0.1.99 > /dev/null
279 if [ $? -ne 0 ]; then
281 echo "ERROR: ping failed"
285 expect="packets 0 bytes 0"
286 for dir in "in" "out" ; do
287 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
288 if [ $? -ne 0 ]; then
289 bad_counter "$ns0" ns1$dir "$expect" "test_local_dnat 1"
294 expect="packets 1 bytes 84"
295 for dir in "in" "out" ; do
296 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect")
297 if [ $? -ne 0 ]; then
298 bad_counter "$ns0" ns2$dir "$expect" "test_local_dnat 2"
303 # expect 0 count in ns1
304 expect="packets 0 bytes 0"
305 for dir in "in" "out" ; do
306 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect")
307 if [ $? -ne 0 ]; then
308 bad_counter "$ns1" ns0$dir "$expect" "test_local_dnat 3"
313 # expect 1 packet in ns2
314 expect="packets 1 bytes 84"
315 for dir in "in" "out" ; do
316 cnt=$(ip netns exec "$ns2" nft list counter inet filter ns0${dir} | grep -q "$expect")
317 if [ $? -ne 0 ]; then
318 bad_counter "$ns2" ns0$dir "$expect" "test_local_dnat 4"
323 test $lret -eq 0 && echo "PASS: ping to $ns1 was $family NATted to $ns2"
325 ip netns exec "$ns0" nft flush chain $family nat output
328 ip netns exec "$ns0" ping -q -c 1 10.0.1.99 > /dev/null
329 if [ $? -ne 0 ]; then
331 echo "ERROR: ping failed"
335 expect="packets 1 bytes 84"
336 for dir in "in" "out" ; do
337 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
338 if [ $? -ne 0 ]; then
339 bad_counter "$ns1" ns1$dir "$expect" "test_local_dnat 5"
343 expect="packets 0 bytes 0"
344 for dir in "in" "out" ; do
345 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect")
346 if [ $? -ne 0 ]; then
347 bad_counter "$ns0" ns2$dir "$expect" "test_local_dnat 6"
352 # expect 1 count in ns1
353 expect="packets 1 bytes 84"
354 for dir in "in" "out" ; do
355 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect")
356 if [ $? -ne 0 ]; then
357 bad_counter "$ns0" ns0$dir "$expect" "test_local_dnat 7"
362 # expect 0 packet in ns2
363 expect="packets 0 bytes 0"
364 for dir in "in" "out" ; do
365 cnt=$(ip netns exec "$ns2" nft list counter inet filter ns0${dir} | grep -q "$expect")
366 if [ $? -ne 0 ]; then
367 bad_counter "$ns2" ns0$dir "$expect" "test_local_dnat 8"
372 test $lret -eq 0 && echo "PASS: ping to $ns1 OK after $family nat output chain flush"
377 test_local_dnat_portonly()
385 ip netns exec "$ns0" nft -f /dev/stdin <<EOF
388 type nat hook output priority 0; policy accept;
389 meta l4proto tcp dnat to :2000
394 if [ $? -ne 0 ]; then
395 if [ $family = "inet" ];then
396 echo "SKIP: inet port test"
400 echo "SKIP: Could not add $family dnat hook"
404 echo SERVER-$family | ip netns exec "$ns1" timeout 5 socat -u STDIN TCP-LISTEN:2000 &
409 result=$(ip netns exec "$ns0" timeout 1 socat TCP:$daddr:2000 STDOUT)
411 if [ "$result" = "SERVER-inet" ];then
412 echo "PASS: inet port rewrite without l3 address"
414 echo "ERROR: inet port rewrite"
425 ip netns exec "$ns0" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
427 ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
428 if [ $? -ne 0 ] ; then
429 echo "ERROR: cannot ping $ns1 from $ns2 via ipv6"
434 expect="packets 1 bytes 104"
435 for dir in "in6" "out6" ; do
436 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
437 if [ $? -ne 0 ]; then
438 bad_counter "$ns1" ns2$dir "$expect" "test_masquerade6 1"
442 cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
443 if [ $? -ne 0 ]; then
444 bad_counter "$ns2" ns1$dir "$expect" "test_masquerade6 2"
451 # add masquerading rule
452 ip netns exec "$ns0" nft -f /dev/stdin <<EOF
455 type nat hook postrouting priority 0; policy accept;
456 meta oif veth0 masquerade $natflags
460 if [ $? -ne 0 ]; then
461 echo "SKIP: Could not add add $family masquerade hook"
465 ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
466 if [ $? -ne 0 ] ; then
467 echo "ERROR: cannot ping $ns1 from $ns2 with active $family masquerade $natflags"
471 # ns1 should have seen packets from ns0, due to masquerade
472 expect="packets 1 bytes 104"
473 for dir in "in6" "out6" ; do
474 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect")
475 if [ $? -ne 0 ]; then
476 bad_counter "$ns1" ns0$dir "$expect" "test_masquerade6 3"
480 cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
481 if [ $? -ne 0 ]; then
482 bad_counter "$ns2" ns1$dir "$expect" "test_masquerade6 4"
487 # ns1 should not have seen packets from ns2, due to masquerade
488 expect="packets 0 bytes 0"
489 for dir in "in6" "out6" ; do
490 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
491 if [ $? -ne 0 ]; then
492 bad_counter "$ns1" ns0$dir "$expect" "test_masquerade6 5"
496 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
497 if [ $? -ne 0 ]; then
498 bad_counter "$ns0" ns1$dir "$expect" "test_masquerade6 6"
503 ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
504 if [ $? -ne 0 ] ; then
505 echo "ERROR: cannot ping $ns1 from $ns2 with active ipv6 masquerade $natflags (attempt 2)"
509 ip netns exec "$ns0" nft flush chain $family nat postrouting
510 if [ $? -ne 0 ]; then
511 echo "ERROR: Could not flush $family nat postrouting" 1>&2
515 test $lret -eq 0 && echo "PASS: $family IPv6 masquerade $natflags for $ns2"
526 ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
527 ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
529 ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
530 if [ $? -ne 0 ] ; then
531 echo "ERROR: cannot ping $ns1 from "$ns2" $natflags"
535 expect="packets 1 bytes 84"
536 for dir in "in" "out" ; do
537 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
538 if [ $? -ne 0 ]; then
539 bad_counter "$ns1" ns2$dir "$expect" "test_masquerade 1"
543 cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
544 if [ $? -ne 0 ]; then
545 bad_counter "$ns2" ns1$dir "$expect" "test_masquerade 2"
552 # add masquerading rule
553 ip netns exec "$ns0" nft -f /dev/stdin <<EOF
556 type nat hook postrouting priority 0; policy accept;
557 meta oif veth0 masquerade $natflags
561 if [ $? -ne 0 ]; then
562 echo "SKIP: Could not add add $family masquerade hook"
566 ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
567 if [ $? -ne 0 ] ; then
568 echo "ERROR: cannot ping $ns1 from $ns2 with active $family masquerade $natflags"
572 # ns1 should have seen packets from ns0, due to masquerade
573 expect="packets 1 bytes 84"
574 for dir in "in" "out" ; do
575 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect")
576 if [ $? -ne 0 ]; then
577 bad_counter "$ns1" ns0$dir "$expect" "test_masquerade 3"
581 cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
582 if [ $? -ne 0 ]; then
583 bad_counter "$ns2" ns1$dir "$expect" "test_masquerade 4"
588 # ns1 should not have seen packets from ns2, due to masquerade
589 expect="packets 0 bytes 0"
590 for dir in "in" "out" ; do
591 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
592 if [ $? -ne 0 ]; then
593 bad_counter "$ns1" ns0$dir "$expect" "test_masquerade 5"
597 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
598 if [ $? -ne 0 ]; then
599 bad_counter "$ns0" ns1$dir "$expect" "test_masquerade 6"
604 ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
605 if [ $? -ne 0 ] ; then
606 echo "ERROR: cannot ping $ns1 from $ns2 with active ip masquerade $natflags (attempt 2)"
610 ip netns exec "$ns0" nft flush chain $family nat postrouting
611 if [ $? -ne 0 ]; then
612 echo "ERROR: Could not flush $family nat postrouting" 1>&2
616 test $lret -eq 0 && echo "PASS: $family IP masquerade $natflags for $ns2"
626 ip netns exec "$ns0" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
628 ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
629 if [ $? -ne 0 ] ; then
630 echo "ERROR: cannnot ping $ns1 from $ns2 via ipv6"
634 expect="packets 1 bytes 104"
635 for dir in "in6" "out6" ; do
636 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
637 if [ $? -ne 0 ]; then
638 bad_counter "$ns1" ns2$dir "$expect" "test_redirect6 1"
642 cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
643 if [ $? -ne 0 ]; then
644 bad_counter "$ns2" ns1$dir "$expect" "test_redirect6 2"
652 ip netns exec "$ns0" nft -f /dev/stdin <<EOF
655 type nat hook prerouting priority 0; policy accept;
656 meta iif veth1 meta l4proto icmpv6 ip6 saddr dead:2::99 ip6 daddr dead:1::99 redirect
660 if [ $? -ne 0 ]; then
661 echo "SKIP: Could not add add $family redirect hook"
665 ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
666 if [ $? -ne 0 ] ; then
667 echo "ERROR: cannot ping $ns1 from $ns2 via ipv6 with active $family redirect"
671 # ns1 should have seen no packets from ns2, due to redirection
672 expect="packets 0 bytes 0"
673 for dir in "in6" "out6" ; do
674 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
675 if [ $? -ne 0 ]; then
676 bad_counter "$ns1" ns0$dir "$expect" "test_redirect6 3"
681 # ns0 should have seen packets from ns2, due to masquerade
682 expect="packets 1 bytes 104"
683 for dir in "in6" "out6" ; do
684 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect")
685 if [ $? -ne 0 ]; then
686 bad_counter "$ns1" ns0$dir "$expect" "test_redirect6 4"
691 ip netns exec "$ns0" nft delete table $family nat
692 if [ $? -ne 0 ]; then
693 echo "ERROR: Could not delete $family nat table" 1>&2
697 test $lret -eq 0 && echo "PASS: $family IPv6 redirection for $ns2"
707 ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
708 ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
710 ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
711 if [ $? -ne 0 ] ; then
712 echo "ERROR: cannot ping $ns1 from $ns2"
716 expect="packets 1 bytes 84"
717 for dir in "in" "out" ; do
718 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
719 if [ $? -ne 0 ]; then
720 bad_counter "$ns1" $ns2$dir "$expect" "test_redirect 1"
724 cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
725 if [ $? -ne 0 ]; then
726 bad_counter "$ns2" ns1$dir "$expect" "test_redirect 2"
734 ip netns exec "$ns0" nft -f /dev/stdin <<EOF
737 type nat hook prerouting priority 0; policy accept;
738 meta iif veth1 ip protocol icmp ip saddr 10.0.2.99 ip daddr 10.0.1.99 redirect
742 if [ $? -ne 0 ]; then
743 echo "SKIP: Could not add add $family redirect hook"
747 ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
748 if [ $? -ne 0 ] ; then
749 echo "ERROR: cannot ping $ns1 from $ns2 with active $family ip redirect"
753 # ns1 should have seen no packets from ns2, due to redirection
754 expect="packets 0 bytes 0"
755 for dir in "in" "out" ; do
757 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
758 if [ $? -ne 0 ]; then
759 bad_counter "$ns1" ns0$dir "$expect" "test_redirect 3"
764 # ns0 should have seen packets from ns2, due to masquerade
765 expect="packets 1 bytes 84"
766 for dir in "in" "out" ; do
767 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect")
768 if [ $? -ne 0 ]; then
769 bad_counter "$ns0" ns0$dir "$expect" "test_redirect 4"
774 ip netns exec "$ns0" nft delete table $family nat
775 if [ $? -ne 0 ]; then
776 echo "ERROR: Could not delete $family nat table" 1>&2
780 test $lret -eq 0 && echo "PASS: $family IP redirection for $ns2"
785 # test port shadowing.
786 # create two listening services, one on router (ns0), one
787 # on client (ns2), which is masqueraded from ns1 point of view.
788 # ns2 sends udp packet coming from service port to ns1, on a highport.
789 # Later, if n1 uses same highport to connect to ns0:service, packet
790 # might be port-forwarded to ns2 instead.
792 # second argument tells if we expect the 'fake-entry' to take effect
793 # (CLIENT) or not (ROUTER).
798 local daddrc="10.0.1.99"
799 local daddrs="10.0.1.1"
803 # make shadow entry, from client (ns2), going to (ns1), port 41404, sport 1405.
804 echo "fake-entry" | ip netns exec "$ns2" timeout 1 socat -u STDIN UDP:"$daddrc":41404,sourceport=1405
806 echo ROUTER | ip netns exec "$ns0" timeout 5 socat -u STDIN UDP4-LISTEN:1405 &
809 echo CLIENT | ip netns exec "$ns2" timeout 5 socat -u STDIN UDP4-LISTEN:1405,reuseport &
814 # ns1 tries to connect to ns0:1405. With default settings this should connect
815 # to client, it matches the conntrack entry created above.
817 result=$(echo "data" | ip netns exec "$ns1" timeout 1 socat - UDP:"$daddrs":1405,sourceport=41404)
819 if [ "$result" = "$expect" ] ;then
820 echo "PASS: portshadow test $test: got reply from ${expect}${logmsg}"
822 echo "ERROR: portshadow test $test: got reply from \"$result\", not $expect as intended"
826 kill $sc_r $sc_c 2>/dev/null
828 # flush udp entries for next test round, if any
829 ip netns exec "$ns0" conntrack -F >/dev/null 2>&1
832 # This prevents port shadow of router service via packet filter,
833 # packets claiming to originate from service port from internal
834 # network are dropped.
835 test_port_shadow_filter()
839 ip netns exec "$ns0" nft -f /dev/stdin <<EOF
840 table $family filter {
842 type filter hook forward priority 0; policy accept;
843 meta iif veth1 udp sport 1405 drop
847 test_port_shadow "port-filter" "ROUTER"
849 ip netns exec "$ns0" nft delete table $family filter
852 # This prevents port shadow of router service via notrack.
853 test_port_shadow_notrack()
857 ip netns exec "$ns0" nft -f /dev/stdin <<EOF
860 type filter hook prerouting priority -300; policy accept;
861 meta iif veth0 udp dport 1405 notrack
864 type filter hook output priority -300; policy accept;
865 meta oif veth0 udp sport 1405 notrack
869 test_port_shadow "port-notrack" "ROUTER"
871 ip netns exec "$ns0" nft delete table $family raw
874 # This prevents port shadow of router service via sport remap.
875 test_port_shadow_pat()
879 ip netns exec "$ns0" nft -f /dev/stdin <<EOF
882 type nat hook postrouting priority -1; policy accept;
883 meta iif veth1 udp sport <= 1405 masquerade to : 1406-65535 random
887 test_port_shadow "pat" "ROUTER"
889 ip netns exec "$ns0" nft delete table $family pat
892 test_port_shadowing()
896 conntrack -h >/dev/null 2>&1
898 echo "SKIP: Could not run nat port shadowing test without conntrack tool"
902 socat -h > /dev/null 2>&1
904 echo "SKIP: Could not run nat port shadowing test without socat tool"
908 ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
909 ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
911 ip netns exec "$ns0" nft -f /dev/stdin <<EOF
914 type nat hook postrouting priority 0; policy accept;
915 meta oif veth0 masquerade
919 if [ $? -ne 0 ]; then
920 echo "SKIP: Could not add add $family masquerade hook"
924 # test default behaviour. Packet from ns1 to ns0 is redirected to ns2.
925 test_port_shadow "default" "CLIENT"
927 # test packet filter based mitigation: prevent forwarding of
928 # packets claiming to come from the service port.
929 test_port_shadow_filter "$family"
931 # test conntrack based mitigation: connections going or coming
932 # from router:service bypass connection tracking.
933 test_port_shadow_notrack "$family"
935 # test nat based mitigation: fowarded packets coming from service port
936 # are masqueraded with random highport.
937 test_port_shadow_pat "$family"
939 ip netns exec "$ns0" nft delete table $family nat
942 test_stateless_nat_ip()
946 ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
947 ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
949 ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
950 if [ $? -ne 0 ] ; then
951 echo "ERROR: cannot ping $ns1 from $ns2 before loading stateless rules"
955 ip netns exec "$ns0" nft -f /dev/stdin <<EOF
958 typeof meta iifname . ip saddr . ip daddr : ip daddr
960 "veth1" . 10.0.2.99 . 10.0.1.99 : 10.0.2.2,
964 typeof meta iifname . ip saddr . ip daddr : ip daddr
966 "veth0" . 10.0.1.99 . 10.0.2.2 : 10.0.2.99
971 type filter hook prerouting priority -400; policy accept;
972 ip saddr set meta iifname . ip saddr . ip daddr map @xlate_in
973 ip daddr set meta iifname . ip saddr . ip daddr map @xlate_out
977 if [ $? -ne 0 ]; then
978 echo "SKIP: Could not add ip statless rules"
984 ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
985 if [ $? -ne 0 ] ; then
986 echo "ERROR: cannot ping $ns1 from $ns2 with stateless rules"
990 # ns1 should have seen packets from .2.2, due to stateless rewrite.
991 expect="packets 1 bytes 84"
992 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0insl | grep -q "$expect")
993 if [ $? -ne 0 ]; then
994 bad_counter "$ns1" ns0insl "$expect" "test_stateless 1"
998 for dir in "in" "out" ; do
999 cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
1000 if [ $? -ne 0 ]; then
1001 bad_counter "$ns2" ns1$dir "$expect" "test_stateless 2"
1006 # ns1 should not have seen packets from ns2, due to masquerade
1007 expect="packets 0 bytes 0"
1008 for dir in "in" "out" ; do
1009 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
1010 if [ $? -ne 0 ]; then
1011 bad_counter "$ns1" ns0$dir "$expect" "test_stateless 3"
1015 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
1016 if [ $? -ne 0 ]; then
1017 bad_counter "$ns0" ns1$dir "$expect" "test_stateless 4"
1024 socat -h > /dev/null 2>&1
1025 if [ $? -ne 0 ];then
1026 echo "SKIP: Could not run stateless nat frag test without socat tool"
1027 if [ $lret -eq 0 ]; then
1031 ip netns exec "$ns0" nft delete table ip stateless
1035 local tmpfile=$(mktemp)
1036 dd if=/dev/urandom of=$tmpfile bs=4096 count=1 2>/dev/null
1038 local outfile=$(mktemp)
1039 ip netns exec "$ns1" timeout 3 socat -u UDP4-RECV:4233 OPEN:$outfile < /dev/null &
1043 # re-do with large ping -> ip fragmentation
1044 ip netns exec "$ns2" timeout 3 socat - UDP4-SENDTO:"10.0.1.99:4233" < "$tmpfile" > /dev/null
1045 if [ $? -ne 0 ] ; then
1046 echo "ERROR: failed to test udp $ns1 to $ns2 with stateless ip nat" 1>&2
1052 cmp "$tmpfile" "$outfile"
1053 if [ $? -ne 0 ]; then
1054 ls -l "$tmpfile" "$outfile"
1055 echo "ERROR: in and output file mismatch when checking udp with stateless nat" 1>&2
1059 rm -f "$tmpfile" "$outfile"
1061 # ns1 should have seen packets from 2.2, due to stateless rewrite.
1062 expect="packets 3 bytes 4164"
1063 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0insl | grep -q "$expect")
1064 if [ $? -ne 0 ]; then
1065 bad_counter "$ns1" ns0insl "$expect" "test_stateless 5"
1069 ip netns exec "$ns0" nft delete table ip stateless
1070 if [ $? -ne 0 ]; then
1071 echo "ERROR: Could not delete table ip stateless" 1>&2
1075 test $lret -eq 0 && echo "PASS: IP statless for $ns2"
1080 # ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99
1082 ip netns exec ns$i-$sfx nft -f /dev/stdin <<EOF
1101 type ipv4_addr : counter
1102 elements = { 10.0.1.1 : "ns0in",
1104 10.0.1.99 : "ns1in",
1105 10.0.2.99 : "ns2in" }
1109 type ipv6_addr : counter
1110 elements = { dead:1::1 : "ns0in6",
1111 dead:2::1 : "ns0in6",
1112 dead:1::99 : "ns1in6",
1113 dead:2::99 : "ns2in6" }
1117 type ipv4_addr : counter
1118 elements = { 10.0.1.1 : "ns0out",
1119 10.0.2.1 : "ns0out",
1120 10.0.1.99: "ns1out",
1121 10.0.2.99: "ns2out" }
1125 type ipv6_addr : counter
1126 elements = { dead:1::1 : "ns0out6",
1127 dead:2::1 : "ns0out6",
1128 dead:1::99 : "ns1out6",
1129 dead:2::99 : "ns2out6" }
1133 type filter hook input priority 0; policy accept;
1134 counter name ip saddr map @nsincounter
1135 icmpv6 type { "echo-request", "echo-reply" } counter name ip6 saddr map @nsincounter6
1138 type filter hook output priority 0; policy accept;
1139 counter name ip daddr map @nsoutcounter
1140 icmpv6 type { "echo-request", "echo-reply" } counter name ip6 daddr map @nsoutcounter6
1146 # special case for stateless nat check, counter needs to
1147 # be done before (input) ip defragmentation
1148 ip netns exec ns1-$sfx nft -f /dev/stdin <<EOF
1153 type filter hook prerouting priority -400; policy accept;
1154 ip saddr 10.0.2.2 counter name "ns0insl"
1160 # test basic connectivity
1162 ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99 > /dev/null
1163 if [ $? -ne 0 ];then
1164 echo "ERROR: Could not reach other namespace(s)" 1>&2
1168 ip netns exec "$ns0" ping -c 1 -q dead:$i::99 > /dev/null
1169 if [ $? -ne 0 ];then
1170 echo "ERROR: Could not reach other namespace(s) via ipv6" 1>&2
1173 check_counters ns$i-$sfx
1174 if [ $? -ne 0 ]; then
1178 check_ns0_counters ns$i
1179 if [ $? -ne 0 ]; then
1185 if [ $ret -eq 0 ];then
1186 echo "PASS: netns routing/connectivity: $ns0 can reach $ns1 and $ns2"
1191 test_local_dnat6 ip6
1194 test_local_dnat_portonly inet 10.0.1.99
1197 $test_inet_nat && test_local_dnat inet
1198 $test_inet_nat && test_local_dnat6 inet
1200 for flags in "" "fully-random"; do
1202 test_masquerade ip $flags
1203 test_masquerade6 ip6 $flags
1205 $test_inet_nat && test_masquerade inet $flags
1206 $test_inet_nat && test_masquerade6 inet $flags
1213 $test_inet_nat && test_redirect inet
1214 $test_inet_nat && test_redirect6 inet
1217 test_stateless_nat_ip
1219 if [ $ret -ne 0 ];then