3 # This test is for basic NAT functionality: snat, dnat, redirect, masquerade.
6 # Kselftest framework requirement - SKIP code is 4.
10 nft --version > /dev/null 2>&1
12 echo "SKIP: Could not run test without nft tool"
16 ip -Version > /dev/null 2>&1
18 echo "SKIP: Could not run test without ip tool"
26 ip link add veth0 netns ns0 type veth peer name eth0 netns ns1
27 ip link add veth1 netns ns0 type veth peer name eth0 netns ns2
29 ip -net ns0 link set lo up
30 ip -net ns0 link set veth0 up
31 ip -net ns0 addr add 10.0.1.1/24 dev veth0
32 ip -net ns0 addr add dead:1::1/64 dev veth0
34 ip -net ns0 link set veth1 up
35 ip -net ns0 addr add 10.0.2.1/24 dev veth1
36 ip -net ns0 addr add dead:2::1/64 dev veth1
39 ip -net ns$i link set lo up
40 ip -net ns$i link set eth0 up
41 ip -net ns$i addr add 10.0.$i.99/24 dev eth0
42 ip -net ns$i route add default via 10.0.$i.1
43 ip -net ns$i addr add dead:$i::99/64 dev eth0
44 ip -net ns$i route add default via dead:$i::1
53 echo "ERROR: $counter counter in $ns has unexpected value (expected $expect)" 1>&2
54 ip netns exec $ns nft list counter inet filter $counter 1>&2
62 cnt=$(ip netns exec $ns nft list counter inet filter ns0in | grep -q "packets 1 bytes 84")
64 bad_counter $ns ns0in "packets 1 bytes 84"
67 cnt=$(ip netns exec $ns nft list counter inet filter ns0out | grep -q "packets 1 bytes 84")
69 bad_counter $ns ns0out "packets 1 bytes 84"
73 expect="packets 1 bytes 104"
74 cnt=$(ip netns exec $ns nft list counter inet filter ns0in6 | grep -q "$expect")
76 bad_counter $ns ns0in6 "$expect"
79 cnt=$(ip netns exec $ns nft list counter inet filter ns0out6 | grep -q "$expect")
81 bad_counter $ns ns0out6 "$expect"
93 cnt=$(ip netns exec ns0 nft list counter inet filter ns0in | grep -q "packets 0 bytes 0")
95 bad_counter ns0 ns0in "packets 0 bytes 0"
99 cnt=$(ip netns exec ns0 nft list counter inet filter ns0in6 | grep -q "packets 0 bytes 0")
100 if [ $? -ne 0 ]; then
101 bad_counter ns0 ns0in6 "packets 0 bytes 0"
105 cnt=$(ip netns exec ns0 nft list counter inet filter ns0out | grep -q "packets 0 bytes 0")
106 if [ $? -ne 0 ]; then
107 bad_counter ns0 ns0out "packets 0 bytes 0"
110 cnt=$(ip netns exec ns0 nft list counter inet filter ns0out6 | grep -q "packets 0 bytes 0")
111 if [ $? -ne 0 ]; then
112 bad_counter ns0 ns0out6 "packets 0 bytes 0"
116 for dir in "in" "out" ; do
117 expect="packets 1 bytes 84"
118 cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir} | grep -q "$expect")
119 if [ $? -ne 0 ]; then
120 bad_counter ns0 $ns$dir "$expect"
124 expect="packets 1 bytes 104"
125 cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir}6 | grep -q "$expect")
126 if [ $? -ne 0 ]; then
127 bad_counter ns0 $ns$dir6 "$expect"
138 ip netns exec ns$i nft reset counters inet > /dev/null
145 ip netns exec ns0 nft -f - <<EOF
148 type nat hook output priority 0; policy accept;
149 ip6 daddr dead:1::99 dnat to dead:2::99
153 if [ $? -ne 0 ]; then
154 echo "SKIP: Could not add add ip6 dnat hook"
158 # ping netns1, expect rewrite to netns2
159 ip netns exec ns0 ping -q -c 1 dead:1::99 > /dev/null
160 if [ $? -ne 0 ]; then
162 echo "ERROR: ping6 failed"
166 expect="packets 0 bytes 0"
167 for dir in "in6" "out6" ; do
168 cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
169 if [ $? -ne 0 ]; then
170 bad_counter ns0 ns1$dir "$expect"
175 expect="packets 1 bytes 104"
176 for dir in "in6" "out6" ; do
177 cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
178 if [ $? -ne 0 ]; then
179 bad_counter ns0 ns2$dir "$expect"
184 # expect 0 count in ns1
185 expect="packets 0 bytes 0"
186 for dir in "in6" "out6" ; do
187 cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
188 if [ $? -ne 0 ]; then
189 bad_counter ns1 ns0$dir "$expect"
194 # expect 1 packet in ns2
195 expect="packets 1 bytes 104"
196 for dir in "in6" "out6" ; do
197 cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
198 if [ $? -ne 0 ]; then
199 bad_counter ns2 ns0$dir "$expect"
204 test $lret -eq 0 && echo "PASS: ipv6 ping to ns1 was NATted to ns2"
205 ip netns exec ns0 nft flush chain ip6 nat output
213 ip netns exec ns0 nft -f - <<EOF
216 type nat hook output priority 0; policy accept;
217 ip daddr 10.0.1.99 dnat to 10.0.2.99
221 # ping netns1, expect rewrite to netns2
222 ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null
223 if [ $? -ne 0 ]; then
225 echo "ERROR: ping failed"
229 expect="packets 0 bytes 0"
230 for dir in "in" "out" ; do
231 cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
232 if [ $? -ne 0 ]; then
233 bad_counter ns0 ns1$dir "$expect"
238 expect="packets 1 bytes 84"
239 for dir in "in" "out" ; do
240 cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
241 if [ $? -ne 0 ]; then
242 bad_counter ns0 ns2$dir "$expect"
247 # expect 0 count in ns1
248 expect="packets 0 bytes 0"
249 for dir in "in" "out" ; do
250 cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
251 if [ $? -ne 0 ]; then
252 bad_counter ns1 ns0$dir "$expect"
257 # expect 1 packet in ns2
258 expect="packets 1 bytes 84"
259 for dir in "in" "out" ; do
260 cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
261 if [ $? -ne 0 ]; then
262 bad_counter ns2 ns0$dir "$expect"
267 test $lret -eq 0 && echo "PASS: ping to ns1 was NATted to ns2"
269 ip netns exec ns0 nft flush chain ip nat output
272 ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null
273 if [ $? -ne 0 ]; then
275 echo "ERROR: ping failed"
279 expect="packets 1 bytes 84"
280 for dir in "in" "out" ; do
281 cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
282 if [ $? -ne 0 ]; then
283 bad_counter ns1 ns1$dir "$expect"
287 expect="packets 0 bytes 0"
288 for dir in "in" "out" ; do
289 cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
290 if [ $? -ne 0 ]; then
291 bad_counter ns0 ns2$dir "$expect"
296 # expect 1 count in ns1
297 expect="packets 1 bytes 84"
298 for dir in "in" "out" ; do
299 cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
300 if [ $? -ne 0 ]; then
301 bad_counter ns0 ns0$dir "$expect"
306 # expect 0 packet in ns2
307 expect="packets 0 bytes 0"
308 for dir in "in" "out" ; do
309 cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
310 if [ $? -ne 0 ]; then
311 bad_counter ns2 ns2$dir "$expect"
316 test $lret -eq 0 && echo "PASS: ping to ns1 OK after nat output chain flush"
327 ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
329 ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
330 if [ $? -ne 0 ] ; then
331 echo "ERROR: cannot ping ns1 from ns2 via ipv6"
336 expect="packets 1 bytes 104"
337 for dir in "in6" "out6" ; do
338 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
339 if [ $? -ne 0 ]; then
340 bad_counter ns1 ns2$dir "$expect"
344 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
345 if [ $? -ne 0 ]; then
346 bad_counter ns2 ns1$dir "$expect"
353 # add masquerading rule
354 ip netns exec ns0 nft -f - <<EOF
357 type nat hook postrouting priority 0; policy accept;
358 meta oif veth0 masquerade $natflags
362 ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
363 if [ $? -ne 0 ] ; then
364 echo "ERROR: cannot ping ns1 from ns2 with active ipv6 masquerade $natflags"
368 # ns1 should have seen packets from ns0, due to masquerade
369 expect="packets 1 bytes 104"
370 for dir in "in6" "out6" ; do
372 cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
373 if [ $? -ne 0 ]; then
374 bad_counter ns1 ns0$dir "$expect"
378 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
379 if [ $? -ne 0 ]; then
380 bad_counter ns2 ns1$dir "$expect"
385 # ns1 should not have seen packets from ns2, due to masquerade
386 expect="packets 0 bytes 0"
387 for dir in "in6" "out6" ; do
388 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
389 if [ $? -ne 0 ]; then
390 bad_counter ns1 ns0$dir "$expect"
394 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
395 if [ $? -ne 0 ]; then
396 bad_counter ns2 ns1$dir "$expect"
401 ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
402 if [ $? -ne 0 ] ; then
403 echo "ERROR: cannot ping ns1 from ns2 with active ipv6 masquerade $natflags (attempt 2)"
407 ip netns exec ns0 nft flush chain ip6 nat postrouting
408 if [ $? -ne 0 ]; then
409 echo "ERROR: Could not flush ip6 nat postrouting" 1>&2
413 test $lret -eq 0 && echo "PASS: IPv6 masquerade $natflags for ns2"
423 ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
424 ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
426 ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
427 if [ $? -ne 0 ] ; then
428 echo "ERROR: cannot ping ns1 from ns2 $natflags"
432 expect="packets 1 bytes 84"
433 for dir in "in" "out" ; do
434 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
435 if [ $? -ne 0 ]; then
436 bad_counter ns1 ns2$dir "$expect"
440 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
441 if [ $? -ne 0 ]; then
442 bad_counter ns2 ns1$dir "$expect"
449 # add masquerading rule
450 ip netns exec ns0 nft -f - <<EOF
453 type nat hook postrouting priority 0; policy accept;
454 meta oif veth0 masquerade $natflags
458 ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
459 if [ $? -ne 0 ] ; then
460 echo "ERROR: cannot ping ns1 from ns2 with active ip masquere $natflags"
464 # ns1 should have seen packets from ns0, due to masquerade
465 expect="packets 1 bytes 84"
466 for dir in "in" "out" ; do
467 cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
468 if [ $? -ne 0 ]; then
469 bad_counter ns1 ns0$dir "$expect"
473 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
474 if [ $? -ne 0 ]; then
475 bad_counter ns2 ns1$dir "$expect"
480 # ns1 should not have seen packets from ns2, due to masquerade
481 expect="packets 0 bytes 0"
482 for dir in "in" "out" ; do
483 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
484 if [ $? -ne 0 ]; then
485 bad_counter ns1 ns0$dir "$expect"
489 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
490 if [ $? -ne 0 ]; then
491 bad_counter ns2 ns1$dir "$expect"
496 ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
497 if [ $? -ne 0 ] ; then
498 echo "ERROR: cannot ping ns1 from ns2 with active ip masquerade $natflags (attempt 2)"
502 ip netns exec ns0 nft flush chain ip nat postrouting
503 if [ $? -ne 0 ]; then
504 echo "ERROR: Could not flush nat postrouting" 1>&2
508 test $lret -eq 0 && echo "PASS: IP masquerade $natflags for ns2"
517 ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
519 ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
520 if [ $? -ne 0 ] ; then
521 echo "ERROR: cannnot ping ns1 from ns2 via ipv6"
525 expect="packets 1 bytes 104"
526 for dir in "in6" "out6" ; do
527 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
528 if [ $? -ne 0 ]; then
529 bad_counter ns1 ns2$dir "$expect"
533 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
534 if [ $? -ne 0 ]; then
535 bad_counter ns2 ns1$dir "$expect"
543 ip netns exec ns0 nft -f - <<EOF
546 type nat hook prerouting priority 0; policy accept;
547 meta iif veth1 meta l4proto icmpv6 ip6 saddr dead:2::99 ip6 daddr dead:1::99 redirect
551 ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
552 if [ $? -ne 0 ] ; then
553 echo "ERROR: cannot ping ns1 from ns2 with active ip6 redirect"
557 # ns1 should have seen no packets from ns2, due to redirection
558 expect="packets 0 bytes 0"
559 for dir in "in6" "out6" ; do
560 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
561 if [ $? -ne 0 ]; then
562 bad_counter ns1 ns0$dir "$expect"
567 # ns0 should have seen packets from ns2, due to masquerade
568 expect="packets 1 bytes 104"
569 for dir in "in6" "out6" ; do
570 cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
571 if [ $? -ne 0 ]; then
572 bad_counter ns1 ns0$dir "$expect"
577 ip netns exec ns0 nft delete table ip6 nat
578 if [ $? -ne 0 ]; then
579 echo "ERROR: Could not delete ip6 nat table" 1>&2
583 test $lret -eq 0 && echo "PASS: IPv6 redirection for ns2"
592 ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
593 ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
595 ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
596 if [ $? -ne 0 ] ; then
597 echo "ERROR: cannot ping ns1 from ns2"
601 expect="packets 1 bytes 84"
602 for dir in "in" "out" ; do
603 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
604 if [ $? -ne 0 ]; then
605 bad_counter ns1 ns2$dir "$expect"
609 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
610 if [ $? -ne 0 ]; then
611 bad_counter ns2 ns1$dir "$expect"
619 ip netns exec ns0 nft -f - <<EOF
622 type nat hook prerouting priority 0; policy accept;
623 meta iif veth1 ip protocol icmp ip saddr 10.0.2.99 ip daddr 10.0.1.99 redirect
627 ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
628 if [ $? -ne 0 ] ; then
629 echo "ERROR: cannot ping ns1 from ns2 with active ip redirect"
633 # ns1 should have seen no packets from ns2, due to redirection
634 expect="packets 0 bytes 0"
635 for dir in "in" "out" ; do
637 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
638 if [ $? -ne 0 ]; then
639 bad_counter ns1 ns0$dir "$expect"
644 # ns0 should have seen packets from ns2, due to masquerade
645 expect="packets 1 bytes 84"
646 for dir in "in" "out" ; do
647 cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
648 if [ $? -ne 0 ]; then
649 bad_counter ns1 ns0$dir "$expect"
654 ip netns exec ns0 nft delete table ip nat
655 if [ $? -ne 0 ]; then
656 echo "ERROR: Could not delete nat table" 1>&2
660 test $lret -eq 0 && echo "PASS: IP redirection for ns2"
666 # ip netns exec ns0 ping -c 1 -q 10.0.$i.99
668 ip netns exec ns$i nft -f - <<EOF
687 type ipv4_addr : counter
688 elements = { 10.0.1.1 : "ns0in",
691 10.0.2.99 : "ns2in" }
695 type ipv6_addr : counter
696 elements = { dead:1::1 : "ns0in6",
697 dead:2::1 : "ns0in6",
698 dead:1::99 : "ns1in6",
699 dead:2::99 : "ns2in6" }
703 type ipv4_addr : counter
704 elements = { 10.0.1.1 : "ns0out",
707 10.0.2.99: "ns2out" }
711 type ipv6_addr : counter
712 elements = { dead:1::1 : "ns0out6",
713 dead:2::1 : "ns0out6",
714 dead:1::99 : "ns1out6",
715 dead:2::99 : "ns2out6" }
719 type filter hook input priority 0; policy accept;
720 counter name ip saddr map @nsincounter
721 icmpv6 type { "echo-request", "echo-reply" } counter name ip6 saddr map @nsincounter6
724 type filter hook output priority 0; policy accept;
725 counter name ip daddr map @nsoutcounter
726 icmpv6 type { "echo-request", "echo-reply" } counter name ip6 daddr map @nsoutcounter6
733 # test basic connectivity
735 ip netns exec ns0 ping -c 1 -q 10.0.$i.99 > /dev/null
737 echo "ERROR: Could not reach other namespace(s)" 1>&2
741 ip netns exec ns0 ping -c 1 -q dead:$i::99 > /dev/null
743 echo "ERROR: Could not reach other namespace(s) via ipv6" 1>&2
747 if [ $? -ne 0 ]; then
751 check_ns0_counters ns$i
752 if [ $? -ne 0 ]; then
758 if [ $ret -eq 0 ];then
759 echo "PASS: netns routing/connectivity: ns0 can reach ns1 and ns2"
771 test_masquerade "fully-random"
772 test_masquerade6 "fully-random"
778 for i in 0 1 2; do ip netns del ns$i;done