3 # This test is for basic NAT functionality: snat, dnat, redirect, masquerade.
6 # Kselftest framework requirement - SKIP code is 4.
13 for i in 0 1 2; do ip netns del ns$i;done
16 nft --version > /dev/null 2>&1
18 echo "SKIP: Could not run test without nft tool"
22 ip -Version > /dev/null 2>&1
24 echo "SKIP: Could not run test without ip tool"
30 echo "SKIP: Could not create net namespace"
39 ip link add veth0 netns ns0 type veth peer name eth0 netns ns1
40 ip link add veth1 netns ns0 type veth peer name eth0 netns ns2
42 ip -net ns0 link set lo up
43 ip -net ns0 link set veth0 up
44 ip -net ns0 addr add 10.0.1.1/24 dev veth0
45 ip -net ns0 addr add dead:1::1/64 dev veth0
47 ip -net ns0 link set veth1 up
48 ip -net ns0 addr add 10.0.2.1/24 dev veth1
49 ip -net ns0 addr add dead:2::1/64 dev veth1
52 ip -net ns$i link set lo up
53 ip -net ns$i link set eth0 up
54 ip -net ns$i addr add 10.0.$i.99/24 dev eth0
55 ip -net ns$i route add default via 10.0.$i.1
56 ip -net ns$i addr add dead:$i::99/64 dev eth0
57 ip -net ns$i route add default via dead:$i::1
66 echo "ERROR: $counter counter in $ns has unexpected value (expected $expect)" 1>&2
67 ip netns exec $ns nft list counter inet filter $counter 1>&2
75 cnt=$(ip netns exec $ns nft list counter inet filter ns0in | grep -q "packets 1 bytes 84")
77 bad_counter $ns ns0in "packets 1 bytes 84"
80 cnt=$(ip netns exec $ns nft list counter inet filter ns0out | grep -q "packets 1 bytes 84")
82 bad_counter $ns ns0out "packets 1 bytes 84"
86 expect="packets 1 bytes 104"
87 cnt=$(ip netns exec $ns nft list counter inet filter ns0in6 | grep -q "$expect")
89 bad_counter $ns ns0in6 "$expect"
92 cnt=$(ip netns exec $ns nft list counter inet filter ns0out6 | grep -q "$expect")
94 bad_counter $ns ns0out6 "$expect"
106 cnt=$(ip netns exec ns0 nft list counter inet filter ns0in | grep -q "packets 0 bytes 0")
107 if [ $? -ne 0 ]; then
108 bad_counter ns0 ns0in "packets 0 bytes 0"
112 cnt=$(ip netns exec ns0 nft list counter inet filter ns0in6 | grep -q "packets 0 bytes 0")
113 if [ $? -ne 0 ]; then
114 bad_counter ns0 ns0in6 "packets 0 bytes 0"
118 cnt=$(ip netns exec ns0 nft list counter inet filter ns0out | grep -q "packets 0 bytes 0")
119 if [ $? -ne 0 ]; then
120 bad_counter ns0 ns0out "packets 0 bytes 0"
123 cnt=$(ip netns exec ns0 nft list counter inet filter ns0out6 | grep -q "packets 0 bytes 0")
124 if [ $? -ne 0 ]; then
125 bad_counter ns0 ns0out6 "packets 0 bytes 0"
129 for dir in "in" "out" ; do
130 expect="packets 1 bytes 84"
131 cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir} | grep -q "$expect")
132 if [ $? -ne 0 ]; then
133 bad_counter ns0 $ns$dir "$expect"
137 expect="packets 1 bytes 104"
138 cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir}6 | grep -q "$expect")
139 if [ $? -ne 0 ]; then
140 bad_counter ns0 $ns$dir6 "$expect"
151 ip netns exec ns$i nft reset counters inet > /dev/null
161 if [ $family = "inet" ];then
165 ip netns exec ns0 nft -f - <<EOF
168 type nat hook output priority 0; policy accept;
169 ip6 daddr dead:1::99 dnat $IPF to dead:2::99
173 if [ $? -ne 0 ]; then
174 echo "SKIP: Could not add add $family dnat hook"
178 # ping netns1, expect rewrite to netns2
179 ip netns exec ns0 ping -q -c 1 dead:1::99 > /dev/null
180 if [ $? -ne 0 ]; then
182 echo "ERROR: ping6 failed"
186 expect="packets 0 bytes 0"
187 for dir in "in6" "out6" ; do
188 cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
189 if [ $? -ne 0 ]; then
190 bad_counter ns0 ns1$dir "$expect"
195 expect="packets 1 bytes 104"
196 for dir in "in6" "out6" ; do
197 cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
198 if [ $? -ne 0 ]; then
199 bad_counter ns0 ns2$dir "$expect"
204 # expect 0 count in ns1
205 expect="packets 0 bytes 0"
206 for dir in "in6" "out6" ; do
207 cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
208 if [ $? -ne 0 ]; then
209 bad_counter ns1 ns0$dir "$expect"
214 # expect 1 packet in ns2
215 expect="packets 1 bytes 104"
216 for dir in "in6" "out6" ; do
217 cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
218 if [ $? -ne 0 ]; then
219 bad_counter ns2 ns0$dir "$expect"
224 test $lret -eq 0 && echo "PASS: ipv6 ping to ns1 was $family NATted to ns2"
225 ip netns exec ns0 nft flush chain ip6 nat output
236 if [ $family = "inet" ];then
240 ip netns exec ns0 nft -f - <<EOF 2>/dev/null
243 type nat hook output priority 0; policy accept;
244 ip daddr 10.0.1.99 dnat $IPF to 10.0.2.99
248 if [ $? -ne 0 ]; then
249 if [ $family = "inet" ];then
250 echo "SKIP: inet nat tests"
254 echo "SKIP: Could not add add $family dnat hook"
258 # ping netns1, expect rewrite to netns2
259 ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null
260 if [ $? -ne 0 ]; then
262 echo "ERROR: ping failed"
266 expect="packets 0 bytes 0"
267 for dir in "in" "out" ; do
268 cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
269 if [ $? -ne 0 ]; then
270 bad_counter ns0 ns1$dir "$expect"
275 expect="packets 1 bytes 84"
276 for dir in "in" "out" ; do
277 cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
278 if [ $? -ne 0 ]; then
279 bad_counter ns0 ns2$dir "$expect"
284 # expect 0 count in ns1
285 expect="packets 0 bytes 0"
286 for dir in "in" "out" ; do
287 cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
288 if [ $? -ne 0 ]; then
289 bad_counter ns1 ns0$dir "$expect"
294 # expect 1 packet in ns2
295 expect="packets 1 bytes 84"
296 for dir in "in" "out" ; do
297 cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
298 if [ $? -ne 0 ]; then
299 bad_counter ns2 ns0$dir "$expect"
304 test $lret -eq 0 && echo "PASS: ping to ns1 was $family NATted to ns2"
306 ip netns exec ns0 nft flush chain $family nat output
309 ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null
310 if [ $? -ne 0 ]; then
312 echo "ERROR: ping failed"
316 expect="packets 1 bytes 84"
317 for dir in "in" "out" ; do
318 cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
319 if [ $? -ne 0 ]; then
320 bad_counter ns1 ns1$dir "$expect"
324 expect="packets 0 bytes 0"
325 for dir in "in" "out" ; do
326 cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
327 if [ $? -ne 0 ]; then
328 bad_counter ns0 ns2$dir "$expect"
333 # expect 1 count in ns1
334 expect="packets 1 bytes 84"
335 for dir in "in" "out" ; do
336 cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
337 if [ $? -ne 0 ]; then
338 bad_counter ns0 ns0$dir "$expect"
343 # expect 0 packet in ns2
344 expect="packets 0 bytes 0"
345 for dir in "in" "out" ; do
346 cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
347 if [ $? -ne 0 ]; then
348 bad_counter ns2 ns2$dir "$expect"
353 test $lret -eq 0 && echo "PASS: ping to ns1 OK after $family nat output chain flush"
365 ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
367 ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
368 if [ $? -ne 0 ] ; then
369 echo "ERROR: cannot ping ns1 from ns2 via ipv6"
374 expect="packets 1 bytes 104"
375 for dir in "in6" "out6" ; do
376 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
377 if [ $? -ne 0 ]; then
378 bad_counter ns1 ns2$dir "$expect"
382 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
383 if [ $? -ne 0 ]; then
384 bad_counter ns2 ns1$dir "$expect"
391 # add masquerading rule
392 ip netns exec ns0 nft -f - <<EOF
395 type nat hook postrouting priority 0; policy accept;
396 meta oif veth0 masquerade $natflags
400 if [ $? -ne 0 ]; then
401 echo "SKIP: Could not add add $family masquerade hook"
405 ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
406 if [ $? -ne 0 ] ; then
407 echo "ERROR: cannot ping ns1 from ns2 with active $family masquerade $natflags"
411 # ns1 should have seen packets from ns0, due to masquerade
412 expect="packets 1 bytes 104"
413 for dir in "in6" "out6" ; do
414 cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
415 if [ $? -ne 0 ]; then
416 bad_counter ns1 ns0$dir "$expect"
420 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
421 if [ $? -ne 0 ]; then
422 bad_counter ns2 ns1$dir "$expect"
427 # ns1 should not have seen packets from ns2, due to masquerade
428 expect="packets 0 bytes 0"
429 for dir in "in6" "out6" ; do
430 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
431 if [ $? -ne 0 ]; then
432 bad_counter ns1 ns0$dir "$expect"
436 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
437 if [ $? -ne 0 ]; then
438 bad_counter ns2 ns1$dir "$expect"
443 ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
444 if [ $? -ne 0 ] ; then
445 echo "ERROR: cannot ping ns1 from ns2 with active ipv6 masquerade $natflags (attempt 2)"
449 ip netns exec ns0 nft flush chain $family nat postrouting
450 if [ $? -ne 0 ]; then
451 echo "ERROR: Could not flush $family nat postrouting" 1>&2
455 test $lret -eq 0 && echo "PASS: $family IPv6 masquerade $natflags for ns2"
466 ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
467 ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
469 ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
470 if [ $? -ne 0 ] ; then
471 echo "ERROR: cannot ping ns1 from ns2 $natflags"
475 expect="packets 1 bytes 84"
476 for dir in "in" "out" ; do
477 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
478 if [ $? -ne 0 ]; then
479 bad_counter ns1 ns2$dir "$expect"
483 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
484 if [ $? -ne 0 ]; then
485 bad_counter ns2 ns1$dir "$expect"
492 # add masquerading rule
493 ip netns exec ns0 nft -f - <<EOF
496 type nat hook postrouting priority 0; policy accept;
497 meta oif veth0 masquerade $natflags
501 if [ $? -ne 0 ]; then
502 echo "SKIP: Could not add add $family masquerade hook"
506 ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
507 if [ $? -ne 0 ] ; then
508 echo "ERROR: cannot ping ns1 from ns2 with active $family masquerade $natflags"
512 # ns1 should have seen packets from ns0, due to masquerade
513 expect="packets 1 bytes 84"
514 for dir in "in" "out" ; do
515 cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
516 if [ $? -ne 0 ]; then
517 bad_counter ns1 ns0$dir "$expect"
521 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
522 if [ $? -ne 0 ]; then
523 bad_counter ns2 ns1$dir "$expect"
528 # ns1 should not have seen packets from ns2, due to masquerade
529 expect="packets 0 bytes 0"
530 for dir in "in" "out" ; do
531 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
532 if [ $? -ne 0 ]; then
533 bad_counter ns1 ns0$dir "$expect"
537 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
538 if [ $? -ne 0 ]; then
539 bad_counter ns2 ns1$dir "$expect"
544 ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
545 if [ $? -ne 0 ] ; then
546 echo "ERROR: cannot ping ns1 from ns2 with active ip masquerade $natflags (attempt 2)"
550 ip netns exec ns0 nft flush chain $family nat postrouting
551 if [ $? -ne 0 ]; then
552 echo "ERROR: Could not flush $family nat postrouting" 1>&2
556 test $lret -eq 0 && echo "PASS: $family IP masquerade $natflags for ns2"
566 ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
568 ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
569 if [ $? -ne 0 ] ; then
570 echo "ERROR: cannnot ping ns1 from ns2 via ipv6"
574 expect="packets 1 bytes 104"
575 for dir in "in6" "out6" ; do
576 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
577 if [ $? -ne 0 ]; then
578 bad_counter ns1 ns2$dir "$expect"
582 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
583 if [ $? -ne 0 ]; then
584 bad_counter ns2 ns1$dir "$expect"
592 ip netns exec ns0 nft -f - <<EOF
595 type nat hook prerouting priority 0; policy accept;
596 meta iif veth1 meta l4proto icmpv6 ip6 saddr dead:2::99 ip6 daddr dead:1::99 redirect
600 if [ $? -ne 0 ]; then
601 echo "SKIP: Could not add add $family redirect hook"
605 ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
606 if [ $? -ne 0 ] ; then
607 echo "ERROR: cannot ping ns1 from ns2 via ipv6 with active $family redirect"
611 # ns1 should have seen no packets from ns2, due to redirection
612 expect="packets 0 bytes 0"
613 for dir in "in6" "out6" ; do
614 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
615 if [ $? -ne 0 ]; then
616 bad_counter ns1 ns0$dir "$expect"
621 # ns0 should have seen packets from ns2, due to masquerade
622 expect="packets 1 bytes 104"
623 for dir in "in6" "out6" ; do
624 cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
625 if [ $? -ne 0 ]; then
626 bad_counter ns1 ns0$dir "$expect"
631 ip netns exec ns0 nft delete table $family nat
632 if [ $? -ne 0 ]; then
633 echo "ERROR: Could not delete $family nat table" 1>&2
637 test $lret -eq 0 && echo "PASS: $family IPv6 redirection for ns2"
647 ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
648 ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
650 ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
651 if [ $? -ne 0 ] ; then
652 echo "ERROR: cannot ping ns1 from ns2"
656 expect="packets 1 bytes 84"
657 for dir in "in" "out" ; do
658 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
659 if [ $? -ne 0 ]; then
660 bad_counter ns1 ns2$dir "$expect"
664 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
665 if [ $? -ne 0 ]; then
666 bad_counter ns2 ns1$dir "$expect"
674 ip netns exec ns0 nft -f - <<EOF
677 type nat hook prerouting priority 0; policy accept;
678 meta iif veth1 ip protocol icmp ip saddr 10.0.2.99 ip daddr 10.0.1.99 redirect
682 if [ $? -ne 0 ]; then
683 echo "SKIP: Could not add add $family redirect hook"
687 ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
688 if [ $? -ne 0 ] ; then
689 echo "ERROR: cannot ping ns1 from ns2 with active $family ip redirect"
693 # ns1 should have seen no packets from ns2, due to redirection
694 expect="packets 0 bytes 0"
695 for dir in "in" "out" ; do
697 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
698 if [ $? -ne 0 ]; then
699 bad_counter ns1 ns0$dir "$expect"
704 # ns0 should have seen packets from ns2, due to masquerade
705 expect="packets 1 bytes 84"
706 for dir in "in" "out" ; do
707 cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
708 if [ $? -ne 0 ]; then
709 bad_counter ns1 ns0$dir "$expect"
714 ip netns exec ns0 nft delete table $family nat
715 if [ $? -ne 0 ]; then
716 echo "ERROR: Could not delete $family nat table" 1>&2
720 test $lret -eq 0 && echo "PASS: $family IP redirection for ns2"
726 # ip netns exec ns0 ping -c 1 -q 10.0.$i.99
728 ip netns exec ns$i nft -f - <<EOF
747 type ipv4_addr : counter
748 elements = { 10.0.1.1 : "ns0in",
751 10.0.2.99 : "ns2in" }
755 type ipv6_addr : counter
756 elements = { dead:1::1 : "ns0in6",
757 dead:2::1 : "ns0in6",
758 dead:1::99 : "ns1in6",
759 dead:2::99 : "ns2in6" }
763 type ipv4_addr : counter
764 elements = { 10.0.1.1 : "ns0out",
767 10.0.2.99: "ns2out" }
771 type ipv6_addr : counter
772 elements = { dead:1::1 : "ns0out6",
773 dead:2::1 : "ns0out6",
774 dead:1::99 : "ns1out6",
775 dead:2::99 : "ns2out6" }
779 type filter hook input priority 0; policy accept;
780 counter name ip saddr map @nsincounter
781 icmpv6 type { "echo-request", "echo-reply" } counter name ip6 saddr map @nsincounter6
784 type filter hook output priority 0; policy accept;
785 counter name ip daddr map @nsoutcounter
786 icmpv6 type { "echo-request", "echo-reply" } counter name ip6 daddr map @nsoutcounter6
793 # test basic connectivity
795 ip netns exec ns0 ping -c 1 -q 10.0.$i.99 > /dev/null
797 echo "ERROR: Could not reach other namespace(s)" 1>&2
801 ip netns exec ns0 ping -c 1 -q dead:$i::99 > /dev/null
803 echo "ERROR: Could not reach other namespace(s) via ipv6" 1>&2
807 if [ $? -ne 0 ]; then
811 check_ns0_counters ns$i
812 if [ $? -ne 0 ]; then
818 if [ $ret -eq 0 ];then
819 echo "PASS: netns routing/connectivity: ns0 can reach ns1 and ns2"
826 $test_inet_nat && test_local_dnat inet
827 $test_inet_nat && test_local_dnat6 inet
829 for flags in "" "fully-random"; do
831 test_masquerade ip $flags
832 test_masquerade6 ip6 $flags
834 $test_inet_nat && test_masquerade inet $flags
835 $test_inet_nat && test_masquerade6 inet $flags
842 $test_inet_nat && test_redirect inet
843 $test_inet_nat && test_redirect6 inet