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