1#!/bin/sh 2#- 3# Copyright (c) 2010, "Bjoern A. Zeeb" <bz@FreeBSD.org> 4# Copyright (c) 2011, Sandvine Incorporated ULC. 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28# 29 30# 31# Test ipfw fwd for IPv4 and IPv6 using VIMAGE, testing that as well. 32# For no test the packet header contents must be changed but always 33# keeping the original destination. 34# 35 36case `id -u` in 370) ;; 38*) echo "ERROR: Must be run as superuser." >&2 39 exit 2 40esac 41 42epair_base() 43{ 44 local ep 45 46 ep=`ifconfig epair create` 47 expr ${ep} : '\(.*\).' 48} 49 50debug_err() 51{ 52 local _p 53 _p="$1" 54 55 case "${DEBUG}" in 56 "") ;; 57 *) 58 echo " ~~ start of debug ~~" 59 echo " ~~ left:" 60 jexec ${ljid} /sbin/ipfw show 61 echo " ~~ middle:" 62 jexec ${mjid} /sbin/ipfw show 63 echo " ~~ right:" 64 jexec ${rjid} /sbin/ipfw show 65 echo " ~~ result file:" 66 cat ${_p}.1 67 echo " ~~ log file:" 68 cat ${_p} 69 echo " ~~ end of debug ~~" 70 ;; 71 esac 72} 73 74check_cleanup_result_file() 75{ 76 local _p 77 _p="$1" 78 79 if test ! -s ${_p}.1; then 80 echo "FAIL (output file empty)." 81 debug_err ${_p} 82 else 83 read line < ${_p}.1 84 # Netcat adds 'X's in udp mode. 85 l="/${line#*/}" 86 if test "${l}" = "${_p}"; then 87 echo "PASS." 88 else 89 echo "FAIL (expected: '${_p}' got '${l}')." 90 debug_err ${_p} 91 fi 92 fi 93 94 rm -f ${_p}.1 95 rm -f ${_p} 96} 97 98# Transparent proxy scenario (local address). 99run_test_tp() 100{ 101 local _descr 102 local _sip _dip _fip _fport _dport _p 103 local _nc_af _nc_p 104 local _lport 105 descr="$1" 106 _sip="$2" 107 _dip="$3" 108 _fip="$4" 109 _fport="$5" 110 _dport="$6" 111 _p="$7" 112 _nc_af="$8" 113 114 _lport=${_dport} 115 case "${_fport}" in 116 "") _lport="${_dport}" ;; 117 *) _lport="${_fport#,}" ;; 118 esac 119 120 case "${_p}" in 121 udp) _nc_p="-u" ;; 122 esac 123 124 OUT=`mktemp -t "ipfwfwd$$-XXXXXX"` 125 echo -n "${descr} (${OUT}).." 126 ( 127 jexec ${ljid} /sbin/ipfw -f flush 128 jexec ${ljid} /sbin/ipfw -f zero 129 jexec ${mjid} /sbin/ipfw -f flush 130 jexec ${mjid} /sbin/ipfw -f zero 131 jexec ${rjid} /sbin/ipfw -f flush 132 jexec ${rjid} /sbin/ipfw -f zero 133 jexec ${mjid} /sbin/ipfw add 100 fwd ${_fip}${_fport} ${_p} from ${_sip} to ${_dip} 134 135 jexec ${mjid} /bin/sh -c "nc -w 10 ${_nc_af} -n ${_nc_p} -l ${_fip} ${_lport} > ${OUT}.1 &" 136 jexec ${rjid} /bin/sh -c "echo '${OUT}' | nc -w 1 -v ${_nc_af} -n ${_nc_p} ${_dip} ${_dport}" 137 ) > ${OUT} 2>&1 138 check_cleanup_result_file "${OUT}" 139} 140 141# Transparent redirect scenario (non-local address). 142run_test_nh() 143{ 144 local _descr 145 local _sip _dip _fip _fport _dport _p 146 local _nc_af _nc_p 147 local _lport 148 descr="$1" 149 _sip="$2" 150 _dip="$3" 151 _fip="$4" 152 _fport="$5" 153 _dport="$6" 154 _p="$7" 155 _nc_af="$8" 156 157 _lport=${_dport} 158 case "${_fport}" in 159 "") _lport="${_dport}" ;; 160 *) _lport="${_fport#,}" ;; 161 esac 162 163 case "${_p}" in 164 udp) _nc_p="-u" ;; 165 esac 166 167 OUT=`mktemp -t "ipfwfwd$$-XXXXXX"` 168 echo -n "${descr} (${OUT}).." 169 ( 170 jexec ${ljid} /sbin/ipfw -f flush 171 jexec ${ljid} /sbin/ipfw -f zero 172 jexec ${mjid} /sbin/ipfw -f flush 173 jexec ${mjid} /sbin/ipfw -f zero 174 jexec ${rjid} /sbin/ipfw -f flush 175 jexec ${rjid} /sbin/ipfw -f zero 176 jexec ${mjid} /sbin/ipfw add 100 fwd ${_fip} ${_p} from ${_sip} to ${_dip} 177 178 jexec ${ljid} /bin/sh -c "nc -w 10 ${_nc_af} -n ${_nc_p} -l ${_dip} ${_lport} > ${OUT}.1 &" 179 jexec ${rjid} /bin/sh -c "echo '${OUT}' | nc -w 1 -v ${_nc_af} -n ${_nc_p} ${_dip} ${_dport}" 180 ) > ${OUT} 2>&1 181 check_cleanup_result_file "${OUT}" 182} 183 184echo "==> Setting up test network" 185kldload -q ipfw > /dev/null 2>&1 186 187# Start left (sender) jail. 188ljid=`jail -i -c -n lef$$ host.hostname=left.example.net vnet persist` 189 190# Start middle (ipfw) jail. 191mjid=`jail -i -c -n mid$$ host.hostname=center.example.net vnet persist` 192 193# Start right (non-local ip redirects go to here) jail. 194rjid=`jail -i -c -n right$$ host.hostname=right.example.net vnet persist` 195 196echo "left ${ljid} middle ${mjid} right ${rjid}" 197 198# Create networking. 199# 200# jail: left middle right 201# ifaces: lmep:a ---- lmep:b mrep:a ---- mrep:b 202# 203 204jexec ${mjid} sysctl net.inet.ip.forwarding=1 205jexec ${mjid} sysctl net.inet6.ip6.forwarding=1 206jexec ${mjid} sysctl net.inet6.ip6.accept_rtadv=0 207 208lmep=$(epair_base) 209ifconfig ${lmep}a vnet ${ljid} 210ifconfig ${lmep}b vnet ${mjid} 211 212jexec ${ljid} ifconfig lo0 inet 127.0.0.1/8 213jexec ${ljid} ifconfig lo0 inet 192.0.2.5/32 alias # Test 9-10 214jexec ${ljid} ifconfig lo0 inet6 2001:db8:1::1/128 alias # Test 11-12 215jexec ${ljid} ifconfig ${lmep}a inet 192.0.2.1/30 up 216jexec ${ljid} ifconfig ${lmep}a inet6 2001:db8::1/64 alias 217 218jexec ${ljid} route add default 192.0.2.2 219jexec ${ljid} route add -inet6 default 2001:db8::2 220 221jexec ${mjid} ifconfig lo0 inet 127.0.0.1/8 222jexec ${mjid} ifconfig lo0 inet 192.0.2.255/32 alias # Test 1-4 223jexec ${mjid} ifconfig lo0 inet6 2001:db8:ffff::1/128 alias # Test 5-8 224jexec ${mjid} ifconfig ${lmep}b inet 192.0.2.2/30 up 225jexec ${mjid} ifconfig ${lmep}b inet6 2001:db8::2/64 alias 226jexec ${mjid} route add default 192.0.2.1 227 228mrep=$(epair_base) 229ifconfig ${mrep}a vnet ${mjid} 230ifconfig ${mrep}b vnet ${rjid} 231 232jexec ${mjid} ifconfig ${mrep}a inet 192.0.2.5/30 up 233jexec ${mjid} ifconfig ${mrep}a inet6 2001:db8:1::1/64 alias 234 235jexec ${rjid} ifconfig lo0 inet 127.0.0.1/8 236jexec ${rjid} ifconfig ${mrep}b inet 192.0.2.6/30 up 237jexec ${rjid} ifconfig ${mrep}b inet6 2001:db8:1::2/64 alias 238 239jexec ${rjid} route add default 192.0.2.5 240jexec ${rjid} route add -inet6 default 2001:db8:1::1 241 242# ------------------------------------------------------------------------------ 243# Tests 244# 245# The jails are not chrooted to they all share the same base filesystem. 246# This means we can put results into /tmp and just collect them from here. 247# 248echo "==> Running tests" 249 250#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 251i=1 252run_test_tp "TEST ${i} IPv4 UDP redirect local to other local address, same port" \ 253 192.0.2.6 192.0.2.5 192.0.2.255 "" 12345 udp "-4" 254 255i=$((i + 1)) 256run_test_tp "TEST ${i} IPv4 UDP redirect local to other local address, different port" \ 257 192.0.2.6 192.0.2.5 192.0.2.255 ",65534" 12345 udp "-4" 258 259#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 260i=$((i + 1)) 261run_test_tp "TEST ${i} IPv4 TCP redirect local to other local address, same port" \ 262 192.0.2.6 192.0.2.5 192.0.2.255 "" 12345 tcp "-4" 263 264i=$((i + 1)) 265run_test_tp "TEST ${i} IPv4 TCP redirect local to other local address, different port" \ 266 192.0.2.6 192.0.2.5 192.0.2.255 ",65534" 12345 tcp "-4" 267 268#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 269i=$((i + 1)) 270run_test_tp "TEST ${i} IPv4 UDP redirect foreign to local address, same port" \ 271 192.0.2.6 192.0.2.1 192.0.2.255 "" 12345 udp "-4" 272 273i=$((i + 1)) 274run_test_tp "TEST ${i} IPv4 UDP redirect foreign to local address, different port" \ 275 192.0.2.6 192.0.2.1 192.0.2.255 ",65534" 12345 udp "-4" 276 277#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 278i=$((i + 1)) 279run_test_tp "TEST ${i} IPv4 TCP redirect foreign to local address, same port" \ 280 192.0.2.6 192.0.2.1 192.0.2.255 "" 12345 tcp "-4" 281 282i=$((i + 1)) 283run_test_tp "TEST ${i} IPv4 TCP redirect foreign to local address, different port" \ 284 192.0.2.6 192.0.2.1 192.0.2.255 ",65534" 12345 tcp "-4" 285 286#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 287i=$((i + 1)) 288run_test_tp "TEST ${i} IPv6 UDP redirect local to other local address, same port" \ 289 2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 "" 12345 udp "-6" 290 291i=$((i + 1)) 292run_test_tp "TEST ${i} IPv6 UDP redirect local to other local address, different port" \ 293 2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 ",65534" 12345 udp "-6" 294 295#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 296i=$((i + 1)) 297run_test_tp "TEST ${i} IPv6 TCP redirect local to other local address, same port" \ 298 2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 "" 12345 tcp "-6" 299 300i=$((i + 1)) 301run_test_tp "TEST ${i} IPv6 TCP redirect local to other local address, different port" \ 302 2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 ",65534" 12345 tcp "-6" 303 304#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 305i=$((i + 1)) 306run_test_tp "TEST ${i} IPv6 UDP redirect foreign to local address, same port" \ 307 2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 "" 12345 udp "-6" 308 309i=$((i + 1)) 310run_test_tp "TEST ${i} IPv6 UDP redirect foreign to local address, different port" \ 311 2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 ",65534" 12345 udp "-6" 312 313#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 314i=$((i + 1)) 315run_test_tp "TEST ${i} IPv6 TCP redirect foreign to local address, same port" \ 316 2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 "" 12345 tcp "-6" 317 318i=$((i + 1)) 319run_test_tp "TEST ${i} IPv6 TCP redirect foreign to local address, different port" \ 320 2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 ",65534" 12345 tcp "-6" 321 322#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 323i=$((i + 1)) 324run_test_nh "TEST ${i} IPv4 UDP redirect to foreign address" \ 325 192.0.2.6 192.0.2.5 192.0.2.1 "" 12345 udp "-4" 326 327i=$((i + 1)) 328run_test_nh "TEST ${i} IPv4 TCP redirect to foreign address" \ 329 192.0.2.6 192.0.2.5 192.0.2.1 "" 12345 tcp "-4" 330 331#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 332i=$((i + 1)) 333run_test_nh "TEST ${i} IPv6 UDP redirect to foreign address" \ 334 2001:db8:1::2 2001:db8:1::1 2001:db8::1 "" 12345 udp "-6" 335 336i=$((i + 1)) 337run_test_nh "TEST ${i} IPv6 TCP redirect to foreign address" \ 338 2001:db8:1::2 2001:db8:1::1 2001:db8::1 "" 12345 tcp "-6" 339 340################################################################################ 341# 342# Cleanup 343# 344echo "==> Cleaning up in 3 seconds" 345# Let VIMAGE network stacks settle to avoid panics while still "experimental". 346sleep 3 347 348jail -r ${rjid} 349jail -r ${mjid} 350jail -r ${ljid} 351 352for jid in ${rjid} ${mjid} ${ljid}; do 353 while : ; do 354 x=`jls -as -j ${jid} jid 2>/dev/null` 355 case "${x}" in 356 jid=*) echo "Waiting for jail ${jid} to stop." >&2 357 sleep 1 358 continue 359 ;; 360 esac 361 break 362 done 363done 364 365ifconfig ${lmep}a destroy 366ifconfig ${mrep}a destroy 367 368# end 369