brintos

brintos / linux-shallow public Read only

0
0
Text · 14.7 KiB · 3eeeeff Raw
487 lines · bash
1#!/bin/bash2# SPDX-License-Identifier: GPL-2.03#4# Check xfrm policy resolution.  Topology:5#6# 1.2   1.1   3.1  3.10    2.1   2.27# eth1  eth1 veth0 veth0 eth1   eth18# ns1 ---- ns3 ----- ns4 ---- ns29#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 21source lib.sh22ret=023policy_checks_ok=124 25KEY_SHA=0xdeadbeef1234567890abcdefabcdefabcdefabcd26KEY_AES=0x0123456789abcdef012345678901234527SPI1=0x128SPI2=0x229 30do_esp_policy() {31    local ns=$132    local me=$233    local remote=$334    local lnet=$435    local rnet=$536 37    # to encrypt packets as they go out (includes forwarded packets that need encapsulation)38    ip -net $ns xfrm policy add src $lnet dst $rnet dir out tmpl src $me dst $remote proto esp mode tunnel priority 100 action allow39    # to fwd decrypted packets after esp processing:40    ip -net $ns xfrm policy add src $rnet dst $lnet dir fwd tmpl src $remote dst $me proto esp mode tunnel priority 100 action allow41}42 43do_esp() {44    local ns=$145    local me=$246    local remote=$347    local lnet=$448    local rnet=$549    local spi_out=$650    local spi_in=$751 52    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 $lnet53    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 $rnet54 55    do_esp_policy $ns $me $remote $lnet $rnet56}57 58# add policies with different netmasks, to make sure kernel carries59# the policies contained within new netmask over when search tree is60# re-built.61# peer netns that are supposed to be encapsulated via esp have addresses62# in the 10.0.1.0/24 and 10.0.2.0/24 subnets, respectively.63#64# Adding a policy for '10.0.1.0/23' will make it necessary to65# alter the prefix of 10.0.1.0 subnet.66# In case new prefix overlaps with existing node, the node and all67# policies it carries need to be merged with the existing one(s).68#69# Do that here.70do_overlap()71{72    local ns=$173 74    # adds new nodes to tree (neither network exists yet in policy database).75    ip -net $ns xfrm policy add src 10.1.0.0/24 dst 10.0.0.0/24 dir fwd priority 200 action block76 77    # adds a new node in the 10.0.0.0/24 tree (dst node exists).78    ip -net $ns xfrm policy add src 10.2.0.0/24 dst 10.0.0.0/24 dir fwd priority 200 action block79 80    # adds a 10.2.0.0/23 node, but for different dst.81    ip -net $ns xfrm policy add src 10.2.0.0/23 dst 10.0.1.0/24 dir fwd priority 200 action block82 83    # dst now overlaps with the 10.0.1.0/24 ESP policy in fwd.84    # kernel must 'promote' existing one (10.0.0.0/24) to 10.0.0.0/23.85    # But 10.0.0.0/23 also includes existing 10.0.1.0/24, so that node86    # also has to be merged too, including source-sorted subtrees.87    # old:88    # 10.0.0.0/24 (node 1 in dst tree of the bin)89    #    10.1.0.0/24 (node in src tree of dst node 1)90    #    10.2.0.0/24 (node in src tree of dst node 1)91    # 10.0.1.0/24 (node 2 in dst tree of the bin)92    #    10.0.2.0/24 (node in src tree of dst node 2)93    #    10.2.0.0/24 (node in src tree of dst node 2)94    #95    # The next 'policy add' adds dst '10.0.0.0/23', which means96    # that dst node 1 and dst node 2 have to be merged including97    # the sub-tree.  As no duplicates are allowed, policies in98    # the two '10.0.2.0/24' are also merged.99    #100    # after the 'add', internal search tree should look like this:101    # 10.0.0.0/23 (node in dst tree of bin)102    #     10.0.2.0/24 (node in src tree of dst node)103    #     10.1.0.0/24 (node in src tree of dst node)104    #     10.2.0.0/24 (node in src tree of dst node)105    #106    # 10.0.0.0/24 and 10.0.1.0/24 nodes have been merged as 10.0.0.0/23.107    ip -net $ns xfrm policy add src 10.1.0.0/24 dst 10.0.0.0/23 dir fwd priority 200 action block108 109    # similar to above: add policies (with partially random address), with shrinking prefixes.110    for p in 29 28 27;do111      for k in $(seq 1 32); do112       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/null113      done114    done115}116 117do_esp_policy_get_check() {118    local ns=$1119    local lnet=$2120    local rnet=$3121 122    ip -net $ns xfrm policy get src $lnet dst $rnet dir out > /dev/null123    if [ $? -ne 0 ] && [ $policy_checks_ok -eq 1 ] ;then124        policy_checks_ok=0125        echo "FAIL: ip -net $ns xfrm policy get src $lnet dst $rnet dir out"126        ret=1127    fi128 129    ip -net $ns xfrm policy get src $rnet dst $lnet dir fwd > /dev/null130    if [ $? -ne 0 ] && [ $policy_checks_ok -eq 1 ] ;then131        policy_checks_ok=0132        echo "FAIL: ip -net $ns xfrm policy get src $rnet dst $lnet dir fwd"133        ret=1134    fi135}136 137do_exception() {138    local ns=$1139    local me=$2140    local remote=$3141    local encryptip=$4142    local plain=$5143 144    # network $plain passes without tunnel145    ip -net $ns xfrm policy add dst $plain dir out priority 10 action allow146 147    # direct policy for $encryptip, use tunnel, higher prio takes precedence148    ip -net $ns xfrm policy add dst $encryptip dir out tmpl src $me dst $remote proto esp mode tunnel priority 1 action allow149}150 151# policies that are not supposed to match any packets generated in this test.152do_dummies4() {153    local ns=$1154 155    for i in $(seq 10 16);do156      # dummy policy with wildcard src/dst.157      echo netns exec $ns ip xfrm policy add src 0.0.0.0/0 dst 10.$i.99.0/30 dir out action block158      echo netns exec $ns ip xfrm policy add src 10.$i.99.0/30 dst 0.0.0.0/0 dir out action block159      for j in $(seq 32 64);do160        echo netns exec $ns ip xfrm policy add src 10.$i.1.0/30 dst 10.$i.$j.0/30 dir out action block161        # silly, as it encompasses the one above too, but its allowed:162        echo netns exec $ns ip xfrm policy add src 10.$i.1.0/29 dst 10.$i.$j.0/29 dir out action block163        # and yet again, even more broad one.164        echo netns exec $ns ip xfrm policy add src 10.$i.1.0/24 dst 10.$i.$j.0/24 dir out action block165        echo netns exec $ns ip xfrm policy add src 10.$i.$j.0/24 dst 10.$i.1.0/24 dir fwd action block166      done167    done | ip -batch /dev/stdin168}169 170do_dummies6() {171    local ns=$1172 173    for i in $(seq 10 16);do174      for j in $(seq 32 64);do175       echo netns exec $ns ip xfrm policy add src dead:$i::/64 dst dead:$i:$j::/64 dir out action block176       echo netns exec $ns ip xfrm policy add src dead:$i:$j::/64 dst dead:$i::/24 dir fwd action block177      done178    done | ip -batch /dev/stdin179}180 181check_ipt_policy_count()182{183	ns=$1184 185	ip netns exec $ns iptables-save -c |grep policy | ( read c rest186		ip netns exec $ns iptables -Z187		if [ x"$c" = x'[0:0]' ]; then188			exit 0189		elif [ x"$c" = x ]; then190			echo "ERROR: No counters"191			ret=1192			exit 111193		else194			exit 1195		fi196	)197}198 199check_xfrm() {200	# 0: iptables -m policy rule count == 0201	# 1: iptables -m policy rule count != 0202	rval=$1203	ip=$2204	local lret=0205 206	ip netns exec ${ns[1]} ping -q -c 1 10.0.2.$ip > /dev/null207 208	check_ipt_policy_count ${ns[3]}209	if [ $? -ne $rval ] ; then210		lret=1211	fi212	check_ipt_policy_count ${ns[4]}213	if [ $? -ne $rval ] ; then214		lret=1215	fi216 217	ip netns exec ${ns[2]} ping -q -c 1 10.0.1.$ip > /dev/null218 219	check_ipt_policy_count ${ns[3]}220	if [ $? -ne $rval ] ; then221		lret=1222	fi223	check_ipt_policy_count ${ns[4]}224	if [ $? -ne $rval ] ; then225		lret=1226	fi227 228	return $lret229}230 231check_exceptions()232{233	logpostfix="$1"234	local lret=0235 236	# ping to .254 should be excluded from the tunnel (exception is in place).237	check_xfrm 0 254238	if [ $? -ne 0 ]; then239		echo "FAIL: expected ping to .254 to fail ($logpostfix)"240		lret=1241	else242		echo "PASS: ping to .254 bypassed ipsec tunnel ($logpostfix)"243	fi244 245	# ping to .253 should use use ipsec due to direct policy exception.246	check_xfrm 1 253247	if [ $? -ne 0 ]; then248		echo "FAIL: expected ping to .253 to use ipsec tunnel ($logpostfix)"249		lret=1250	else251		echo "PASS: direct policy matches ($logpostfix)"252	fi253 254	# ping to .2 should use ipsec.255	check_xfrm 1 2256	if [ $? -ne 0 ]; then257		echo "FAIL: expected ping to .2 to use ipsec tunnel ($logpostfix)"258		lret=1259	else260		echo "PASS: policy matches ($logpostfix)"261	fi262 263	return $lret264}265 266check_hthresh_repeat()267{268	local log=$1269	i=0270 271	for i in $(seq 1 10);do272		ip -net ${ns[1]} 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 || break273		ip -net ${ns[1]} xfrm policy set hthresh6 0 28 || break274 275		ip -net ${ns[1]} xfrm policy update src e000:0001::0000 dst ff01::01 dir in tmpl src :: dst :: proto esp mode tunnel priority 100 action allow || break276		ip -net ${ns[1]} xfrm policy set hthresh6 0 28 || break277	done278 279	if [ $i -ne 10 ] ;then280		echo "FAIL: $log" 1>&2281		ret=1282		return 1283	fi284 285	echo "PASS: $log"286	return 0287}288 289# insert non-overlapping policies in a random order and check that290# all of them can be fetched using the traffic selectors.291check_random_order()292{293	local ns=$1294	local log=$2295 296	for i in $(seq 50); do297		ip -net $ns xfrm policy flush298		for j in $(seq 0 16 255 | sort -R); do299			ip -net $ns xfrm policy add dst $j.0.0.0/24 dir out priority 10 action allow300		done301		for j in $(seq 0 16 255); do302			if ! ip -net $ns xfrm policy get dst $j.0.0.0/24 dir out > /dev/null; then303				echo "FAIL: $log" 1>&2304				return 1305			fi306		done307	done308 309	for i in $(seq 50); do310		ip -net $ns xfrm policy flush311		for j in $(seq 0 16 255 | sort -R); do312			local addr=$(printf "e000:0000:%02x00::/56" $j)313			ip -net $ns xfrm policy add dst $addr dir out priority 10 action allow314		done315		for j in $(seq 0 16 255); do316			local addr=$(printf "e000:0000:%02x00::/56" $j)317			if ! ip -net $ns xfrm policy get dst $addr dir out > /dev/null; then318				echo "FAIL: $log" 1>&2319				return 1320			fi321		done322	done323 324	ip -net $ns xfrm policy flush325 326	echo "PASS: $log"327	return 0328}329 330#check for needed privileges331if [ "$(id -u)" -ne 0 ];then332	echo "SKIP: Need root privileges"333	exit $ksft_skip334fi335 336ip -Version 2>/dev/null >/dev/null337if [ $? -ne 0 ];then338	echo "SKIP: Could not run test without the ip tool"339	exit $ksft_skip340fi341 342# needed to check if policy lookup got valid ipsec result343iptables --version 2>/dev/null >/dev/null344if [ $? -ne 0 ];then345	echo "SKIP: Could not run test without iptables tool"346	exit $ksft_skip347fi348 349setup_ns ns1 ns2 ns3 ns4350ns[1]=$ns1351ns[2]=$ns2352ns[3]=$ns3353ns[4]=$ns4354 355DEV=veth0356ip link add $DEV netns ${ns[1]} type veth peer name eth1 netns ${ns[3]}357ip link add $DEV netns ${ns[2]} type veth peer name eth1 netns ${ns[4]}358 359ip link add $DEV netns ${ns[3]} type veth peer name veth0 netns ${ns[4]}360 361DEV=veth0362for i in 1 2; do363    ip -net ${ns[$i]} link set $DEV up364    ip -net ${ns[$i]} addr add 10.0.$i.2/24 dev $DEV365    ip -net ${ns[$i]} addr add dead:$i::2/64 dev $DEV366 367    ip -net ${ns[$i]} addr add 10.0.$i.253 dev $DEV368    ip -net ${ns[$i]} addr add 10.0.$i.254 dev $DEV369    ip -net ${ns[$i]} addr add dead:$i::fd dev $DEV370    ip -net ${ns[$i]} addr add dead:$i::fe dev $DEV371done372 373for i in 3 4; do374    ip -net ${ns[$i]} link set eth1 up375    ip -net ${ns[$i]} link set veth0 up376done377 378ip -net ${ns[1]} route add default via 10.0.1.1379ip -net ${ns[2]} route add default via 10.0.2.1380 381ip -net ${ns[3]} addr add 10.0.1.1/24 dev eth1382ip -net ${ns[3]} addr add 10.0.3.1/24 dev veth0383ip -net ${ns[3]} addr add 2001:1::1/64 dev eth1384ip -net ${ns[3]} addr add 2001:3::1/64 dev veth0385 386ip -net ${ns[3]} route add default via 10.0.3.10387 388ip -net ${ns[4]} addr add 10.0.2.1/24 dev eth1389ip -net ${ns[4]} addr add 10.0.3.10/24 dev veth0390ip -net ${ns[4]} addr add 2001:2::1/64 dev eth1391ip -net ${ns[4]} addr add 2001:3::10/64 dev veth0392ip -net ${ns[4]} route add default via 10.0.3.1393 394for j in 4 6; do395	for i in 3 4;do396		ip netns exec ${ns[$i]} sysctl net.ipv$j.conf.eth1.forwarding=1 > /dev/null397		ip netns exec ${ns[$i]} sysctl net.ipv$j.conf.veth0.forwarding=1 > /dev/null398	done399done400 401# abuse iptables rule counter to check if ping matches a policy402ip netns exec ${ns[3]} iptables -p icmp -A FORWARD -m policy --dir out --pol ipsec403ip netns exec ${ns[4]} iptables -p icmp -A FORWARD -m policy --dir out --pol ipsec404if [ $? -ne 0 ];then405	echo "SKIP: Could not insert iptables rule"406	cleanup_ns $ns1 $ns2 $ns3 $ns4407	exit $ksft_skip408fi409 410#          localip  remoteip  localnet    remotenet411do_esp ${ns[3]} 10.0.3.1 10.0.3.10 10.0.1.0/24 10.0.2.0/24 $SPI1 $SPI2412do_esp ${ns[3]} dead:3::1 dead:3::10 dead:1::/64 dead:2::/64 $SPI1 $SPI2413do_esp ${ns[4]} 10.0.3.10 10.0.3.1 10.0.2.0/24 10.0.1.0/24 $SPI2 $SPI1414do_esp ${ns[4]} dead:3::10 dead:3::1 dead:2::/64 dead:1::/64 $SPI2 $SPI1415 416do_dummies4 ${ns[3]}417do_dummies6 ${ns[4]}418 419do_esp_policy_get_check ${ns[3]} 10.0.1.0/24 10.0.2.0/24420do_esp_policy_get_check ${ns[4]} 10.0.2.0/24 10.0.1.0/24421do_esp_policy_get_check ${ns[3]} dead:1::/64 dead:2::/64422do_esp_policy_get_check ${ns[4]} dead:2::/64 dead:1::/64423 424# ping to .254 should use ipsec, exception is not installed.425check_xfrm 1 254426if [ $? -ne 0 ]; then427	echo "FAIL: expected ping to .254 to use ipsec tunnel"428	ret=1429else430	echo "PASS: policy before exception matches"431fi432 433# installs exceptions434#                localip  remoteip   encryptdst  plaindst435do_exception ${ns[3]} 10.0.3.1 10.0.3.10 10.0.2.253 10.0.2.240/28436do_exception ${ns[4]} 10.0.3.10 10.0.3.1 10.0.1.253 10.0.1.240/28437 438do_exception ${ns[3]} dead:3::1 dead:3::10 dead:2::fd  dead:2:f0::/96439do_exception ${ns[4]} dead:3::10 dead:3::1 dead:1::fd  dead:1:f0::/96440 441check_exceptions "exceptions"442if [ $? -ne 0 ]; then443	ret=1444fi445 446# insert block policies with adjacent/overlapping netmasks447do_overlap ${ns[3]}448 449check_exceptions "exceptions and block policies"450if [ $? -ne 0 ]; then451	ret=1452fi453 454for n in ${ns[3]} ${ns[4]};do455	ip -net $n xfrm policy set hthresh4 28 24 hthresh6 126 125456	sleep $((RANDOM%5))457done458 459check_exceptions "exceptions and block policies after hresh changes"460 461# full flush of policy db, check everything gets freed incl. internal meta data462ip -net ${ns[3]} xfrm policy flush463 464do_esp_policy ${ns[3]} 10.0.3.1 10.0.3.10 10.0.1.0/24 10.0.2.0/24465do_exception ${ns[3]} 10.0.3.1 10.0.3.10 10.0.2.253 10.0.2.240/28466 467# move inexact policies to hash table468ip -net ${ns[3]} xfrm policy set hthresh4 16 16469 470sleep $((RANDOM%5))471check_exceptions "exceptions and block policies after hthresh change in ns3"472 473# restore original hthresh settings -- move policies back to tables474for n in ${ns[3]} ${ns[4]};do475	ip -net $n xfrm policy set hthresh4 32 32 hthresh6 128 128476	sleep $((RANDOM%5))477done478check_exceptions "exceptions and block policies after htresh change to normal"479 480check_hthresh_repeat "policies with repeated htresh change"481 482check_random_order ${ns[3]} "policies inserted in random order"483 484cleanup_ns $ns1 $ns2 $ns3 $ns4485 486exit $ret487