. |-- VM_SCRIPTS | |-- IPFW_root_bin.tgz : common scripts for all VMs (see bin list) | |-- Manifest_IPFW_root_bin.txt : Manifest document for IPFW_root_bin.tgz | |-- Manifest_index.txt : Manifest document for index.html files |-- bin | |-- tcon.sh : TCP connection script | |-- tconr.sh : TCP connect with random port script | |-- tcont.sh : TCP continuous connection script | |-- tserv.sh : TCP server script for one port | |-- tserv3.sh : TCP server script for three ports | |-- ucon.sh : UDP connection script | |-- uconr.sh : UDP connect with random port script | |-- ucont.sh : UDP continuous connection script | |-- userv.sh : UDP server script for one port | |-- userv3.sh : UDP server script for three ports | `-- userv5.sh : UDP server script for five ports | |-- dnshost : | | |-- Manifest_namedb.txt : Manifest for dnshost /usr/local/etc/namedb | | |-- dnshost_usrlocaletc_namedb.tgz : Files for the above | | `-- index.html : Nginx index.html file for dnshost VM | |-- external1 : | | `-- index.html : Nginx index.html file for external1 VM | |-- external2 : | | `-- index.html : Nginx index.html file for external2 VM | |-- external3 : | | `-- index.html : Nginx index.html file for external3 VM | |-- firewall : | | |-- bsdclat464.sh : Script for Section 6.2 XLAT464 CLAT | | `-- index.html : Nginx index.html file for firewall VM | |-- firewall2 : | | |-- bsdplat464.sh : Script for Section 6.2 XLAT464 CLAT | | `-- index.html : Nginx index.html file for firewall2 VM | |-- internal : | | `-- index.html : Nginx index.html file for internal VM | `-- v6only : | `-- index.html : Nginx index.html file for v6only VM |-- _CreateAllVMs.sh : Script to create all VMs used in book |-- dnshost.sh : QEMU startup script for dnshost VM |-- external1.sh : QEMU startup script for external1 VM |-- external2.sh : QEMU startup script for external2 VM |-- external3.sh : QEMU startup script for external3 VM |-- firewall.sh : QEMU startup script for firewall VM |-- firewall2.sh : QEMU startup script for firewall2 VM |-- internal.sh : QEMU startup script for internal VM |-- mkbr.sh : Script to make host bridge and tap devices |-- runvm.sh : XFCE4 script to start VMs |-- v6only.sh : QEMU startup script for v6only VM |-- vm_envs.sh : IPFW lab environment variables `-- CODE `-- divert.c : C code for working with divert keyword
Appendix B. Scripts and Code for QEMU Lab
Table of Contents
The listing below shows how the scripts are organized on the GitHub ipfw-primer/SCRIPTS site.
All scripts are shown below in lexicographic order:
SCRIPT: VM_SCRIPTS/firewall/bsdclat464.sh #!/bin/sh # IPFW Primer # License: 3-clause BSD # Author: Jim Brown, jpb@jimby.name # Code: https://github.com/jimmyb-gh/ipfw-primer # # FreeBSD 464XLAT CLAT script for firewall VM. # # bsdclat464.sh: FreeBSD IPFW script for 464XLAT CLAT. See Section 6.2 # Usage: # /bin/sh bsdclat464.sh (run script as root) set -x kldunload ipfw_nat64 kldunload ipfw sleep 1 kldload ipfw kldload ipfw_nat64 # Create the nat64clat instance ipfw nat64clat CLAT create clat_prefix 2001:db8:aaaa::/96 plat_prefix 2001:db8:bbbb::/96 allow_private log # Allow neighbor discovery ipfw add 100 allow log icmp6 from any to any icmp6types 135,136 # pass any ip through the nat64clat instance ipfw add 150 nat64clat CLAT log ip from any to any # pass any ip through the nat64plat instance ipfw add 200 nat64clat CLAT log ip from any to 2001:db8:bbbb::/96 # allow ipv6 from any to any ipfw add 300 allow log ip6 from any to any # allow ipv4 from any to any ipfw add 400 allow log ip from any to any # 0=log with ipfwlog0, 1=log with syslog sysctl net.inet.ip.fw.verbose=0 sysctl net.inet.ip.fw.nat64_debug=1 # direct output: 1 enable, 0 disable (packet goes back into ruleset) sysctl net.inet.ip.fw.nat64_direct_output=1 ========================================================== SCRIPT: VM_SCRIPTS/firewall2/bsdplat464.sh #!/bin/sh # IPFW Primer # License: 3-clause BSD # Author: Jim Brown, jpb@jimby.name # Code: https://github.com/jimmyb-gh/ipfw-primer # # FreeBSD 464XLAT PLAT script for firewall2 VM. # # bsdplat464.sh: FreeBSD IPFW script for 464XLAT CLAT. See Section 6.2 # Usage: # /bin/sh bsdplat464.sh (run script as root) set -x kldunload ipfw_nat64 kldunload ipfw sleep 1 kldload ipfw kldload ipfw_nat64 # create the nat64 stateful instance ipfw nat64lsn NAT64 create log prefix4 203.0.112.0/24 prefix6 2001:db8:bbbb::/96 allow_private # Allow neighbor discovery ipfw add allow log icmp6 from any to any icmp6types 135,136 # Allow the nat64 outbound ipfw add nat64lsn NAT64 log ip from 2001:db8:12::/64 to 2001:db8:bbbb::/96 in ipfw add nat64lsn NAT64 log ip from any to 2001:db8:bbbb::/96 in # Allow the nat64 inbound ipfw add nat64lsn NAT64 log ip from any to 203.0.112.0/24 in # Allow ipv4 from any to any ipfw add allow log ip from any to any # Allow ipv6 from any to any ipfw add allow log ip6 from any to any # Logging: 0 interfaces, 1 syslog sysctl net.inet.ip.fw.verbose=0 # Debug nat64 sysctl net.inet.ip.fw.nat64_debug=1 # Direct output: 1 enable, 0 disable (packet goes back into ruleset) sysctl net.inet.ip.fw.nat64_direct_output=1 ========================================================== SCRIPT: _CreateAllVMs.sh #!/bin/sh # IPFW Primer # License: 3-clause BSD # Author: Jim Brown, jpb@jimby.name # Code: https://github.com/jimmyb-gh/ipfw-primer # # _CreateAllVM.sh : Create VMs for the IPFW Primer lab. Files are created in ../VM/ # echo "Running _CreateAllVMs.sh" echo echo "This script will create 8 virtual machines in ../VM/" echo read -p "DO YOU REALLY WANT TO CREATE NEW QEMU IMAGES OVERWRITING ANY EXISTING IMAGES? Answer YES to continue. " junk echo [${junk}] if [ "X${junk}" != "XYES" ] then echo "Response was [${junk}]" echo "bailing out..." exit 1 fi echo "Response was [${junk}]" echo "Ok, continuing..." #exit for i in dnshost external1 external2 external3 firewall firewall2 internal v6only do echo "Creating ${i} VM" echo qemu-img create -f qcow2 -o preallocation=full ../VM/${i}.qcow2 4G qemu-img create -f qcow2 -o preallocation=full ../VM/${i}.qcow2 4G done echo echo "Done." ========================================================== SCRIPT: tcon.sh #!/bin/sh # # location: external Vms # # sh tcon.sh PORTNUM - start up 1 connection over TCP # usage() { echo "sh tcon.sh PORTNUM" exit 1 } #echo $# if [ $# -ne 1 ] then usage else export PORT1=$1 fi # echo "PORT1 = [$PORT1]" export CONN="203.0.113.50" export COUNT=1 export MYIP=ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'
export MYNAME="external1" echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]" echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]"| ncat $CONN $PORT1 export PREVIOUS_PORT=$PORT1 while : do COUNT=expr $COUNT + 1
read -p "ncat [$COUNT] ready. Enter a valid PORTNUM: " PORT1 if [ "X$PORT1" = "X" ] then PORT1=$PREVIOUS_PORT fi echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]" echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]"| ncat $CONN $PORT1 if [ $? -ne 0 ] then echo "TCP connection [$MYIP],[$PORT1],[$COUNT] FAILED" fi PREVIOUS_PORT=$PORT1 done ========================================================== SCRIPT: tconr.sh #!/bin/sh # # location: external Vms # # sh tconr.sh PORTNUM SLEEPVAL (randomized port numbers) - start up 1 connection over TCP # usage() { echo "sh tconr.sh PORT1NUM SLEEPVAL (randomized port numbers)" exit 1 } # echo $# if [ $# -ne 2 ] then usage fi PORT1=$1 SLEEPVAL=$2 echo "PORT1 = [$PORT1]" echo "SLEEPVAL = [$SLEEPVAL]" export CONN="203.0.113.50" export COUNT=1 export MYIP=ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'
export MYNAME="external1" echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]" echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]"| ncat $CONN $PORT1 while : do COUNT=expr $COUNT + 1
# use jot(1) to get a random port between 5656 and 5659. # Connection to 5659 has no listener on firewall and will thus fail. PORT1=jot -r 1 5656 5659 $RANDOM
echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]" echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]"| ncat $CONN $PORT1 if [ $? -ne 0 ] then echo "TCP connection [$MYIP],[$PORT1],[$COUNT] FAILED" fi sleep $SLEEPVAL done ========================================================== SCRIPT: tcont.sh #!/bin/sh # # location: external Vms # # sh tcont.sh PORT1NUM SLEEPVAL - keep hammering same TCP port every SLEEPVAL # usage() { echo "sh tcont.sh PORT1NUM SLEEPVAL" exit 1 } #echo $# if [ $# -ne 2 ] then usage fi export PORT1=$1 export SLEEPVAL=$2 echo "PORT1 = [$PORT1]" echo "SLEEPVAL = [$SLEEPVAL]" export CONN="203.0.113.50" export COUNT=1 export MYIP=ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'
echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]" echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]"| ncat $CONN $PORT1 while : do COUNT=expr $COUNT + 1
echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]" echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]"| ncat $CONN $PORT1 if [ $? -ne 0 ] then echo "TCP connection [$MYIP],[$PORT1],[$COUNT] FAILED" fi sleep $SLEEPVAL done ========================================================== SCRIPT: tserv.sh #!/bin/sh # # location: firewall VMs # # tserv.sh - start up 1 listener over TCP zapall() { kill -TERM $PID1 } trap zapall SIGINT export MYIP=ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'
export PORT1=5656 echo "Starting TCP listener on [$PORT1]" ncat -l -4 -k $MYIP $PORT1 & PID1=$! wait exit ========================================================== SCRIPT: tserv3.sh #!/bin/sh # # location: firewall VMs # # tserv3.sh - start up 3 listeners over TCP zapall() { kill -TERM $PID1 $PID2 $PID3 } trap zapall SIGINT export MYIP=ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'
export PORT1=5656 export PORT2=5657 export PORT3=5658 echo "Starting TCP listeners on [$PORT1],[$PORT2],[$PORT3]" ncat -l -4 -k $MYIP $PORT1 & PID1=$! ncat -l -4 -k $MYIP $PORT2 & PID2=$! ncat -l -4 -k $MYIP $PORT3 & PID3=$! wait exit ========================================================== SCRIPT: ucon.sh #!/bin/sh # # location: external Vms # # sh ucon.sh PORTNUM - start up 1 transfer over UDP # usage() { echo "sh ucon.sh PORTNUM" exit 1 } #echo $# if [ $# -ne 1 ] then usage else export PORT1=$1 fi # echo "PORT1 = [$PORT1]" export CONN="203.0.113.50" # export CONN="10.10.10.50" export COUNT=1 export MYIP=ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'
export MYNAME="external1" echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]" echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]"| ncat -u $CONN $PORT1 export PREVIOUS_PORT=$PORT1 while : do COUNT=expr $COUNT + 1
read -p "ncat [$COUNT] ready. Enter a valid PORTNUM: " PORT1 if [ "X$PORT1" = "X" ] then PORT1=$PREVIOUS_PORT fi echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]" echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]"| ncat -u $CONN $PORT1 if [ $? -ne 0 ] then echo "UDP packet [$MYIP],[$PORT1],[$COUNT] FAILED" fi PREVIOUS_PORT=$PORT1 done ========================================================== SCRIPT: uconr.sh #!/bin/sh # # location: external Vms # usage() { echo "sh uconr.sh PORT1NUM SLEEPVAL (randomized port numbers)" exit 1 } # echo $# if [ $# -ne 2 ] then usage fi PORT1=$1 SLEEPVAL=$2 echo "PORT1 = [$PORT1]" echo "SLEEPVAL = [$SLEEPVAL]" export CONN="203.0.113.50" export COUNT=1 export MYIP=ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'
export MYNAME="external1" echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]" echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]"| ncat -u $CONN $PORT1 while : do COUNT=expr $COUNT + 1
# use jot(1) to get a random port between 5656 and 5659. # Packet on 5659 has no listener on firewall and will thus fail. PORT1=jot -r 1 5656 5659 $RANDOM
echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]" echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]"| ncat -u $CONN $PORT1 if [ $? -ne 0 ] then echo "UDP packet [$MYIP],[$PORT1],[$COUNT] FAILED" fi sleep $SLEEPVAL done ========================================================== SCRIPT: ucont.sh #!/bin/sh # # location: external Vms # # sh ucont.sh PORT1NUM SLEEPVAL - keep hammering same UDP port every SLEEPVAL # usage() { echo "sh ucont.sh PORT1NUM SLEEPVAL" exit 1 } #echo $# if [ $# -ne 2 ] then usage fi export PORT1=$1 export SLEEPVAL=$2 echo "PORT1 = [$PORT1]" echo "SLEEPVAL = [$SLEEPVAL]" # export CONN="10.10.10.50" export CONN="203.0.113.50" export COUNT=1 export MYIP=ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'
echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]" echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]"| ncat -u $CONN $PORT1 while : do COUNT=expr $COUNT + 1
# echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]" # echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]"| ncat -u $CONN $PORT1 echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]" echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]"| ncat -u $CONN $PORT1 if [ $? -ne 0 ] then echo "UDP packet [$MYIP],[$PORT1],[$COUNT] FAILED" fi sleep $SLEEPVAL done ========================================================== SCRIPT: userv.sh #!/bin/sh # # location: firewall VMs # # userv.sh PORTNUM - start up 1 listener over UDP # usage() { echo "sh userv.sh PORTNUM" exit 1 } #echo $# if [ $# -ne 1 ] then usage else PORT1=$1 fi echo "PORT1 = [$PORT1]" zapall() { kill -TERM $PID1 } trap zapall SIGINT export MYIP=ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'
echo "Starting UDP listener on [$MYIP],[$PORT1]" # echo nc -l -k -u $MYIP $PORT1 nc -l -k -u $MYIP $PORT1 & PID1=$! wait exit ========================================================== SCRIPT: userv3.sh #!/bin/sh # # location: firewall VMs # # userv3.sh - start up 3 listeners over udp zapall() { kill -TERM $PID1 $PID2 $PID3 } trap zapall SIGINT export MYIP=ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'
export PORT1=5656 export PORT2=5657 export PORT3=5658 echo "Starting UDP listeners on [$PORT1],[$PORT2],[$PORT3]" nc -l -k -u $MYIP $PORT1 & PID1=$! nc -l -k -u $MYIP $PORT2 & PID2=$! nc -l -k -u $MYIP $PORT3 & PID3=$! wait exit ========================================================== SCRIPT: userv5.sh #!/bin/sh # # location: firewall VMs # # userv5.sh - start up 5 listeners over udp zapall() { kill -TERM $PID1 $PID2 $PID3 $PID4 $PID5 } trap zapall SIGINT export MYIP=ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'
export PORT1=5656 export PORT2=5657 export PORT3=5658 export PORT4=5659 export PORT5=5660 echo "Starting UDP listeners on [$PORT1],[$PORT2],[$PORT3],[$PORT4],[$PORT5]" nc -l -k -u $MYIP $PORT1 & PID1=$! nc -l -k -u $MYIP $PORT2 & PID2=$! nc -l -k -u $MYIP $PORT3 &cd PID3=$! nc -l -k -u $MYIP $PORT4 & PID4=$! nc -l -k -u $MYIP $PORT5 & PID5=$! wait exit ========================================================== SCRIPT: dnshost.sh #!/bin/sh # IPFW Primer # License: 3-clause BSD # Author: Jim Brown, jpb@jimby.name # Code: https://github.com/jimmyb-gh/ipfw-primer # # FreeBSD QEMU VM startup script for dnshost VM. # # dnshost.sh: FreeBSD QEMU VM startup script for dnshost VM. # Usage: sudo /bin/sh dnshost.sh # Note: Set up for serial console. Start another session and telnet to the port shown. # #set -x # pick up environment for this run . ./vm_envs.sh echo [ISO=${_DNSHOST_ISO}] echo [mem=${_DNSHOST_mem}] echo [hdsize=${_DNSHOST_hdsize}] echo [img=${_DNSHOST_img}] echo [mac1=${_DNSHOST_mac1}] echo [mac2=${_DNSHOST_mac2}] echo [name=${_DNSHOST_name}] echo [tap7=${_DNSHOST_tap7}] echo [tap8=${_DNSHOST_tap8}] echo [tap11=${_DNSHOST_tap11}] echo [telnetport=${_DNSHOST_telnetport}] #exit # Note - the dnshost has two interfaces - em0 and em1. # em0 is considered the ipv4 interface and # em1 is considered the ipv6 interface. echo echo "NOTE!!! telnet server running! To start QEMU telnet to localhost $_DNSHOST_telnetport" echo /usr/local/bin/qemu-system-x86_64 -monitor stdio \ -serial telnet:localhost:${_DNSHOST_telnetport},server=on,wait=on \ -cpu qemu64 \ -vga cirrus \ -m ${_DNSHOST_mem} \ -cdrom ${_DNSHOST_ISO} \ -boot order=cd,menu=on,splash=${_DNS_splash},splash-time=3000 \ -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_DNSHOST_img} \ -device virtio-blk,drive=drive0 \ -netdev tap,id=nd0,ifname=${_DNSHOST_tap7},script=no,downscript=no \ -device e1000,netdev=nd0,mac=${_DNSHOST_mac1} \ -netdev tap,id=nd1,ifname=${_DNSHOST_tap8},script=no,downscript=no \ -device e1000,netdev=nd1,mac=${_DNSHOST_mac2} \ -netdev tap,id=nd2,ifname=${_DNSHOST_tap11},script=no,downscript=no \ -device e1000,netdev=nd2,mac=${_DNSHOST_mac3} \ -name \"${_DNSHOST_name}\" ========================================================== SCRIPT: external1.sh #!/bin/sh # IPFW Primer # License: 3-clause BSD # Author: Jim Brown, jpb@jimby.name # Code: https://github.com/jimmyb-gh/ipfw-primer # # FreeBSD QEMU VM startup script for external1 VM. # # external1.sh: FreeBSD QEMU VM startup script for external1 VM. # Usage: sudo /bin/sh external1.sh # Note: Set up for serial console. Start another session and telnet to the port shown. # # FreeBSD QEMU VM startup script # # external1.sh # #set -x # pick up environment for this run . ./vm_envs.sh echo [$_EXTERNAL1_ISO] echo [$_EXTERNAL1_mem] echo [$_EXTERNAL1_hdsize] echo [$_EXTERNAL1_img] echo [$_EXTERNAL1_mac] echo [$_EXTERNAL1_name] echo [$_EXTERNAL1_tap1] echo [$_EXTERNAL1_telnetport] # #exit # echo echo "NOTE!!! telnet server running! To start QEMU telnet to localhost $_EXTERNAL1_telnetport" echo /usr/local/bin/qemu-system-x86_64 -monitor vc \ -serial telnet:localhost:${_EXTERNAL1_telnetport},server=on,wait=on \ -cpu qemu64 \ -vga cirrus \ -m ${_EXTERNAL1_mem} \ -cdrom ${_EXTERNAL1_ISO} \ -boot order=cd,menu=on,splash=${_EX1_splash},splash-time=3000 \ -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_EXTERNAL1_img} \ -device virtio-blk,drive=drive0 \ -netdev tap,id=nd0,ifname=${_EXTERNAL1_tap1},script=no,downscript=no \ -device e1000,netdev=nd0,mac=${_EXTERNAL1_mac} \ -name \"${_EXTERNAL1_name}\" ========================================================== SCRIPT: external2.sh #!/bin/sh # IPFW Primer # License: 3-clause BSD # Author: Jim Brown, jpb@jimby.name # Code: https://github.com/jimmyb-gh/ipfw-primer # # FreeBSD QEMU VM startup script for external2 VM. # # external2.sh: FreeBSD QEMU VM startup script for external2 VM. # Usage: sudo /bin/sh external2.sh # Note: Set up for serial console. Start another session and telnet to the port shown. # # FreeBSD qemu vm startup script # # external2.sh # #set -x # pick up environment for this run . ./vm_envs.sh echo [ISO=${_EXTERNAL2_ISO}] echo [mem=${_EXTERNAL2_mem}] echo [hdsize=${_EXTERNAL2_hdsize}] echo [img=${_EXTERNAL2_img}] echo [mac=${_EXTERNAL2_mac}] echo [name=${_EXTERNAL2_name}] echo [tap2=${_EXTERNAL2_tap2}] echo [telnetport=${_EXTERNAL2_telnetport}] # #exit # echo echo "NOTE!!! telnet server running! To start QEMU telnet to localhost $_EXTERNAL2_telnetport" echo /usr/local/bin/qemu-system-x86_64 -monitor stdio \ -serial telnet:localhost:${_EXTERNAL2_telnetport},server=on,wait=on \ -cpu qemu64 \ -vga cirrus \ -m ${_EXTERNAL2_mem} \ -cdrom ${_EXTERNAL2_ISO} \ -boot order=cd,menu=on,splash=${_EX2_splash},splash-time=3000 \ -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_EXTERNAL2_img} \ -device virtio-blk,drive=drive0 \ -netdev tap,id=nd0,ifname=${_EXTERNAL2_tap2},script=no,downscript=no \ -device e1000,netdev=nd0,mac=${_EXTERNAL2_mac} \ -name \"${_EXTERNAL2_name}\" ========================================================== SCRIPT: external3.sh #!/bin/sh # IPFW Primer # License: 3-clause BSD # Author: Jim Brown, jpb@jimby.name # Code: https://github.com/jimmyb-gh/ipfw-primer # # FreeBSD QEMU VM startup script for external3 VM. # # external3.sh: FreeBSD QEMU VM startup script for external3 VM. # Usage: sudo /bin/sh external3.sh # Note: Set up for serial console. Start another session and telnet to the port shown. # # FreeBSD QEMU VM startup script # # external3.sh # #set -x # pick up environment for this run . ./vm_envs.sh echo [ISO=${_EXTERNAL3_ISO}] echo [mem=${_EXTERNAL3_mem}] echo [hdsize=${_EXTERNAL3_hdsize}] echo [img=${_EXTERNAL3_img}] echo [mac=${_EXTERNAL3_mac}] echo [name=${_EXTERNAL3_name}] echo [tap3=${_EXTERNAL3_tap3}] echo [telnetport=${_EXTERNAL3_telnetport}] # #exit # echo echo "NOTE!!! telnet server running! To start QEMU telnet to localhost $_EXTERNAL3_telnetport" echo /usr/local/bin/qemu-system-x86_64 -monitor vc \ -serial telnet:localhost:${_EXTERNAL3_telnetport},server=on,wait=on \ -cpu qemu64 \ -vga cirrus \ -m ${_EXTERNAL3_mem} \ -cdrom ${_EXTERNAL3_ISO} \ -boot order=cd,menu=on,splash=${_EX3_splash},splash-time=3000 \ -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_EXTERNAL3_img} \ -device virtio-blk,drive=drive0 \ -netdev tap,id=nd0,ifname=${_EXTERNAL3_tap3},script=no,downscript=no \ -device e1000,netdev=nd0,mac=${_EXTERNAL3_mac} \ -name \"${_EXTERNAL3_name}\" ========================================================== SCRIPT: firewall.sh #!/bin/sh # IPFW Primer # License: 3-clause BSD # Author: Jim Brown, jpb@jimby.name # Code: https://github.com/jimmyb-gh/ipfw-primer # # FreeBSD QEMU VM startup script for firewall VM. # # firewall.sh: FreeBSD QEMU VM startup script for firewall VM. # Usage: sudo /bin/sh firewall.sh # Note: Set up for serial console. Start another session and telnet to the port shown. # # FreeBSD QEMU VM startup script # # firewall.sh # #set -x # pick up environment for this run . ./vm_envs.sh echo [$_FIREWALL_ISO] echo [$_FIREWALL_mem] echo [$_FIREWALL_hdsize] echo [$_FIREWALL_img] echo [$_FIREWALL_mac1] echo [$_FIREWALL_mac2] echo [$_FIREWALL_name] echo [$_FIREWALL_tap0] echo [$_FIREWALL_tap4] echo [$_FIREWALL_telnetport] #exit # Note - the firewall has two interfaces - em0 and em1. # em0 is considered the 'external' interface and # em1 is considered the 'internal' interface. echo echo "NOTE!!! telnet server running! To start QEMU telnet to localhost $_FIREWALL_telnetport " echo /usr/local/bin/qemu-system-x86_64 -monitor none \ -serial telnet:localhost:${_FIREWALL_telnetport},server=on,wait=on \ -cpu qemu64 \ -display gtk \ -vga cirrus \ -m ${_FIREWALL_mem} \ -cdrom ${_FIREWALL_ISO} \ -boot order=cd,menu=on,splash=${_FW_splash},splash-time=3000 \ -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_FIREWALL_img} \ -device virtio-blk,drive=drive0 \ -netdev tap,id=nd0,ifname=${_FIREWALL_tap0},script=no,downscript=no \ -device e1000,netdev=nd0,mac=${_FIREWALL_mac1} \ -netdev tap,id=nd1,ifname=${_FIREWALL_tap4},script=no,downscript=no \ -device e1000,netdev=nd1,mac=${_FIREWALL_mac2} \ -name \"${_FIREWALL_name}\" ========================================================== SCRIPT: firewall2.sh #!/bin/sh # IPFW Primer # License: 3-clause BSD # Author: Jim Brown, jpb@jimby.name # Code: https://github.com/jimmyb-gh/ipfw-primer # # FreeBSD QEMU VM startup script for firewall2 VM. # # firewall2.sh: FreeBSD QEMU VM startup script for firewall2 VM. # Usage: sudo /bin/sh firewall2.sh # Note: Set up for serial console. Start another session and telnet to the port shown. # # FreeBSD QEMU VM startup script # # firewall2.sh # #set -x # pick up environment for this run . ./vm_envs.sh echo [ISO=${_FIREWALL2_ISO}] echo [mem=${_FIREWALL2_mem}] echo [hdsize=${_FIREWALL2_hdsize}] echo [img=${_FIREWALL2_img}] echo [mac1=${_FIREWALL2_mac1}] echo [mac2=${_FIREWALL2_mac2}] echo [name=${_FIREWALL2_name}] echo [tap9=${_FIREWALL2_tap9}] echo [tap10=${_FIREWALL2_tap10}] echo [telnetport=${_FIREWALL2_telnetport}] #exit # Note - the firewall has two interfaces - em0 and em1. # em0 is considered the 'external' interface and # em1 is considered the 'internal' interface. echo echo "NOTE!!! telnet server running! To start QEMU telnet to localhost $_FIREWALL2_telnetport" echo /usr/local/bin/qemu-system-x86_64 -monitor none \ -serial telnet:localhost:${_FIREWALL2_telnetport},server=on,wait=on \ -cpu qemu64 \ -display gtk \ -vga cirrus \ -m ${_FIREWALL2_mem} \ -cdrom ${_FIREWALL_ISO} \ -boot order=cd,menu=on,splash=${_FW2_splash},splash-time=3000 \ -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_FIREWALL2_img} \ -device virtio-blk,drive=drive0 \ -netdev tap,id=nd0,ifname=${_FIREWALL2_tap9},script=no,downscript=no \ -device e1000,netdev=nd0,mac=${_FIREWALL2_mac1} \ -netdev tap,id=nd1,ifname=${_FIREWALL2_tap10},script=no,downscript=no \ -device e1000,netdev=nd1,mac=${_FIREWALL2_mac2} \ -name \"${_FIREWALL2_name}\" ========================================================== SCRIPT: internal.sh #!/bin/sh # IPFW Primer # License: 3-clause BSD # Author: Jim Brown, jpb@jimby.name # Code: https://github.com/jimmyb-gh/ipfw-primer # # FreeBSD QEMU VM startup script for internal VM. # # internal.sh: FreeBSD QEMU VM startup script for internal VM. # Usage: sudo /bin/sh internal.sh # Note: Set up for serial console. Start another session and telnet to the port shown. # # FreeBSD QEMU VM startup script # # internal.sh # #set -x # pick up environment for this run . ./vm_envs.sh echo [ISO=${_INTERNAL_ISO}] echo [mem=${_INTERNAL_mem}] echo [hdsize=${_INTERNAL_hdsize}] echo [img=${_INTERNAL_img}] echo [mac=${_INTERNAL_mac}] echo [name=${_INTERNAL_name}] echo [tap5=${_INTERNAL_tap5}] echo [telnetport=${_INTERNAL_telnetport}] # #exit echo echo "NOTE!!! telnet server running! To start QEMU telnet to localhost $_INTERNAL_telnetport" echo /usr/local/bin/qemu-system-x86_64 -monitor none \ -serial telnet:localhost:${\_INTERNAL_telnetport},server \ -cpu qemu64 \ -vga cirrus \ -m ${_INTERNAL_mem} \ -cdrom ${_INTERNAL_ISO} \ -boot order=cd,menu=on,splash=${_INT_splash},splash-time=3000 \ -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_INTERNAL_img} \ -device virtio-blk,drive=drive0 \ -netdev tap,id=nd0,ifname=${_INTERNAL_tap5},script=no,downscript=no \ -device e1000,netdev=nd0,mac=${_INTERNAL_mac} \ -name \"${_INTERNAL_name}\" ========================================================== SCRIPT: mkbr.sh #!/bin/sh # IPFW Primer # License: 3-clause BSD # Author: Jim Brown, jpb@jimby.name # Code: https://github.com/jimmyb-gh/ipfw-primer # # FreeBSD startup script for bridge and tap devices. # # mkbr.sh: FreeBSD startup script for bridge and tap devices. # EXAMPLE Usage: sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 bridge1 tap2 bridge2 tap3 tap4 tap5 em0 # # mkbr.sh - manage bridge and tap interfaces for FreeBSD. # # Have fun, but don't blame me if it smokes your machine. # # This script is used to start the bridge and tap interfaces. # # To create one bridge, two tap interfaces, and connect the # local ethernet interace (here em0), run under sudo as follows: # sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 em0 # # The script can be used to create any number of bridges and taps # for any internal network design: # sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 bridge1 tap2 tap3 tap4 bridge2 tap5 em0 ... etc. # # To add other taps to existing bridges, do not specify the "reset" parameter. # sudo /bin/sh mkbr.sh bridge0 tap10 tap11 bridge1 tap12 tap13 ... etc. # # To delete all bridge and tap devices: # sudo /bin/sh mkbr.sh reset # # #set -x usage() { echo "Usage: mkbr.sh ["reset"] <bridgeN> <tapA> [[<bringeM>] <tapB> <tapC> ...]" echo "You must be root to run this script." exit 1 } if [ "X0" != "X`id -u`" ] then usage fi if [ $# = 0 ] then usage; fi if [ $1 = "reset" ] then echo echo "Note - if_bridge and/or if_tap may be compiled into the kernel and can't be unloaded. Adjust interfaces manually if necessary." echo echo "unloading..." kldunload if_bridge kldunload if_tap echo echo "Deleting any remaining bridge and tap devices:" for i inifconfig -l
do echo "Interface: ${i}" case ${i} in bridge*) echo " ... destroying bridge ${i}" ifconfig ${i} destroy ;; tap*) echo " ... destroying tap ${i}" ifconfig ${i} destroy ;; esac done sleep 1 echo "loading..." kldload if_bridge kldload if_tap shift RESET="Y" echo "RESET=Y" # Before using the tap devices in QEMU, two sysctls require adjustment: sysctl net.link.tap.user_open=1 sysctl net.link.tap.up_on_open=1 else RESET="N" echo "RESET=N" fi PARAM=$1 while [ "X${PARAM}" != "X" ] do # echo "PARAM=[$PARAM]" case $PARAM in bridge*) BRIDGE=$1 # if [ "$RESET" = "Y" ] # then echo ifconfig $BRIDGE create ifconfig $BRIDGE create echo ifconfig $BRIDGE ifconfig $BRIDGE # fi echo ifconfig $BRIDGE up ifconfig $BRIDGE up ;; tap*) TAP=$1 # if [ "$RESET" = "Y" ] # then echo ifconfig $TAP create ifconfig $TAP create # fi echo "ifconfig $BRIDGE addm $TAP " ifconfig $BRIDGE addm $TAP ;; *) echo "*** Checking to see if $1 is a valid interface" TMPINT=$1 RESULT="IS NOT" for i inifconfig -l
do # echo $i if [ "${i}X" = "${TMPINT}X" ] then echo "Found a valid interface: ${TMPINT} Adding it to the bridge. Check results." echo "ifconfig $BRIDGE addm $TMPINT" ifconfig $BRIDGE addm $TMPINT RESULT="IS" break; else echo -n "." fi done echo "Interface ${TMPINT} $RESULT a valid interface." ;; esac shift PARAM=$1 done exit 0 ========================================================== SCRIPT: runvm.sh #!/bin/sh # IPFW Primer # License: 3-clause BSD # Author: Jim Brown, jpb@jimby.name # Code: https://github.com/jimmyb-gh/ipfw-primer # # FreeBSD QEMU VM startup script for multiple VMs at once. # # runvm.sh: FreeBSD QEMU VM startup script for multiple VMs. # EXAMPLE Usage: /bin/sh runvm.sh firewall external1 external2 internal # # location: FreeBSD Host # # runvm.sh - run virtual machines specified on the command line. # # To use this script, run mkbr.sh first to set up the bridge and # tap configurations for the desired network architecture. # # NOTE: this script works best on XFCE4 desktop as it takes advantage of the # xfce4-terminal and it's ability to use multiple tabs. # # >>>> It is unlikely to work on another desktop. <<<< # # Essentially, this script is a big case statement. It gets the # command line names of the virtual machines and calls a function # that starts the virtual machine. # # pick up environment for this run . ./vm_envs.sh #set -x #WKDIR=$HOME/LAB/SCRIPTS export WKDIR=$HOME/ipfw echo "[${WKDIR}]" usage() { echo "Usage: /bin/sh runvm.sh vmname [vmname ...]" echo "Each virtual machine opens up on xfce4-terminal with two tabs -" echo " one for the qemu virtual machine, and one for the serial" echo " terminal interface." echo "" exit 1 } CURDIR=pwd
if [ "X${CURDIR}" != "X${WKDIR}/SCRIPTS" ] then usage; fi if [ $# = 0 ] then usage; fi # Functions for each VM dnshost_vm () { # DNS host echo "in function: [${_DNSHOST_telnetport}]" xfce4-terminal --window --geometry="80x24+50+50" --zoom="-1" \ -T "${_DNSHOST_name}" -e "bash -c \"cd ${WKDIR}/SCRIPTS && sudo /bin/sh dnshost.sh ; bash\"" \ --tab -T "${_DNSHOST_name}" -e "bash -c \"cd ${WKDIR}/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet -4 localhost ${_DNSHOST_telnetport}); bash\"" return } external1_vm () { # external1 echo "in function: [${_EXTERNAL1_telnetport}]" xfce4-terminal --window --geometry="80x24+75+75" --zoom="-1" \ -T "${_EXTERNAL1_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sudo /bin/sh external1.sh ; bash\"" \ --tab -T "${_EXTERNAL1_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_EXTERNAL1_telnetport}); bash\"" return } external2_vm () { # external2 echo "in function: [${_EXTERNAL2_telnetport}]" xfce4-terminal --window --geometry="80x24+100+100" --zoom="-1" \ -T "${_EXTERNAL2_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sudo /bin/sh external2.sh ; bash\"" \ --tab -T "${_EXTERNAL2_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_EXTERNAL2_telnetport}); bash\"" return } external3_vm () { # external3 echo "in function: [${_EXTERNAL3_telnetport}]" xfce4-terminal --window --geometry="80x24+125+125" --zoom="-1" \ -T "${_EXTERNAL3_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sudo /bin/sh external3.sh ; bash\"" \ --tab -T "${_EXTERNAL3_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_EXTERNAL3_telnetport}); bash\"" return } firewall_vm () { # Firewall echo "in function: [${_FIREWALL_telnetport}]" xfce4-terminal --window --geometry="80x24+150+150" --zoom="-1" \ -T "${_FIREWALL_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sudo /bin/sh firewall.sh ; bash\"" \ --tab -T "${_FIREWALL_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh; telnet localhost ${_FIREWALL_telnetport}); bash\"" return } firewall2_vm () { # Firewall2 echo "in function: [${_FIREWALL2_telnetport}]" xfce4-terminal --window --geometry="80x24+175+175" --zoom="-1" \ -T "${_FIREWALL2_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sudo /bin/sh firewall2.sh ; bash\"" \ --tab -T "${_FIREWALL2_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_FIREWALL2_telnetport}); bash\"" return } internal_vm () { # internal echo "in function: [${_INTERNAL_telnetport}]" xfce4-terminal --window --geometry="80x24+200+200" --zoom="-1" \ -T "${_INTERNAL_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sudo /bin/sh internal.sh ; bash\"" \ --tab -T "${_INTERNAL_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_INTERNAL_telnetport}); bash\"" return } v6only_vm () { # v6only echo "in function: [${_V6ONLY_telnetport}]" xfce4-terminal --window --geometry="80x24+225+225" --zoom="-1" \ -T "${_V6ONLY_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sudo /bin/sh v6only.sh ; bash\"" \ --tab -T "${_V6ONLY_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_V6ONLY_telnetport}); bash\"" return } # # Startup the requested VMs # PARAM=$1 while [ "X${PARAM}" != "X" ] do echo "PARAM = [${PARAM}]" case ${PARAM} in dnshost) echo "dnshost ..." echo "_DNSHOST_telnetport = [${_DNSHOST_telnetport}]" dnshost_vm ;; external1) echo "external1 ..." echo "_EXTERNAL1_telnetport = [${_EXTERNAL1_telnetport}]" external1_vm ;; external2) echo "external2 ..." echo "_EXTERNAL2_telnetport = [${_EXTERNAL2_telnetport}]" external2_vm ;; external3) echo "external3 ..." echo "_EXTERNAL3_telnetport = [${_EXTERNAL3_telnetport}]" external3_vm ;; firewall) echo "firewall ..." echo "_FIREWALL_telnetport = [${_FIREWALL_telnetport}]" firewall_vm ;; firewall2) echo "firewall2 ..." echo "_FIREWALL2_telnetport = [${_FIREWALL2_telnetport}]" firewall2_vm ;; internal) echo "internal ..." echo "_INTERNAL_telnetport = [${_INTERNAL_telnetport}]" internal_vm ;; v6only) echo "v6only ..." echo "_V6ONLY_telnetport = [${_V6ONLY_telnetport}]" v6only_vm ;; *) echo "" echo "*** ERROR: NO VM NAMED [$PARAM]" echo "" ;; esac shift sleep 3 PARAM=$1 done exit 0 ========================================================== SCRIPT: v6only.sh #!/bin/sh # IPFW Primer # License: 3-clause BSD # Author: Jim Brown, jpb@jimby.name # Code: https://github.com/jimmyb-gh/ipfw-primer # # FreeBSD QEMU VM startup script for v6only VM. # # v6only.sh: FreeBSD QEMU VM startup script for v6only VM. # Usage: sudo /bin/sh v6only.sh # Note: Set up for serial console. Start another session and telnet to the port shown. # # FreeBSD QEMU VM startup script # # v6only.sh # #set -x # pick up environment for this run . ./vm_envs.sh echo [ISO=${_V6ONLY_ISO}] echo [mem=${_V6ONLY_mem}] echo [hdsize=${_V6ONLY_hdsize}] echo [img=${_V6ONLY_img}] echo [mac=${_V6ONLY_mac}] echo [name=${_V6ONLY_name}] echo [tap6=${_V6ONLY_tap6}] echo [telnetport=${_V6ONLY_telnetport}] # #exit echo echo "NOTE!!! telnet server running! To start QEMU telnet to localhost $_V6ONLY_telnetport" echo /usr/local/bin/qemu-system-x86_64 -monitor none \ -serial telnet:localhost:${_V6ONLY_telnetport},server \ -cpu qemu64 \ -vga cirrus \ -m ${_V6ONLY_mem} \ -cdrom ${_V6ONLY_ISO} \ -boot order=cd,menu=on,splash=${_V6_splash},splash-time=3000 \ -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_V6ONLY_img} \ -device virtio-blk,drive=drive0 \ -netdev tap,id=nd0,ifname=${_V6ONLY_tap6},script=no,downscript=no \ -device e1000,netdev=nd0,mac=${_V6ONLY_mac} \ -name \"${_V6ONLY_name}\" ========================================================== SCRIPT: vm_envs.sh # IPFW Primer # License: 3-clause BSD # Author: Jim Brown, jpb@jimby.name # Code: https://github.com/jimmyb-gh/ipfw-primer # # FreeBSD QEMU VM environment script. # # vmenv.sh: FreeBSD QEMU VM environment setup script. # Usage: ./bin/sh vmenv.sh # # vm_envs.sh - environment for setting up virtual machines # for the IPFW examples lab. # # Set the environment variables below (or keep the defaults) # Note that the default disk size for each virtual machine is # 4GB - so all five VMs will take up about 32GB if you preallocate # space. # # In brief: # # Install FreeBSD on the host machine and update to latest patch level. # Install desktop software. # Install QEMU (latest) # Install nmap (needed for ncat) # Install sudo # # # The script mkbr.sh should be run before starting # the virtual machines. mkbr.sh sets up the bridge and tap # devices needed by the VMs. # # sudo /bin/sh ./mkbr.sh reset bridge0 tap0 tap1 tap2 tap3 em0 bridge1 tap4 tap5 # # This will set up the devices needed by QEMU. # # #The file directory layout for the examples is: # # ~/ipfw # /SCRIPTS # _CreateAllVMs.sh (create Qemu disks images) # dnshost.sh (run script for dns server VM) # external1.sh (run scripts for external VMs) # external2.sh " # external3.sh " # firewall.sh (run script for firewall VM) # firewall2.sh (run script for firewall2 VM) # internal.sh (script to setup internal host) # v6only.sh (run script for IPv6 only VM) # mkbr.sh (script to create bridge and tap devices) # vm_envs.sh (script to manage all parameters) # runvm.sh (script to manage all virtual machines) # /BMP # dns_splash_640x480.bmp # external1_splash_640x480.bmp # external2_splash_640x480.bmp # external3_splash_640x480.bmp # internal_splash_640x480.bmp # ipfw2_splash_640x480.bmp # ipfw_splash_640x480.bmp # v6only_splash_640x480.bmp # dnshost_splash_640x480.bmp # /ISO # fbsd.iso (latest FreeBSD install iso) # /VM # dnshost.qcow2 (Qemu disk image for dns host) # external1.qcow2 (Qemu disk image for external hosts) # external2.qcow2 " # external3.qcow2 " # firewall.qcow2 (Qemu disk image for firewall) # firewall2.qcow2 (Qemu disk image for firewall2) # internal.qcow2 (Qemu disk image for an internal host) # v6only.qcow2 (Qemu disk image for an ipv6only host) # # # Start the VMs and install / test one at a time. # # sudo /bin/sh firewall.sh # sudo /bin/sh firewall2.sh # sudo /bin/sh external1.sh # sudo /bin/sh external2.sh # sudo /bin/sh external3.sh # sudo /bin/sh internal.sh # sudo /bin/sh v6only.sh # sudo /bin/sh dnshost.sh # # Each install should first utilize DHCP to get a valid IP address # After install, proceed to update FreeBSD with "freebsd-update fetch install" # Install packages: # Use whatever shell you prefer. Bash is listed below. # Firewall - pkg install bash cmdwatch lynx iperf3 nmap hping3 nginx # All others - pkg install bash cmdwatch lynx iperf3 nmap hping3 nginx # DNS host - pkg install bind918 dual-dhclient bash cmdwatch lynx nginx # # Reset all IP addresses for static usage: # # Host interface: add 172.16.10.100/24 alias # Disable any firewall (pf, ipfw, etc.) on the host. # BE SURE this is Ok for your environment. # # Firewall em0 172.16.10.50/24, default gateway 172.16.10.100 # em1 10.10.10.50/24 # # Firewall2 em0 as needed # em1 as needed # # External1: em0 172.16.10.10/24, default gateway 172.16.10.100 # External2: em0 172.16.10.20/24, default gateway 172.16.10.100 # External3: em0 172.16.10.30/24, default gateway 172.16.10.100 # Internal: em0 10.10.10.200/24, default gateway 10.10.10.50 # # v6only as needed # dnshost as needed # # export _BASE=/home/jpb/ipfw # Bridge and tap info export _FIREWALL_tap0=tap0 export _EXTERNAL1_tap1=tap1 export _EXTERNAL2_tap2=tap2 export _EXTERNAL3_tap3=tap3 export _FIREWALL_tap4=tap4 export _INTERNAL_tap5=tap5 export _V6ONLY_tap6=tap6 export _DNSHOST_tap7=tap7 export _DNSHOST_tap8=tap8 export _FIREWALL2_tap9=tap9 export _FIREWALL2_tap10=tap10 export _DNSHOST_tap11=tap11 export _bridge0_=bridge0 export bridge1=bridge1 export bridge2=bridge2 # Disk sizes export _EXTERNAL1_hdsize=4G export _EXTERNAL2_hdsize=4G export _EXTERNAL3_hdsize=4G export _FIREWALL_hdsize=4G export _FIREWALL2_hdsize=4G export _INTERNAL_hdsize=4G export _V6ONLY_hdsize=4G export _DNSHOST_hdsize=4G # Is this needed anymore? export _FBSD_ISO=${_BASE}/ISO/fbsd.iso # Boot iso locations export _DNSHOST_ISO=${_BASE}/ISO/fbsd.iso export _EXTERNAL1_ISO=${_BASE}/ISO/fbsd.iso export _EXTERNAL2_ISO=${_BASE}/ISO/fbsd.iso export _EXTERNAL3_ISO=${_BASE}/ISO/fbsd.iso export _FIREWALL_ISO=${_BASE}/ISO/fbsd.iso export _FIREWALL2_ISO=${_BASE}/ISO/fbsd.iso export _INTERNAL_ISO=${_BASE}/ISO/fbsd.iso export _V6ONLY_ISO=${_BASE}/ISO/fbsd.iso # Memory sizes export _DNSHOST_mem=1024 export _EXTERNAL1_mem=1024 # lower all to 512 if necessary export _EXTERNAL2_mem=1024 export _EXTERNAL3_mem=1024 export _FIREWALL_mem=1024 export _FIREWALL2_mem=1024 export _INTERNAL_mem=1024 export _V6ONLY_mem=1024 # Qemu disk image locations. export _DNSHOST_img=${_BASE}/VM/dnshost.qcow2 export _EXTERNAL1_img=${_BASE}/VM/external1.qcow2 export _EXTERNAL2_img=${_BASE}/VM/external2.qcow2 export _EXTERNAL3_img=${_BASE}/VM/external3.qcow2 export _FIREWALL_img=${_BASE}/VM/firewall.qcow2 export _FIREWALL2_img=${_BASE}/VM/firewall2.qcow2 export _INTERNAL_img=${_BASE}/VM/internal.qcow2 export _V6ONLY_img=${_BASE}/VM/v6only.qcow2 # MAC addresses export _DNSHOST_mac1=02:49:53:53:53:53 export _DNSHOST_mac2=02:49:53:53:54:54 export _DNSHOST_mac3=02:49:53:53:55:55 export _EXTERNAL1_mac=02:45:58:54:31:10 export _EXTERNAL2_mac=02:45:58:54:32:20 export _EXTERNAL3_mac=02:45:58:54:33:30 export _FIREWALL_mac1=02:49:50:46:57:41 export _FIREWALL2_mac1=02:49:50:00:22:22 export _FIREWALL_mac2=02:49:50:46:57:42 export _FIREWALL2_mac2=02:49:50:22:22:22 export _INTERNAL_mac=02:49:4E:54:0a:42 export _V6ONLY_mac=02:49:de:ad:be:ef # VM names export _DNSHOST_name=DNSHOST export _EXTERNAL1_name=EXTERNAL1 export _EXTERNAL2_name=EXTERNAL2 export _EXTERNAL3_name=EXTERNAL3 export _FIREWALL_name=FIREWALL export _FIREWALL2_name=FIREWALL2 export _INTERNAL_name=INTERNAL export _V6ONLY_name=V6ONLY # Slash images export _DNS_splash=${_BASE}/BMP/dns_splash_640x480.bmp export _EX1_splash=${_BASE}/BMP/external1_splash_640x480.bmp export _EX2_splash=${_BASE}/BMP/external2_splash_640x480.bmp export _EX3_splash=${_BASE}/BMP/external3_splash_640x480.bmp export _FW_splash=${_BASE}/BMP/ipfw_splash_640x480.bmp export _FW2_splash=${_BASE}/BMP/ipfw2_splash_640x480.bmp export _INT_splash=${_BASE}/BMP/internal_splash_640x480.bmp export _V6_splash=${_BASE}/BMP/ipv6_splash_640x480.bmp # # Telnet ports export _DNSHOST_telnetport=4453 export _EXTERNAL1_telnetport=4410 export _EXTERNAL2_telnetport=4420 export _EXTERNAL3_telnetport=4430 export _FIREWALL_telnetport=4450 export _FIREWALL2_telnetport=4250 export _INTERNAL_telnetport=44200 export _V6ONLY_telnetport=4460 # Bridge and Tap configurations. # # Note: em0 is used for the host interface. # Change as needed. # # Two bridge configuration # Standard examples # # em0 # | # External1(tap1) -----bridge0------(tap0)Firewall # External2(tap2) -----+ | (tap4) # External3(tap3) -------+ | # bridge1 # | # Internal(tap5) -----------------------------+ # # sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 tap2 tap3 em0 # # # # Two bridge configuration # NAT & LSNAT examples # # # # (firewall does LSNAT load balancing) # External1(tap1) -----bridge0------(tap0)Firewall # External2(tap2) -----+ | (tap4) # External3(tap3) -------+ | # (these function as internal machines) bridge1----em0 # | # Internal(tap5) -----------------------------+ # (this functions as an external machine) # # sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 tap2 tap3 bridge1 tap4 tap5 em0 # # # # Two bridge configuration # NAT64/DNS64 example # # ipv4 only NAT64 Translator # External1(tap1) ------bridge0-----(tap0)Firewall # (ipv4 only) + (tap4) # (webserver) | + # dnshost(tap7) | # (DNS server) | # (running DNS64) | # (tap8) | # | | # + | # ipv6 only | # v6only(tap6) --------bridge1----------------+ # (v6 only host) # # sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 tap7 bridge1 tap4 tap6 tap8 # # ========================================================== ========================================================== CODE: divert.c #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/tcp.h> #include <arpa/inet.h> #include <stdio.h> #include <string.h> #include <err.h> #include <sys/systm.h> #define DIVERT_PORT 700 void hexdump(void *ptr, int length, const char *hdr, int flags); int main(int argc, char *argv[]) { int fd, s; struct sockaddr_in sin; socklen_t sin_len; printf("Opening divert on port %d\n",DIVERT_PORT); fd = socket(PF_DIVERT, SOCK_RAW, 0); if (fd == -1) err(1, "socket"); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(DIVERT_PORT); sin.sin_addr.s_addr = 0; sin_len = sizeof(struct sockaddr_in); s = bind(fd, (struct sockaddr *) &sin, sin_len); if (s == -1) err(1, "bind"); for (;;) { ssize_t n; char packet[IP_MAXPACKET]; struct ip *ip; struct tcphdr *th; int hlen; char src[64], dst[64], printbuff[12]; memset(src, 0, sizeof(src)); memset(dst, 0, sizeof(dst)); memset(printbuff, 0, sizeof(printbuff)); memset(packet, 0, sizeof(packet)); n = recvfrom(fd, packet, sizeof(packet), 0, (struct sockaddr *) &sin, &sin_len); if (n == -1) { warn("recvfrom"); continue; } if (n < sizeof(struct ip)) { warnx("packet is too short"); continue; } ip = (struct ip *) packet; hlen = ip->ip_hl << 2; if (hlen < sizeof(struct ip) || ntohs(ip->ip_len) < hlen || n < ntohs(ip->ip_len)) { warnx("invalid IPv4 packet"); continue; } th = (struct tcphdr *) (packet + hlen); if (inet_ntop(AF_INET, &ip->ip_src, src, sizeof(src)) == NULL) (void)strlcpy(src, "?", sizeof(src)); if (inet_ntop(AF_INET, &ip->ip_dst, dst, sizeof(dst)) == NULL) (void)strlcpy(dst, "?", sizeof(dst)); printf("%s:%u -> %s:%u\n", src, ntohs(th->th_sport), dst, ntohs(th->th_dport) ); /* * dump the packet in hex and ascii with hexdump(3) */ hexdump((void *)packet, n, "|",0); n = sendto(fd, packet, n, 0, (struct sockaddr *) &sin, sin_len); if (n == -1) warn("sendto"); } return 0; }