1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4# Check xfrm policy resolution. Topology: 5# 6# 1.2 1.1 3.1 3.10 2.1 2.2 7# eth1 eth1 veth0 veth0 eth1 eth1 8# ns1 ---- ns3 ----- ns4 ---- ns2 9# 10# ns3 and ns4 are connected via ipsec tunnel. 11# pings from ns1 to ns2 (and vice versa) are supposed to work like this: 12# ns1: ping 10.0.2.2: passes via ipsec tunnel. 13# ns2: ping 10.0.1.2: passes via ipsec tunnel. 14 15# ns1: ping 10.0.1.253: passes via ipsec tunnel (direct policy) 16# ns2: ping 10.0.2.253: passes via ipsec tunnel (direct policy) 17# 18# ns1: ping 10.0.2.254: does NOT pass via ipsec tunnel (exception) 19# ns2: ping 10.0.1.254: does NOT pass via ipsec tunnel (exception) 20 21# Kselftest framework requirement - SKIP code is 4. 22ksft_skip=4 23ret=0 24policy_checks_ok=1 25 26KEY_SHA=0xdeadbeef1234567890abcdefabcdefabcdefabcd 27KEY_AES=0x0123456789abcdef0123456789012345 28SPI1=0x1 29SPI2=0x2 30 31do_esp_policy() { 32 local ns=$1 33 local me=$2 34 local remote=$3 35 local lnet=$4 36 local rnet=$5 37 38 # to encrypt packets as they go out (includes forwarded packets that need encapsulation) 39 ip -net $ns xfrm policy add src $lnet dst $rnet dir out tmpl src $me dst $remote proto esp mode tunnel priority 100 action allow 40 # to fwd decrypted packets after esp processing: 41 ip -net $ns xfrm policy add src $rnet dst $lnet dir fwd tmpl src $remote dst $me proto esp mode tunnel priority 100 action allow 42} 43 44do_esp() { 45 local ns=$1 46 local me=$2 47 local remote=$3 48 local lnet=$4 49 local rnet=$5 50 local spi_out=$6 51 local spi_in=$7 52 53 ip -net $ns xfrm state add src $remote dst $me proto esp spi $spi_in enc aes $KEY_AES auth sha1 $KEY_SHA mode tunnel sel src $rnet dst $lnet 54 ip -net $ns xfrm state add src $me dst $remote proto esp spi $spi_out enc aes $KEY_AES auth sha1 $KEY_SHA mode tunnel sel src $lnet dst $rnet 55 56 do_esp_policy $ns $me $remote $lnet $rnet 57} 58 59# add policies with different netmasks, to make sure kernel carries 60# the policies contained within new netmask over when search tree is 61# re-built. 62# peer netns that are supposed to be encapsulated via esp have addresses 63# in the 10.0.1.0/24 and 10.0.2.0/24 subnets, respectively. 64# 65# Adding a policy for '10.0.1.0/23' will make it necessary to 66# alter the prefix of 10.0.1.0 subnet. 67# In case new prefix overlaps with existing node, the node and all 68# policies it carries need to be merged with the existing one(s). 69# 70# Do that here. 71do_overlap() 72{ 73 local ns=$1 74 75 # adds new nodes to tree (neither network exists yet in policy database). 76 ip -net $ns xfrm policy add src 10.1.0.0/24 dst 10.0.0.0/24 dir fwd priority 200 action block 77 78 # adds a new node in the 10.0.0.0/24 tree (dst node exists). 79 ip -net $ns xfrm policy add src 10.2.0.0/24 dst 10.0.0.0/24 dir fwd priority 200 action block 80 81 # adds a 10.2.0.0/23 node, but for different dst. 82 ip -net $ns xfrm policy add src 10.2.0.0/23 dst 10.0.1.0/24 dir fwd priority 200 action block 83 84 # dst now overlaps with the 10.0.1.0/24 ESP policy in fwd. 85 # kernel must 'promote' existing one (10.0.0.0/24) to 10.0.0.0/23. 86 # But 10.0.0.0/23 also includes existing 10.0.1.0/24, so that node 87 # also has to be merged too, including source-sorted subtrees. 88 # old: 89 # 10.0.0.0/24 (node 1 in dst tree of the bin) 90 # 10.1.0.0/24 (node in src tree of dst node 1) 91 # 10.2.0.0/24 (node in src tree of dst node 1) 92 # 10.0.1.0/24 (node 2 in dst tree of the bin) 93 # 10.0.2.0/24 (node in src tree of dst node 2) 94 # 10.2.0.0/24 (node in src tree of dst node 2) 95 # 96 # The next 'policy add' adds dst '10.0.0.0/23', which means 97 # that dst node 1 and dst node 2 have to be merged including 98 # the sub-tree. As no duplicates are allowed, policies in 99 # the two '10.0.2.0/24' are also merged. 100 # 101 # after the 'add', internal search tree should look like this: 102 # 10.0.0.0/23 (node in dst tree of bin) 103 # 10.0.2.0/24 (node in src tree of dst node) 104 # 10.1.0.0/24 (node in src tree of dst node) 105 # 10.2.0.0/24 (node in src tree of dst node) 106 # 107 # 10.0.0.0/24 and 10.0.1.0/24 nodes have been merged as 10.0.0.0/23. 108 ip -net $ns xfrm policy add src 10.1.0.0/24 dst 10.0.0.0/23 dir fwd priority 200 action block 109 110 # similar to above: add policies (with partially random address), with shrinking prefixes. 111 for p in 29 28 27;do 112 for k in $(seq 1 32); do 113 ip -net $ns xfrm policy add src 10.253.1.$((RANDOM%255))/$p dst 10.254.1.$((RANDOM%255))/$p dir fwd priority $((200+k)) action block 2>/dev/null 114 done 115 done 116} 117 118do_esp_policy_get_check() { 119 local ns=$1 120 local lnet=$2 121 local rnet=$3 122 123 ip -net $ns xfrm policy get src $lnet dst $rnet dir out > /dev/null 124 if [ $? -ne 0 ] && [ $policy_checks_ok -eq 1 ] ;then 125 policy_checks_ok=0 126 echo "FAIL: ip -net $ns xfrm policy get src $lnet dst $rnet dir out" 127 ret=1 128 fi 129 130 ip -net $ns xfrm policy get src $rnet dst $lnet dir fwd > /dev/null 131 if [ $? -ne 0 ] && [ $policy_checks_ok -eq 1 ] ;then 132 policy_checks_ok=0 133 echo "FAIL: ip -net $ns xfrm policy get src $rnet dst $lnet dir fwd" 134 ret=1 135 fi 136} 137 138do_exception() { 139 local ns=$1 140 local me=$2 141 local remote=$3 142 local encryptip=$4 143 local plain=$5 144 145 # network $plain passes without tunnel 146 ip -net $ns xfrm policy add dst $plain dir out priority 10 action allow 147 148 # direct policy for $encryptip, use tunnel, higher prio takes precedence 149 ip -net $ns xfrm policy add dst $encryptip dir out tmpl src $me dst $remote proto esp mode tunnel priority 1 action allow 150} 151 152# policies that are not supposed to match any packets generated in this test. 153do_dummies4() { 154 local ns=$1 155 156 for i in $(seq 10 16);do 157 # dummy policy with wildcard src/dst. 158 echo netns exec $ns ip xfrm policy add src 0.0.0.0/0 dst 10.$i.99.0/30 dir out action block 159 echo netns exec $ns ip xfrm policy add src 10.$i.99.0/30 dst 0.0.0.0/0 dir out action block 160 for j in $(seq 32 64);do 161 echo netns exec $ns ip xfrm policy add src 10.$i.1.0/30 dst 10.$i.$j.0/30 dir out action block 162 # silly, as it encompasses the one above too, but its allowed: 163 echo netns exec $ns ip xfrm policy add src 10.$i.1.0/29 dst 10.$i.$j.0/29 dir out action block 164 # and yet again, even more broad one. 165 echo netns exec $ns ip xfrm policy add src 10.$i.1.0/24 dst 10.$i.$j.0/24 dir out action block 166 echo netns exec $ns ip xfrm policy add src 10.$i.$j.0/24 dst 10.$i.1.0/24 dir fwd action block 167 done 168 done | ip -batch /dev/stdin 169} 170 171do_dummies6() { 172 local ns=$1 173 174 for i in $(seq 10 16);do 175 for j in $(seq 32 64);do 176 echo netns exec $ns ip xfrm policy add src dead:$i::/64 dst dead:$i:$j::/64 dir out action block 177 echo netns exec $ns ip xfrm policy add src dead:$i:$j::/64 dst dead:$i::/24 dir fwd action block 178 done 179 done | ip -batch /dev/stdin 180} 181 182check_ipt_policy_count() 183{ 184 ns=$1 185 186 ip netns exec $ns iptables-save -c |grep policy | ( read c rest 187 ip netns exec $ns iptables -Z 188 if [ x"$c" = x'[0:0]' ]; then 189 exit 0 190 elif [ x"$c" = x ]; then 191 echo "ERROR: No counters" 192 ret=1 193 exit 111 194 else 195 exit 1 196 fi 197 ) 198} 199 200check_xfrm() { 201 # 0: iptables -m policy rule count == 0 202 # 1: iptables -m policy rule count != 0 203 rval=$1 204 ip=$2 205 local lret=0 206 207 ip netns exec ns1 ping -q -c 1 10.0.2.$ip > /dev/null 208 209 check_ipt_policy_count ns3 210 if [ $? -ne $rval ] ; then 211 lret=1 212 fi 213 check_ipt_policy_count ns4 214 if [ $? -ne $rval ] ; then 215 lret=1 216 fi 217 218 ip netns exec ns2 ping -q -c 1 10.0.1.$ip > /dev/null 219 220 check_ipt_policy_count ns3 221 if [ $? -ne $rval ] ; then 222 lret=1 223 fi 224 check_ipt_policy_count ns4 225 if [ $? -ne $rval ] ; then 226 lret=1 227 fi 228 229 return $lret 230} 231 232check_exceptions() 233{ 234 logpostfix="$1" 235 local lret=0 236 237 # ping to .254 should be excluded from the tunnel (exception is in place). 238 check_xfrm 0 254 239 if [ $? -ne 0 ]; then 240 echo "FAIL: expected ping to .254 to fail ($logpostfix)" 241 lret=1 242 else 243 echo "PASS: ping to .254 bypassed ipsec tunnel ($logpostfix)" 244 fi 245 246 # ping to .253 should use use ipsec due to direct policy exception. 247 check_xfrm 1 253 248 if [ $? -ne 0 ]; then 249 echo "FAIL: expected ping to .253 to use ipsec tunnel ($logpostfix)" 250 lret=1 251 else 252 echo "PASS: direct policy matches ($logpostfix)" 253 fi 254 255 # ping to .2 should use ipsec. 256 check_xfrm 1 2 257 if [ $? -ne 0 ]; then 258 echo "FAIL: expected ping to .2 to use ipsec tunnel ($logpostfix)" 259 lret=1 260 else 261 echo "PASS: policy matches ($logpostfix)" 262 fi 263 264 return $lret 265} 266 267check_hthresh_repeat() 268{ 269 local log=$1 270 i=0 271 272 for i in $(seq 1 10);do 273 ip -net ns1 xfrm policy update src e000:0001::0000 dst ff01::0014:0000:0001 dir in tmpl src :: dst :: proto esp mode tunnel priority 100 action allow || break 274 ip -net ns1 xfrm policy set hthresh6 0 28 || break 275 276 ip -net ns1 xfrm policy update src e000:0001::0000 dst ff01::01 dir in tmpl src :: dst :: proto esp mode tunnel priority 100 action allow || break 277 ip -net ns1 xfrm policy set hthresh6 0 28 || break 278 done 279 280 if [ $i -ne 10 ] ;then 281 echo "FAIL: $log" 1>&2 282 ret=1 283 return 1 284 fi 285 286 echo "PASS: $log" 287 return 0 288} 289 290# insert non-overlapping policies in a random order and check that 291# all of them can be fetched using the traffic selectors. 292check_random_order() 293{ 294 local ns=$1 295 local log=$2 296 297 for i in $(seq 100); do 298 ip -net $ns xfrm policy flush 299 for j in $(seq 0 16 255 | sort -R); do 300 ip -net $ns xfrm policy add dst $j.0.0.0/24 dir out priority 10 action allow 301 done 302 for j in $(seq 0 16 255); do 303 if ! ip -net $ns xfrm policy get dst $j.0.0.0/24 dir out > /dev/null; then 304 echo "FAIL: $log" 1>&2 305 return 1 306 fi 307 done 308 done 309 310 for i in $(seq 100); do 311 ip -net $ns xfrm policy flush 312 for j in $(seq 0 16 255 | sort -R); do 313 local addr=$(printf "e000:0000:%02x00::/56" $j) 314 ip -net $ns xfrm policy add dst $addr dir out priority 10 action allow 315 done 316 for j in $(seq 0 16 255); do 317 local addr=$(printf "e000:0000:%02x00::/56" $j) 318 if ! ip -net $ns xfrm policy get dst $addr dir out > /dev/null; then 319 echo "FAIL: $log" 1>&2 320 return 1 321 fi 322 done 323 done 324 325 ip -net $ns xfrm policy flush 326 327 echo "PASS: $log" 328 return 0 329} 330 331#check for needed privileges 332if [ "$(id -u)" -ne 0 ];then 333 echo "SKIP: Need root privileges" 334 exit $ksft_skip 335fi 336 337ip -Version 2>/dev/null >/dev/null 338if [ $? -ne 0 ];then 339 echo "SKIP: Could not run test without the ip tool" 340 exit $ksft_skip 341fi 342 343# needed to check if policy lookup got valid ipsec result 344iptables --version 2>/dev/null >/dev/null 345if [ $? -ne 0 ];then 346 echo "SKIP: Could not run test without iptables tool" 347 exit $ksft_skip 348fi 349 350for i in 1 2 3 4; do 351 ip netns add ns$i 352 ip -net ns$i link set lo up 353done 354 355DEV=veth0 356ip link add $DEV netns ns1 type veth peer name eth1 netns ns3 357ip link add $DEV netns ns2 type veth peer name eth1 netns ns4 358 359ip link add $DEV netns ns3 type veth peer name veth0 netns ns4 360 361DEV=veth0 362for i in 1 2; do 363 ip -net ns$i link set $DEV up 364 ip -net ns$i addr add 10.0.$i.2/24 dev $DEV 365 ip -net ns$i addr add dead:$i::2/64 dev $DEV 366 367 ip -net ns$i addr add 10.0.$i.253 dev $DEV 368 ip -net ns$i addr add 10.0.$i.254 dev $DEV 369 ip -net ns$i addr add dead:$i::fd dev $DEV 370 ip -net ns$i addr add dead:$i::fe dev $DEV 371done 372 373for i in 3 4; do 374ip -net ns$i link set eth1 up 375ip -net ns$i link set veth0 up 376done 377 378ip -net ns1 route add default via 10.0.1.1 379ip -net ns2 route add default via 10.0.2.1 380 381ip -net ns3 addr add 10.0.1.1/24 dev eth1 382ip -net ns3 addr add 10.0.3.1/24 dev veth0 383ip -net ns3 addr add 2001:1::1/64 dev eth1 384ip -net ns3 addr add 2001:3::1/64 dev veth0 385 386ip -net ns3 route add default via 10.0.3.10 387 388ip -net ns4 addr add 10.0.2.1/24 dev eth1 389ip -net ns4 addr add 10.0.3.10/24 dev veth0 390ip -net ns4 addr add 2001:2::1/64 dev eth1 391ip -net ns4 addr add 2001:3::10/64 dev veth0 392ip -net ns4 route add default via 10.0.3.1 393 394for j in 4 6; do 395 for i in 3 4;do 396 ip netns exec ns$i sysctl net.ipv$j.conf.eth1.forwarding=1 > /dev/null 397 ip netns exec ns$i sysctl net.ipv$j.conf.veth0.forwarding=1 > /dev/null 398 done 399done 400 401# abuse iptables rule counter to check if ping matches a policy 402ip netns exec ns3 iptables -p icmp -A FORWARD -m policy --dir out --pol ipsec 403ip netns exec ns4 iptables -p icmp -A FORWARD -m policy --dir out --pol ipsec 404if [ $? -ne 0 ];then 405 echo "SKIP: Could not insert iptables rule" 406 for i in 1 2 3 4;do ip netns del ns$i;done 407 exit $ksft_skip 408fi 409 410# localip remoteip localnet remotenet 411do_esp ns3 10.0.3.1 10.0.3.10 10.0.1.0/24 10.0.2.0/24 $SPI1 $SPI2 412do_esp ns3 dead:3::1 dead:3::10 dead:1::/64 dead:2::/64 $SPI1 $SPI2 413do_esp ns4 10.0.3.10 10.0.3.1 10.0.2.0/24 10.0.1.0/24 $SPI2 $SPI1 414do_esp ns4 dead:3::10 dead:3::1 dead:2::/64 dead:1::/64 $SPI2 $SPI1 415 416do_dummies4 ns3 417do_dummies6 ns4 418 419do_esp_policy_get_check ns3 10.0.1.0/24 10.0.2.0/24 420do_esp_policy_get_check ns4 10.0.2.0/24 10.0.1.0/24 421do_esp_policy_get_check ns3 dead:1::/64 dead:2::/64 422do_esp_policy_get_check ns4 dead:2::/64 dead:1::/64 423 424# ping to .254 should use ipsec, exception is not installed. 425check_xfrm 1 254 426if [ $? -ne 0 ]; then 427 echo "FAIL: expected ping to .254 to use ipsec tunnel" 428 ret=1 429else 430 echo "PASS: policy before exception matches" 431fi 432 433# installs exceptions 434# localip remoteip encryptdst plaindst 435do_exception ns3 10.0.3.1 10.0.3.10 10.0.2.253 10.0.2.240/28 436do_exception ns4 10.0.3.10 10.0.3.1 10.0.1.253 10.0.1.240/28 437 438do_exception ns3 dead:3::1 dead:3::10 dead:2::fd dead:2:f0::/96 439do_exception ns4 dead:3::10 dead:3::1 dead:1::fd dead:1:f0::/96 440 441check_exceptions "exceptions" 442if [ $? -ne 0 ]; then 443 ret=1 444fi 445 446# insert block policies with adjacent/overlapping netmasks 447do_overlap ns3 448 449check_exceptions "exceptions and block policies" 450if [ $? -ne 0 ]; then 451 ret=1 452fi 453 454for n in ns3 ns4;do 455 ip -net $n xfrm policy set hthresh4 28 24 hthresh6 126 125 456 sleep $((RANDOM%5)) 457done 458 459check_exceptions "exceptions and block policies after hresh changes" 460 461# full flush of policy db, check everything gets freed incl. internal meta data 462ip -net ns3 xfrm policy flush 463 464do_esp_policy ns3 10.0.3.1 10.0.3.10 10.0.1.0/24 10.0.2.0/24 465do_exception ns3 10.0.3.1 10.0.3.10 10.0.2.253 10.0.2.240/28 466 467# move inexact policies to hash table 468ip -net ns3 xfrm policy set hthresh4 16 16 469 470sleep $((RANDOM%5)) 471check_exceptions "exceptions and block policies after hthresh change in ns3" 472 473# restore original hthresh settings -- move policies back to tables 474for n in ns3 ns4;do 475 ip -net $n xfrm policy set hthresh4 32 32 hthresh6 128 128 476 sleep $((RANDOM%5)) 477done 478check_exceptions "exceptions and block policies after htresh change to normal" 479 480check_hthresh_repeat "policies with repeated htresh change" 481 482check_random_order ns3 "policies inserted in random order" 483 484for i in 1 2 3 4;do ip netns del ns$i;done 485 486exit $ret 487