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