1# $NetBSD: t_ipsec_natt.sh,v 1.5 2020/06/05 03:24:58 knakahara Exp $ 2# 3# Copyright (c) 2018 Internet Initiative Japan Inc. 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25# POSSIBILITY OF SUCH DAMAGE. 26# 27 28SOCK_LOCAL_A=unix://ipsec_natt_local_a 29SOCK_LOCAL_B=unix://ipsec_natt_local_b 30SOCK_NAT=unix://ipsec_natt_nat 31SOCK_REMOTE=unix://ipsec_natt_remote 32BUS_LOCAL=./bus_ipsec_natt_local 33BUS_NAT=./bus_ipsec_natt_nat 34 35DEBUG=${DEBUG:-false} 36 37setup_servers() 38{ 39 40 rump_server_crypto_start $SOCK_LOCAL_A netipsec ipsec 41 rump_server_crypto_start $SOCK_LOCAL_B netipsec ipsec 42 rump_server_npf_start $SOCK_NAT 43 rump_server_crypto_start $SOCK_REMOTE netipsec ipsec 44 rump_server_add_iface $SOCK_LOCAL_A shmif0 $BUS_LOCAL 45 rump_server_add_iface $SOCK_LOCAL_B shmif0 $BUS_LOCAL 46 rump_server_add_iface $SOCK_NAT shmif0 $BUS_LOCAL 47 rump_server_add_iface $SOCK_NAT shmif1 $BUS_NAT 48 rump_server_add_iface $SOCK_REMOTE shmif0 $BUS_NAT 49} 50 51setup_ipsecif() 52{ 53 local sock=$1 54 local ifid=$2 55 local src_ip=$3 56 local src_port=$4 57 local dst_ip=$5 58 local dst_port=$6 59 local ipsecif_ip=$7 60 local peer_ip=$8 61 62 export RUMP_SERVER=$sock 63 rump_server_add_iface $sock ipsec$ifid 64 atf_check -s exit:0 rump.ifconfig ipsec$ifid link0 # enable NAT-T 65 atf_check -s exit:0 rump.ifconfig ipsec$ifid tunnel ${src_ip},${src_port} ${dst_ip},${dst_port} 66 atf_check -s exit:0 rump.ifconfig ipsec$ifid ${ipsecif_ip}/32 67 atf_check -s exit:0 -o ignore \ 68 rump.route -n add ${peer_ip}/32 $ipsecif_ip 69} 70 71add_sa() 72{ 73 local sock=$1 74 local proto=$2 75 local algo_args="$3" 76 local src_ip=$4 77 local src_port=$5 78 local dst_ip=$6 79 local dst_port=$7 80 local out_spi=$8 81 local in_spi=$9 82 local tmpfile=./tmp 83 84 export RUMP_SERVER=$sock 85 cat > $tmpfile <<-EOF 86 add $src_ip [$src_port] $dst_ip [$dst_port] $proto $out_spi -m transport $algo_args; 87 add $dst_ip [$dst_port] $src_ip [$src_port] $proto $in_spi -m transport $algo_args; 88 EOF 89 $DEBUG && cat $tmpfile 90 atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile 91 # XXX it can be expired if $lifetime is very short 92 #check_sa_entries $SOCK_LOCAL $ip_local $ip_remote 93} 94 95prepare_file() 96{ 97 local file=$1 98 local data="0123456789" 99 100 touch $file 101 for i in `seq 1 512` 102 do 103 echo $data >> $file 104 done 105} 106 107build_npf_conf() 108{ 109 local outfile=$1 110 local localnet=$2 111 112 cat > $outfile <<-EOF 113 set bpf.jit off 114 \$int_if = inet4(shmif0) 115 \$ext_if = inet4(shmif1) 116 \$localnet = { $localnet } 117 map \$ext_if dynamic \$localnet -> \$ext_if 118 group "external" on \$ext_if { 119 pass stateful out final all 120 } 121 group "internal" on \$int_if { 122 block in all 123 pass in final from \$localnet 124 pass out final all 125 } 126 group default { 127 pass final on lo0 all 128 block all 129 } 130 EOF 131} 132 133PIDSFILE=./terminator.pids 134start_natt_terminator() 135{ 136 local sock=$1 137 local ip=$2 138 local port=$3 139 local pidsfile=$4 140 local backup=$RUMP_SERVER 141 local pid= 142 local terminator="$(atf_get_srcdir)/../ipsec/natt_terminator" 143 144 export RUMP_SERVER=$sock 145 146 env LD_PRELOAD=/usr/lib/librumphijack.so \ 147 $terminator $ip $port & 148 pid=$! 149 if [ ! -f $PIDSFILE ]; then 150 touch $PIDSFILE 151 fi 152 echo $pid >> $PIDSFILE 153 154 $DEBUG && rump.netstat -a -f inet 155 156 export RUMP_SERVER=$backup 157 158 sleep 1 159} 160 161stop_natt_terminators() 162{ 163 local pid= 164 165 if [ ! -f $PIDSFILE ]; then 166 return 167 fi 168 169 for pid in $(cat $PIDSFILE); do 170 kill -9 $pid 171 done 172 rm -f $PIDSFILE 173} 174 175check_ping_packets() 176{ 177 local sock=$1 178 local bus=$2 179 local from_ip=$3 180 local to_ip=$4 181 182 local outfile=./out.ping 183 184 extract_new_packets $bus > $outfile 185 186 export RUMP_SERVER=$sock 187 atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $to_ip 188 189 extract_new_packets $bus > $outfile 190 $DEBUG && cat $outfile 191 atf_check -s exit:0 \ 192 -o match:"$from_ip > $to_ip: ICMP echo request" \ 193 cat $outfile 194 atf_check -s exit:0 \ 195 -o match:"$to_ip > $from_ip: ICMP echo reply" \ 196 cat $outfile 197} 198 199check_ping_packets_over_ipsecif() 200{ 201 local sock=$1 202 local bus=$2 203 local to_ip=$3 204 local nat_from_ip=$4 205 local nat_from_port=$5 206 local nat_to_ip=$6 207 local nat_to_port=$7 208 209 local outfile=./out.ping_over_ipsecif 210 211 extract_new_packets $bus > $outfile 212 213 export RUMP_SERVER=$sock 214 atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 7 $to_ip 215 216 # Check both ports and UDP encapsulation 217 extract_new_packets $bus > $outfile 218 $DEBUG && cat $outfile 219 atf_check -s exit:0 \ 220 -o match:"${nat_from_ip}\.$nat_from_port > ${nat_to_ip}\.${nat_to_port}: UDP-encap" \ 221 cat $outfile 222 atf_check -s exit:0 \ 223 -o match:"${nat_to_ip}\.${nat_to_port} > ${nat_from_ip}\.${nat_from_port}: UDP-encap" \ 224 cat $outfile 225} 226 227check_tcp_com_prepare() 228{ 229 local server_sock=$1 230 local client_sock=$2 231 local bus=$3 232 local to_ip=$4 233 local nat_from_ip=$5 234 local nat_to_ip=$6 235 236 local outfile=./out.prepare 237 local file_send=./file.send.prepare 238 local file_recv=./file.recv.prepare 239 240 extract_new_packets $bus > $outfile 241 242 start_nc_server $server_sock 4501 $file_recv ipv4 243 244 prepare_file $file_send 245 export RUMP_SERVER=$client_sock 246 atf_check -s exit:0 $HIJACKING nc -w 3 $to_ip 4501 < $file_send 247 atf_check -s exit:0 diff -q $file_send $file_recv 248 extract_new_packets $bus > $outfile 249 $DEBUG && cat $outfile 250 atf_check -s exit:0 \ 251 -o match:"${nat_from_ip}\.[0-9]+ > ${nat_to_ip}\.4501" \ 252 cat $outfile 253 atf_check -s exit:0 \ 254 -o match:"${nat_to_ip}\.4501 > ${nat_from_ip}\.[0-9]+" \ 255 cat $outfile 256 257 stop_nc_server 258} 259 260check_tcp_com_over_ipsecif() 261{ 262 local server_sock=$1 263 local client_sock=$2 264 local bus=$3 265 local to_ip=$4 266 local nat_from_ip=$5 267 local nat_from_port=$6 268 local nat_to_ip=$7 269 local nat_to_port=$8 270 271 local outfile=./out.ipsecif 272 local file_send=./file.send.ipsecif 273 local file_recv=./file.recv.ipsecif 274 275 extract_new_packets $bus > $outfile 276 277 start_nc_server $server_sock 4501 $file_recv ipv4 278 prepare_file $file_send 279 export RUMP_SERVER=$client_sock 280 atf_check -s exit:0 -o ignore $HIJACKING nc -w 7 $to_ip 4501 < $file_send 281 atf_check -s exit:0 diff -q $file_send $file_recv 282 stop_nc_server 283 284 # Check both ports and UDP encapsulation 285 extract_new_packets $bus > $outfile 286 $DEBUG && cat $outfile 287 atf_check -s exit:0 \ 288 -o match:"${nat_from_ip}\.$nat_from_port > ${nat_to_ip}\.${nat_to_port}: UDP-encap" \ 289 cat $outfile 290 atf_check -s exit:0 \ 291 -o match:"${nat_to_ip}\.${nat_to_port} > ${nat_from_ip}\.${nat_from_port}: UDP-encap" \ 292 cat $outfile 293} 294 295test_ipsecif_natt_transport() 296{ 297 local algo=$1 298 local ip_local_a=192.168.0.2 299 local ip_local_b=192.168.0.3 300 local ip_nat_local=192.168.0.1 301 local ip_nat_remote=10.0.0.1 302 local ip_remote=10.0.0.2 303 local subnet_local=192.168.0.0 304 local ip_local_ipsecif_a=172.16.100.1 305 local ip_local_ipsecif_b=172.16.110.1 306 local ip_remote_ipsecif_a=172.16.10.1 307 local ip_remote_ipsecif_b=172.16.11.1 308 309 local npffile=./npf.conf 310 local file_send=./file.send 311 local algo_args="$(generate_algo_args esp-udp $algo)" 312 local pid= port_a= port_b= 313 314 setup_servers 315 316 export RUMP_SERVER=$SOCK_LOCAL_A 317 atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0 318 atf_check -s exit:0 rump.ifconfig shmif0 $ip_local_a/24 319 atf_check -s exit:0 -o ignore \ 320 rump.route -n add default $ip_nat_local 321 322 export RUMP_SERVER=$SOCK_LOCAL_B 323 atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0 324 atf_check -s exit:0 rump.ifconfig shmif0 $ip_local_b/24 325 atf_check -s exit:0 -o ignore \ 326 rump.route -n add default $ip_nat_local 327 328 export RUMP_SERVER=$SOCK_NAT 329 atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0 330 atf_check -s exit:0 rump.ifconfig shmif0 $ip_nat_local/24 331 atf_check -s exit:0 rump.ifconfig shmif1 $ip_nat_remote/24 332 atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.forwarding=1 333 334 export RUMP_SERVER=$SOCK_REMOTE 335 atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0 336 atf_check -s exit:0 rump.ifconfig shmif0 $ip_remote/24 337 atf_check -s exit:0 -o ignore \ 338 rump.route -n add -net $subnet_local $ip_nat_remote 339 340 # There is no NAT/NAPT. ping should just work. 341 check_ping_packets $SOCK_LOCAL_A $BUS_NAT $ip_local_a $ip_remote 342 check_ping_packets $SOCK_LOCAL_B $BUS_NAT $ip_local_b $ip_remote 343 344 # Setup an NAPT with npf 345 build_npf_conf $npffile "$subnet_local/24" 346 347 export RUMP_SERVER=$SOCK_NAT 348 atf_check -s exit:0 $HIJACKING_NPF npfctl reload $npffile 349 atf_check -s exit:0 $HIJACKING_NPF npfctl start 350 $DEBUG && ${HIJACKING},"blanket=/dev/npf" npfctl show 351 352 # There is an NAPT. ping works but source IP/port are translated 353 check_ping_packets $SOCK_LOCAL_A $BUS_NAT $ip_nat_remote $ip_remote 354 check_ping_packets $SOCK_LOCAL_B $BUS_NAT $ip_nat_remote $ip_remote 355 356 # Try TCP communications just in case 357 check_tcp_com_prepare $SOCK_REMOTE $SOCK_LOCAL_A $BUS_NAT \ 358 $ip_remote $ip_nat_remote $ip_remote 359 check_tcp_com_prepare $SOCK_REMOTE $SOCK_LOCAL_B $BUS_NAT \ 360 $ip_remote $ip_nat_remote $ip_remote 361 362 # Launch a nc server as a terminator of NAT-T on outside the NAPT 363 start_natt_terminator $SOCK_REMOTE $ip_remote 4500 364 echo zzz > $file_send 365 366 #################### Test for primary ipsecif(4) NAT-T. 367 368 export RUMP_SERVER=$SOCK_LOCAL_A 369 # Send a UDP packet to the remote server at port 4500 from the local 370 # host of port 4500. This makes a mapping on the NAPT between them 371 atf_check -s exit:0 $HIJACKING \ 372 nc -u -w 3 -p 4500 $ip_remote 4500 < $file_send 373 # Launch a nc server as a terminator of NAT-T on inside the NAPT, 374 # taking over port 4500 of the local host. 375 start_natt_terminator $SOCK_LOCAL_A $ip_local_a 4500 376 377 # We need to keep the servers for NAT-T 378 379 export RUMP_SERVER=$SOCK_LOCAL_A 380 $DEBUG && rump.netstat -na -f inet 381 export RUMP_SERVER=$SOCK_REMOTE 382 $DEBUG && rump.netstat -na -f inet 383 384 # Get a translated port number from 4500 on the NAPT 385 export RUMP_SERVER=$SOCK_NAT 386 $DEBUG && $HIJACKING_NPF npfctl list 387 # 192.168.0.2:4500 10.0.0.2:4500 via shmif1:65248 388 port_a=$(get_natt_port $ip_local_a $ip_nat_remote) 389 $DEBUG && echo port_a=$port_a 390 if [ -z "$port_a" ]; then 391 atf_fail "Failed to get a translated port on NAPT" 392 fi 393 394 # Setup ESP-UDP ipsecif(4) for first client under NAPT 395 setup_ipsecif $SOCK_LOCAL_A 0 $ip_local_a 4500 $ip_remote 4500 \ 396 $ip_local_ipsecif_a $ip_remote_ipsecif_a 397 setup_ipsecif $SOCK_REMOTE 0 $ip_remote 4500 $ip_nat_remote $port_a \ 398 $ip_remote_ipsecif_a $ip_local_ipsecif_a 399 400 add_sa $SOCK_LOCAL_A "esp-udp" "$algo_args" \ 401 $ip_local_a 4500 $ip_remote 4500 10000 10001 402 add_sa $SOCK_REMOTE "esp-udp" "$algo_args" \ 403 $ip_remote 4500 $ip_nat_remote $port_a 10001 10000 404 405 export RUMP_SERVER=$SOCK_LOCAL_A 406 # ping should still work 407 atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_remote 408 409 # Try ping over the ESP-UDP ipsecif(4) 410 check_ping_packets_over_ipsecif $SOCK_LOCAL_A $BUS_NAT \ 411 $ip_remote_ipsecif_a $ip_nat_remote $port_a $ip_remote 4500 412 413 # Try TCP communications over the ESP-UDP ipsecif(4) 414 check_tcp_com_over_ipsecif $SOCK_REMOTE $SOCK_LOCAL_A $BUS_NAT \ 415 $ip_remote_ipsecif_a $ip_nat_remote $port_a $ip_remote 4500 416 417 #################### Test for secondary ipsecif(4) NAT-T. 418 419 export RUMP_SERVER=$SOCK_REMOTE 420 $HIJACKING setkey -D 421 $HIJACKING setkey -DP 422 423 export RUMP_SERVER=$SOCK_LOCAL_B 424 # Send a UDP packet to the remote server at port 4500 from the local 425 # host of port 4500. This makes a mapping on the NAPT between them 426 atf_check -s exit:0 $HIJACKING \ 427 nc -u -w 3 -p 4500 $ip_remote 4500 < $file_send 428 # Launch a nc server as a terminator of NAT-T on inside the NAPT, 429 # taking over port 4500 of the local host. 430 start_natt_terminator $SOCK_LOCAL_B $ip_local_b 4500 431 432 # We need to keep the servers for NAT-T 433 434 export RUMP_SERVER=$SOCK_LOCAL_B 435 $DEBUG && rump.netstat -na -f inet 436 export RUMP_SERVER=$SOCK_REMOTE 437 $DEBUG && rump.netstat -na -f inet 438 439 # Get a translated port number from 4500 on the NAPT 440 export RUMP_SERVER=$SOCK_NAT 441 $DEBUG && $HIJACKING_NPF npfctl list 442 # 192.168.0.2:4500 10.0.0.2:4500 via shmif1:65248 443 port_b=$(get_natt_port $ip_local_b $ip_nat_remote) 444 $DEBUG && echo port_b=$port_b 445 if [ -z "$port_b" ]; then 446 atf_fail "Failed to get a translated port on NAPT" 447 fi 448 449 # Setup ESP-UDP ipsecif(4) for first client under NAPT 450 setup_ipsecif $SOCK_LOCAL_B 0 $ip_local_b 4500 $ip_remote 4500 \ 451 $ip_local_ipsecif_b $ip_remote_ipsecif_b 452 setup_ipsecif $SOCK_REMOTE 1 $ip_remote 4500 $ip_nat_remote $port_b \ 453 $ip_remote_ipsecif_b $ip_local_ipsecif_b 454 455 check_ping_packets_over_ipsecif $SOCK_LOCAL_A $BUS_NAT \ 456 $ip_remote_ipsecif_a $ip_nat_remote $port_a $ip_remote 4500 457 458 add_sa $SOCK_LOCAL_B "esp-udp" "$algo_args" \ 459 $ip_local_b 4500 $ip_remote 4500 11000 11001 460 add_sa $SOCK_REMOTE "esp-udp" "$algo_args" \ 461 $ip_remote 4500 $ip_nat_remote $port_b 11001 11000 462 463 export RUMP_SERVER=$SOCK_LOCAL_B 464 # ping should still work 465 atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_remote 466 467 # Try ping over the ESP-UDP ipsecif(4) 468 check_ping_packets_over_ipsecif $SOCK_LOCAL_B $BUS_NAT \ 469 $ip_remote_ipsecif_b $ip_nat_remote $port_b $ip_remote 4500 470 471 472 # Try TCP communications over the ESP-UDP ipsecif(4) 473 check_tcp_com_over_ipsecif $SOCK_REMOTE $SOCK_LOCAL_B $BUS_NAT \ 474 $ip_remote_ipsecif_b $ip_nat_remote $port_b $ip_remote 4500 475 476 # Try ping over the ESP-UDP ipsecif(4) for primary again 477 check_ping_packets_over_ipsecif $SOCK_LOCAL_A $BUS_NAT \ 478 $ip_remote_ipsecif_a $ip_nat_remote $port_a $ip_remote 4500 479 480 # Try TCP communications over the ESP-UDP ipsecif(4) for primary again 481 check_tcp_com_over_ipsecif $SOCK_REMOTE $SOCK_LOCAL_A $BUS_NAT \ 482 $ip_remote_ipsecif_a $ip_nat_remote $port_a $ip_remote 4500 483 484 # Kill the NAT-T terminator 485 stop_natt_terminators 486} 487 488add_test_ipsecif_natt_transport() 489{ 490 local algo=$1 491 local _algo=$(echo $algo | sed 's/-//g') 492 local name= desc= 493 494 desc="Test ipsecif(4) NAT-T ($algo)" 495 name="ipsecif_natt_transport_${_algo}" 496 497 atf_test_case ${name} cleanup 498 eval " 499 ${name}_head() { 500 atf_set descr \"$desc\" 501 atf_set require.progs rump_server setkey nc 502 } 503 ${name}_body() { 504 test_ipsecif_natt_transport $algo 505 rump_server_destroy_ifaces 506 } 507 ${name}_cleanup() { 508 stop_nc_server 509 stop_natt_terminators 510 \$DEBUG && dump 511 cleanup 512 } 513 " 514 atf_add_test_case ${name} 515} 516 517atf_init_test_cases() 518{ 519 local algo= 520 521 for algo in $ESP_ENCRYPTION_ALGORITHMS_MINIMUM; do 522 add_test_ipsecif_natt_transport $algo 523 done 524} 525