1#!/bin/bash 2# 3# This test is for basic NAT functionality: snat, dnat, redirect, masquerade. 4# 5 6# Kselftest framework requirement - SKIP code is 4. 7ksft_skip=4 8ret=0 9test_inet_nat=true 10 11sfx=$(mktemp -u "XXXXXXXX") 12ns0="ns0-$sfx" 13ns1="ns1-$sfx" 14ns2="ns2-$sfx" 15 16cleanup() 17{ 18 for i in 0 1 2; do ip netns del ns$i-"$sfx";done 19} 20 21nft --version > /dev/null 2>&1 22if [ $? -ne 0 ];then 23 echo "SKIP: Could not run test without nft tool" 24 exit $ksft_skip 25fi 26 27ip -Version > /dev/null 2>&1 28if [ $? -ne 0 ];then 29 echo "SKIP: Could not run test without ip tool" 30 exit $ksft_skip 31fi 32 33ip netns add "$ns0" 34if [ $? -ne 0 ];then 35 echo "SKIP: Could not create net namespace $ns0" 36 exit $ksft_skip 37fi 38 39trap cleanup EXIT 40 41ip netns add "$ns1" 42if [ $? -ne 0 ];then 43 echo "SKIP: Could not create net namespace $ns1" 44 exit $ksft_skip 45fi 46 47ip netns add "$ns2" 48if [ $? -ne 0 ];then 49 echo "SKIP: Could not create net namespace $ns2" 50 exit $ksft_skip 51fi 52 53ip link add veth0 netns "$ns0" type veth peer name eth0 netns "$ns1" > /dev/null 2>&1 54if [ $? -ne 0 ];then 55 echo "SKIP: No virtual ethernet pair device support in kernel" 56 exit $ksft_skip 57fi 58ip link add veth1 netns "$ns0" type veth peer name eth0 netns "$ns2" 59 60ip -net "$ns0" link set lo up 61ip -net "$ns0" link set veth0 up 62ip -net "$ns0" addr add 10.0.1.1/24 dev veth0 63ip -net "$ns0" addr add dead:1::1/64 dev veth0 64 65ip -net "$ns0" link set veth1 up 66ip -net "$ns0" addr add 10.0.2.1/24 dev veth1 67ip -net "$ns0" addr add dead:2::1/64 dev veth1 68 69for i in 1 2; do 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 76done 77 78bad_counter() 79{ 80 local ns=$1 81 local counter=$2 82 local expect=$3 83 local tag=$4 84 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 87} 88 89check_counters() 90{ 91 ns=$1 92 local lret=0 93 94 cnt=$(ip netns exec $ns nft list counter inet filter ns0in | grep -q "packets 1 bytes 84") 95 if [ $? -ne 0 ]; then 96 bad_counter $ns ns0in "packets 1 bytes 84" "check_counters 1" 97 lret=1 98 fi 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" 102 lret=1 103 fi 104 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" 109 lret=1 110 fi 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" 114 lret=1 115 fi 116 117 return $lret 118} 119 120check_ns0_counters() 121{ 122 local ns=$1 123 local lret=0 124 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" 128 lret=1 129 fi 130 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" 134 lret=1 135 fi 136 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" 140 lret=1 141 fi 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 " 145 lret=1 146 fi 147 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" 153 lret=1 154 fi 155 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" 160 lret=1 161 fi 162 done 163 164 return $lret 165} 166 167reset_counters() 168{ 169 for i in 0 1 2;do 170 ip netns exec ns$i-$sfx nft reset counters inet > /dev/null 171 done 172} 173 174test_local_dnat6() 175{ 176 local family=$1 177 local lret=0 178 local IPF="" 179 180 if [ $family = "inet" ];then 181 IPF="ip6" 182 fi 183 184ip netns exec "$ns0" nft -f /dev/stdin <<EOF 185table $family nat { 186 chain output { 187 type nat hook output priority 0; policy accept; 188 ip6 daddr dead:1::99 dnat $IPF to dead:2::99 189 } 190} 191EOF 192 if [ $? -ne 0 ]; then 193 echo "SKIP: Could not add add $family dnat hook" 194 return $ksft_skip 195 fi 196 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 200 lret=1 201 echo "ERROR: ping6 failed" 202 return $lret 203 fi 204 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" 210 lret=1 211 fi 212 done 213 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" 219 lret=1 220 fi 221 done 222 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" 229 lret=1 230 fi 231 done 232 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" 239 lret=1 240 fi 241 done 242 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 245 246 return $lret 247} 248 249test_local_dnat() 250{ 251 local family=$1 252 local lret=0 253 local IPF="" 254 255 if [ $family = "inet" ];then 256 IPF="ip" 257 fi 258 259ip netns exec "$ns0" nft -f /dev/stdin <<EOF 2>/dev/null 260table $family nat { 261 chain output { 262 type nat hook output priority 0; policy accept; 263 ip daddr 10.0.1.99 dnat $IPF to 10.0.2.99 264 } 265} 266EOF 267 if [ $? -ne 0 ]; then 268 if [ $family = "inet" ];then 269 echo "SKIP: inet nat tests" 270 test_inet_nat=false 271 return $ksft_skip 272 fi 273 echo "SKIP: Could not add add $family dnat hook" 274 return $ksft_skip 275 fi 276 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 280 lret=1 281 echo "ERROR: ping failed" 282 return $lret 283 fi 284 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" 290 lret=1 291 fi 292 done 293 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" 299 lret=1 300 fi 301 done 302 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" 309 lret=1 310 fi 311 done 312 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" 319 lret=1 320 fi 321 done 322 323 test $lret -eq 0 && echo "PASS: ping to $ns1 was $family NATted to $ns2" 324 325 ip netns exec "$ns0" nft flush chain $family nat output 326 327 reset_counters 328 ip netns exec "$ns0" ping -q -c 1 10.0.1.99 > /dev/null 329 if [ $? -ne 0 ]; then 330 lret=1 331 echo "ERROR: ping failed" 332 return $lret 333 fi 334 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" 340 lret=1 341 fi 342 done 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" 348 lret=1 349 fi 350 done 351 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" 358 lret=1 359 fi 360 done 361 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" 368 lret=1 369 fi 370 done 371 372 test $lret -eq 0 && echo "PASS: ping to $ns1 OK after $family nat output chain flush" 373 374 return $lret 375} 376 377 378test_masquerade6() 379{ 380 local family=$1 381 local natflags=$2 382 local lret=0 383 384 ip netns exec "$ns0" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null 385 386 ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 387 if [ $? -ne 0 ] ; then 388 echo "ERROR: cannot ping $ns1 from $ns2 via ipv6" 389 return 1 390 lret=1 391 fi 392 393 expect="packets 1 bytes 104" 394 for dir in "in6" "out6" ; do 395 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") 396 if [ $? -ne 0 ]; then 397 bad_counter "$ns1" ns2$dir "$expect" "test_masquerade6 1" 398 lret=1 399 fi 400 401 cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") 402 if [ $? -ne 0 ]; then 403 bad_counter "$ns2" ns1$dir "$expect" "test_masquerade6 2" 404 lret=1 405 fi 406 done 407 408 reset_counters 409 410# add masquerading rule 411ip netns exec "$ns0" nft -f /dev/stdin <<EOF 412table $family nat { 413 chain postrouting { 414 type nat hook postrouting priority 0; policy accept; 415 meta oif veth0 masquerade $natflags 416 } 417} 418EOF 419 if [ $? -ne 0 ]; then 420 echo "SKIP: Could not add add $family masquerade hook" 421 return $ksft_skip 422 fi 423 424 ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 425 if [ $? -ne 0 ] ; then 426 echo "ERROR: cannot ping $ns1 from $ns2 with active $family masquerade $natflags" 427 lret=1 428 fi 429 430 # ns1 should have seen packets from ns0, due to masquerade 431 expect="packets 1 bytes 104" 432 for dir in "in6" "out6" ; do 433 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect") 434 if [ $? -ne 0 ]; then 435 bad_counter "$ns1" ns0$dir "$expect" "test_masquerade6 3" 436 lret=1 437 fi 438 439 cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") 440 if [ $? -ne 0 ]; then 441 bad_counter "$ns2" ns1$dir "$expect" "test_masquerade6 4" 442 lret=1 443 fi 444 done 445 446 # ns1 should not have seen packets from ns2, due to masquerade 447 expect="packets 0 bytes 0" 448 for dir in "in6" "out6" ; do 449 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") 450 if [ $? -ne 0 ]; then 451 bad_counter "$ns1" ns0$dir "$expect" "test_masquerade6 5" 452 lret=1 453 fi 454 455 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect") 456 if [ $? -ne 0 ]; then 457 bad_counter "$ns0" ns1$dir "$expect" "test_masquerade6 6" 458 lret=1 459 fi 460 done 461 462 ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 463 if [ $? -ne 0 ] ; then 464 echo "ERROR: cannot ping $ns1 from $ns2 with active ipv6 masquerade $natflags (attempt 2)" 465 lret=1 466 fi 467 468 ip netns exec "$ns0" nft flush chain $family nat postrouting 469 if [ $? -ne 0 ]; then 470 echo "ERROR: Could not flush $family nat postrouting" 1>&2 471 lret=1 472 fi 473 474 test $lret -eq 0 && echo "PASS: $family IPv6 masquerade $natflags for $ns2" 475 476 return $lret 477} 478 479test_masquerade() 480{ 481 local family=$1 482 local natflags=$2 483 local lret=0 484 485 ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null 486 ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null 487 488 ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 489 if [ $? -ne 0 ] ; then 490 echo "ERROR: cannot ping $ns1 from "$ns2" $natflags" 491 lret=1 492 fi 493 494 expect="packets 1 bytes 84" 495 for dir in "in" "out" ; do 496 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") 497 if [ $? -ne 0 ]; then 498 bad_counter "$ns1" ns2$dir "$expect" "test_masquerade 1" 499 lret=1 500 fi 501 502 cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") 503 if [ $? -ne 0 ]; then 504 bad_counter "$ns2" ns1$dir "$expect" "test_masquerade 2" 505 lret=1 506 fi 507 done 508 509 reset_counters 510 511# add masquerading rule 512ip netns exec "$ns0" nft -f /dev/stdin <<EOF 513table $family nat { 514 chain postrouting { 515 type nat hook postrouting priority 0; policy accept; 516 meta oif veth0 masquerade $natflags 517 } 518} 519EOF 520 if [ $? -ne 0 ]; then 521 echo "SKIP: Could not add add $family masquerade hook" 522 return $ksft_skip 523 fi 524 525 ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 526 if [ $? -ne 0 ] ; then 527 echo "ERROR: cannot ping $ns1 from $ns2 with active $family masquerade $natflags" 528 lret=1 529 fi 530 531 # ns1 should have seen packets from ns0, due to masquerade 532 expect="packets 1 bytes 84" 533 for dir in "in" "out" ; do 534 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect") 535 if [ $? -ne 0 ]; then 536 bad_counter "$ns1" ns0$dir "$expect" "test_masquerade 3" 537 lret=1 538 fi 539 540 cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") 541 if [ $? -ne 0 ]; then 542 bad_counter "$ns2" ns1$dir "$expect" "test_masquerade 4" 543 lret=1 544 fi 545 done 546 547 # ns1 should not have seen packets from ns2, due to masquerade 548 expect="packets 0 bytes 0" 549 for dir in "in" "out" ; do 550 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") 551 if [ $? -ne 0 ]; then 552 bad_counter "$ns1" ns0$dir "$expect" "test_masquerade 5" 553 lret=1 554 fi 555 556 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect") 557 if [ $? -ne 0 ]; then 558 bad_counter "$ns0" ns1$dir "$expect" "test_masquerade 6" 559 lret=1 560 fi 561 done 562 563 ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 564 if [ $? -ne 0 ] ; then 565 echo "ERROR: cannot ping $ns1 from $ns2 with active ip masquerade $natflags (attempt 2)" 566 lret=1 567 fi 568 569 ip netns exec "$ns0" nft flush chain $family nat postrouting 570 if [ $? -ne 0 ]; then 571 echo "ERROR: Could not flush $family nat postrouting" 1>&2 572 lret=1 573 fi 574 575 test $lret -eq 0 && echo "PASS: $family IP masquerade $natflags for $ns2" 576 577 return $lret 578} 579 580test_redirect6() 581{ 582 local family=$1 583 local lret=0 584 585 ip netns exec "$ns0" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null 586 587 ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 588 if [ $? -ne 0 ] ; then 589 echo "ERROR: cannnot ping $ns1 from $ns2 via ipv6" 590 lret=1 591 fi 592 593 expect="packets 1 bytes 104" 594 for dir in "in6" "out6" ; do 595 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") 596 if [ $? -ne 0 ]; then 597 bad_counter "$ns1" ns2$dir "$expect" "test_redirect6 1" 598 lret=1 599 fi 600 601 cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") 602 if [ $? -ne 0 ]; then 603 bad_counter "$ns2" ns1$dir "$expect" "test_redirect6 2" 604 lret=1 605 fi 606 done 607 608 reset_counters 609 610# add redirect rule 611ip netns exec "$ns0" nft -f /dev/stdin <<EOF 612table $family nat { 613 chain prerouting { 614 type nat hook prerouting priority 0; policy accept; 615 meta iif veth1 meta l4proto icmpv6 ip6 saddr dead:2::99 ip6 daddr dead:1::99 redirect 616 } 617} 618EOF 619 if [ $? -ne 0 ]; then 620 echo "SKIP: Could not add add $family redirect hook" 621 return $ksft_skip 622 fi 623 624 ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 625 if [ $? -ne 0 ] ; then 626 echo "ERROR: cannot ping $ns1 from $ns2 via ipv6 with active $family redirect" 627 lret=1 628 fi 629 630 # ns1 should have seen no packets from ns2, due to redirection 631 expect="packets 0 bytes 0" 632 for dir in "in6" "out6" ; do 633 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") 634 if [ $? -ne 0 ]; then 635 bad_counter "$ns1" ns0$dir "$expect" "test_redirect6 3" 636 lret=1 637 fi 638 done 639 640 # ns0 should have seen packets from ns2, due to masquerade 641 expect="packets 1 bytes 104" 642 for dir in "in6" "out6" ; do 643 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect") 644 if [ $? -ne 0 ]; then 645 bad_counter "$ns1" ns0$dir "$expect" "test_redirect6 4" 646 lret=1 647 fi 648 done 649 650 ip netns exec "$ns0" nft delete table $family nat 651 if [ $? -ne 0 ]; then 652 echo "ERROR: Could not delete $family nat table" 1>&2 653 lret=1 654 fi 655 656 test $lret -eq 0 && echo "PASS: $family IPv6 redirection for $ns2" 657 658 return $lret 659} 660 661test_redirect() 662{ 663 local family=$1 664 local lret=0 665 666 ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null 667 ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null 668 669 ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 670 if [ $? -ne 0 ] ; then 671 echo "ERROR: cannot ping $ns1 from $ns2" 672 lret=1 673 fi 674 675 expect="packets 1 bytes 84" 676 for dir in "in" "out" ; do 677 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") 678 if [ $? -ne 0 ]; then 679 bad_counter "$ns1" $ns2$dir "$expect" "test_redirect 1" 680 lret=1 681 fi 682 683 cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") 684 if [ $? -ne 0 ]; then 685 bad_counter "$ns2" ns1$dir "$expect" "test_redirect 2" 686 lret=1 687 fi 688 done 689 690 reset_counters 691 692# add redirect rule 693ip netns exec "$ns0" nft -f /dev/stdin <<EOF 694table $family nat { 695 chain prerouting { 696 type nat hook prerouting priority 0; policy accept; 697 meta iif veth1 ip protocol icmp ip saddr 10.0.2.99 ip daddr 10.0.1.99 redirect 698 } 699} 700EOF 701 if [ $? -ne 0 ]; then 702 echo "SKIP: Could not add add $family redirect hook" 703 return $ksft_skip 704 fi 705 706 ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 707 if [ $? -ne 0 ] ; then 708 echo "ERROR: cannot ping $ns1 from $ns2 with active $family ip redirect" 709 lret=1 710 fi 711 712 # ns1 should have seen no packets from ns2, due to redirection 713 expect="packets 0 bytes 0" 714 for dir in "in" "out" ; do 715 716 cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") 717 if [ $? -ne 0 ]; then 718 bad_counter "$ns1" ns0$dir "$expect" "test_redirect 3" 719 lret=1 720 fi 721 done 722 723 # ns0 should have seen packets from ns2, due to masquerade 724 expect="packets 1 bytes 84" 725 for dir in "in" "out" ; do 726 cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect") 727 if [ $? -ne 0 ]; then 728 bad_counter "$ns0" ns0$dir "$expect" "test_redirect 4" 729 lret=1 730 fi 731 done 732 733 ip netns exec "$ns0" nft delete table $family nat 734 if [ $? -ne 0 ]; then 735 echo "ERROR: Could not delete $family nat table" 1>&2 736 lret=1 737 fi 738 739 test $lret -eq 0 && echo "PASS: $family IP redirection for $ns2" 740 741 return $lret 742} 743 744# test port shadowing. 745# create two listening services, one on router (ns0), one 746# on client (ns2), which is masqueraded from ns1 point of view. 747# ns2 sends udp packet coming from service port to ns1, on a highport. 748# Later, if n1 uses same highport to connect to ns0:service, packet 749# might be port-forwarded to ns2 instead. 750 751# second argument tells if we expect the 'fake-entry' to take effect 752# (CLIENT) or not (ROUTER). 753test_port_shadow() 754{ 755 local test=$1 756 local expect=$2 757 local daddrc="10.0.1.99" 758 local daddrs="10.0.1.1" 759 local result="" 760 local logmsg="" 761 762 echo ROUTER | ip netns exec "$ns0" nc -w 5 -u -l -p 1405 >/dev/null 2>&1 & 763 nc_r=$! 764 765 echo CLIENT | ip netns exec "$ns2" nc -w 5 -u -l -p 1405 >/dev/null 2>&1 & 766 nc_c=$! 767 768 # make shadow entry, from client (ns2), going to (ns1), port 41404, sport 1405. 769 echo "fake-entry" | ip netns exec "$ns2" nc -w 1 -p 1405 -u "$daddrc" 41404 > /dev/null 770 771 # ns1 tries to connect to ns0:1405. With default settings this should connect 772 # to client, it matches the conntrack entry created above. 773 774 result=$(echo "" | ip netns exec "$ns1" nc -w 1 -p 41404 -u "$daddrs" 1405) 775 776 if [ "$result" = "$expect" ] ;then 777 echo "PASS: portshadow test $test: got reply from ${expect}${logmsg}" 778 else 779 echo "ERROR: portshadow test $test: got reply from \"$result\", not $expect as intended" 780 ret=1 781 fi 782 783 kill $nc_r $nc_c 2>/dev/null 784 785 # flush udp entries for next test round, if any 786 ip netns exec "$ns0" conntrack -F >/dev/null 2>&1 787} 788 789# This prevents port shadow of router service via packet filter, 790# packets claiming to originate from service port from internal 791# network are dropped. 792test_port_shadow_filter() 793{ 794 local family=$1 795 796ip netns exec "$ns0" nft -f /dev/stdin <<EOF 797table $family filter { 798 chain forward { 799 type filter hook forward priority 0; policy accept; 800 meta iif veth1 udp sport 1405 drop 801 } 802} 803EOF 804 test_port_shadow "port-filter" "ROUTER" 805 806 ip netns exec "$ns0" nft delete table $family filter 807} 808 809# This prevents port shadow of router service via notrack. 810test_port_shadow_notrack() 811{ 812 local family=$1 813 814ip netns exec "$ns0" nft -f /dev/stdin <<EOF 815table $family raw { 816 chain prerouting { 817 type filter hook prerouting priority -300; policy accept; 818 meta iif veth0 udp dport 1405 notrack 819 udp dport 1405 notrack 820 } 821 chain output { 822 type filter hook output priority -300; policy accept; 823 udp sport 1405 notrack 824 } 825} 826EOF 827 test_port_shadow "port-notrack" "ROUTER" 828 829 ip netns exec "$ns0" nft delete table $family raw 830} 831 832# This prevents port shadow of router service via sport remap. 833test_port_shadow_pat() 834{ 835 local family=$1 836 837ip netns exec "$ns0" nft -f /dev/stdin <<EOF 838table $family pat { 839 chain postrouting { 840 type nat hook postrouting priority -1; policy accept; 841 meta iif veth1 udp sport <= 1405 masquerade to : 1406-65535 random 842 } 843} 844EOF 845 test_port_shadow "pat" "ROUTER" 846 847 ip netns exec "$ns0" nft delete table $family pat 848} 849 850test_port_shadowing() 851{ 852 local family="ip" 853 854 ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null 855 ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null 856 857 ip netns exec "$ns0" nft -f /dev/stdin <<EOF 858table $family nat { 859 chain postrouting { 860 type nat hook postrouting priority 0; policy accept; 861 meta oif veth0 masquerade 862 } 863} 864EOF 865 if [ $? -ne 0 ]; then 866 echo "SKIP: Could not add add $family masquerade hook" 867 return $ksft_skip 868 fi 869 870 # test default behaviour. Packet from ns1 to ns0 is redirected to ns2. 871 test_port_shadow "default" "CLIENT" 872 873 # test packet filter based mitigation: prevent forwarding of 874 # packets claiming to come from the service port. 875 test_port_shadow_filter "$family" 876 877 # test conntrack based mitigation: connections going or coming 878 # from router:service bypass connection tracking. 879 test_port_shadow_notrack "$family" 880 881 # test nat based mitigation: fowarded packets coming from service port 882 # are masqueraded with random highport. 883 test_port_shadow_pat "$family" 884 885 ip netns exec "$ns0" nft delete table $family nat 886} 887 888# ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99 889for i in 0 1 2; do 890ip netns exec ns$i-$sfx nft -f /dev/stdin <<EOF 891table inet filter { 892 counter ns0in {} 893 counter ns1in {} 894 counter ns2in {} 895 896 counter ns0out {} 897 counter ns1out {} 898 counter ns2out {} 899 900 counter ns0in6 {} 901 counter ns1in6 {} 902 counter ns2in6 {} 903 904 counter ns0out6 {} 905 counter ns1out6 {} 906 counter ns2out6 {} 907 908 map nsincounter { 909 type ipv4_addr : counter 910 elements = { 10.0.1.1 : "ns0in", 911 10.0.2.1 : "ns0in", 912 10.0.1.99 : "ns1in", 913 10.0.2.99 : "ns2in" } 914 } 915 916 map nsincounter6 { 917 type ipv6_addr : counter 918 elements = { dead:1::1 : "ns0in6", 919 dead:2::1 : "ns0in6", 920 dead:1::99 : "ns1in6", 921 dead:2::99 : "ns2in6" } 922 } 923 924 map nsoutcounter { 925 type ipv4_addr : counter 926 elements = { 10.0.1.1 : "ns0out", 927 10.0.2.1 : "ns0out", 928 10.0.1.99: "ns1out", 929 10.0.2.99: "ns2out" } 930 } 931 932 map nsoutcounter6 { 933 type ipv6_addr : counter 934 elements = { dead:1::1 : "ns0out6", 935 dead:2::1 : "ns0out6", 936 dead:1::99 : "ns1out6", 937 dead:2::99 : "ns2out6" } 938 } 939 940 chain input { 941 type filter hook input priority 0; policy accept; 942 counter name ip saddr map @nsincounter 943 icmpv6 type { "echo-request", "echo-reply" } counter name ip6 saddr map @nsincounter6 944 } 945 chain output { 946 type filter hook output priority 0; policy accept; 947 counter name ip daddr map @nsoutcounter 948 icmpv6 type { "echo-request", "echo-reply" } counter name ip6 daddr map @nsoutcounter6 949 } 950} 951EOF 952done 953 954sleep 3 955# test basic connectivity 956for i in 1 2; do 957 ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99 > /dev/null 958 if [ $? -ne 0 ];then 959 echo "ERROR: Could not reach other namespace(s)" 1>&2 960 ret=1 961 fi 962 963 ip netns exec "$ns0" ping -c 1 -q dead:$i::99 > /dev/null 964 if [ $? -ne 0 ];then 965 echo "ERROR: Could not reach other namespace(s) via ipv6" 1>&2 966 ret=1 967 fi 968 check_counters ns$i-$sfx 969 if [ $? -ne 0 ]; then 970 ret=1 971 fi 972 973 check_ns0_counters ns$i 974 if [ $? -ne 0 ]; then 975 ret=1 976 fi 977 reset_counters 978done 979 980if [ $ret -eq 0 ];then 981 echo "PASS: netns routing/connectivity: $ns0 can reach $ns1 and $ns2" 982fi 983 984reset_counters 985test_local_dnat ip 986test_local_dnat6 ip6 987reset_counters 988$test_inet_nat && test_local_dnat inet 989$test_inet_nat && test_local_dnat6 inet 990 991for flags in "" "fully-random"; do 992reset_counters 993test_masquerade ip $flags 994test_masquerade6 ip6 $flags 995reset_counters 996$test_inet_nat && test_masquerade inet $flags 997$test_inet_nat && test_masquerade6 inet $flags 998done 999 1000reset_counters 1001test_redirect ip 1002test_redirect6 ip6 1003reset_counters 1004$test_inet_nat && test_redirect inet 1005$test_inet_nat && test_redirect6 inet 1006 1007test_port_shadowing 1008 1009if [ $ret -ne 0 ];then 1010 echo -n "FAIL: " 1011 nft --version 1012fi 1013 1014exit $ret 1015