Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@mizhka
Last active March 1, 2022 12:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mizhka/5c770e6f2b3335147eecb8299d8b383d to your computer and use it in GitHub Desktop.
Save mizhka/5c770e6f2b3335147eecb8299d8b383d to your computer and use it in GitHub Desktop.
Jail+vnet
# dhcpd.conf
# option definitions common to all supported networks...
option subnet-mask 255.255.255.0;
default-lease-time 600;
max-lease-time 7200;
subnet 192.168.20.0 netmask 255.255.255.0 {
range 192.168.20.2 192.168.20.40;
option domain-name-servers 192.168.20.1;
option routers 192.168.20.1;
}
#!/bin/sh
ORIGIN="tank/guests/vm/jails/basepg@base"
TARGET="tank/guests/vm/jails"
JAILNAME="tmp`date +%Y%m%d`"
# Check if dataset exists
zfs get name ${TARGET}/${JAILNAME} > /dev/null 2>&1
if [ $? -ne 0 ]
then
echo ">>> Create ZFS dataset ${TARGET}/${JAILNAME}"
zfs clone ${ORIGIN} ${TARGET}/${JAILNAME} || exit 1
fi
echo ">>> Register new temp jail in jail.conf"
grep -qxF "${JAILNAME} {}" /etc/jail.conf || printf "${JAILNAME} {}\n" >> /etc/jail.conf
jls -j ${JAILNAME} > /dev/null 2>&1
if [ $? -ne 0 ]
then
echo ">>> Start jail"
jail -vc ${JAILNAME} || exit 3
fi
echo ">>> Go to shell"
jexec -l ${JAILNAME} zsh || exit 4
#!/bin/sh
# Environment discovery
EXTERNAL_IF=`netstat -r4n | grep defa | cut -f4 -w`
EXTERNAL_IP=`ifconfig $EXTERNAL_IF | grep inet | cut -f3 -w`
# Extra settings
KLDMODS="ng_ipfw ng_ether ng_nat ng_eiface"
NG_IFPREFIX="ng-"
VERBOSE="yes"
# Input parameters
INTERNAL_IP="192.168.20.1"
INTERNAL_IF="${NG_IFPREFIX}jailgw"
NG_NATNAME="jail_nat0"
NG_BRGNAME="jail_bridge0"
print ( )
{
if [ "$VERBOSE" = "yes" ] ; then
echo ">>>> " $*
fi
}
print_error ( )
{
echo "Stopped at:" $*
exit 1
}
# Load kernel modules
load_kld ( )
{
local _kldmod
print "Loading kernel modules"
for _kldmod in ${KLDMODS}; do
print "... Loading" ${_kldmod}
kldload -n ${_kldmod}
done
print "All kernel module loaded"
}
init_ipfw_nat ( )
{
local _name _in _out _ext_ip _ext_if _int_ip _int_if
_name=$1
_ext_ip=$2
_ext_if=$3
_int_ip=$4
_int_if=$5
_in=100
_out=110
ngctl info ${_name}: > /dev/null 2>&1 && return
print "[NAT] start configuration of $_name from $_int_ip/$_int_if to $_ext_ip/$_ext_if"
print "... netgraph"
ngctl mkpeer ipfw: nat ${_in} in || print_error init_ipfw_nat ${LINENO}
ngctl name ipfw:${_in} ${_name} || print_error init_ipfw_nat ${LINENO}
ngctl connect ipfw: ${_name}: ${_out} out || print_error init_ipfw_nat ${LINENO}
ngctl msg ${_name}: setaliasaddr ${_ext_ip} || print_error init_ipfw_nat ${LINENO}
print "... ipfw"
destroy_ipfw_rules
ipfw -q add 200 allow ip from any to $_int_ip in via $_int_if || print_error init_ipfw_nat ${LINENO}
ipfw -q add 300 netgraph $_out all from any to any in via $_int_if || print_error init_ipfw_nat ${LINENO}
ipfw -q add 400 netgraph $_in all from any to any in via $_ext_if || print_error init_ipfw_nat ${LINENO}
ipfw -q add 500 allow ip from any to any || print_error init_ipfw_nat ${LINENO}
print "[NAT] done"
}
destroy_ipfw_rules ( )
{
ipfw -q delete 200 > /dev/null 2>&1
ipfw -q delete 300 > /dev/null 2>&1
ipfw -q delete 400 > /dev/null 2>&1
ipfw -q delete 500 > /dev/null 2>&1
}
destroy_ng_node ( )
{
ngctl shutdown $1: > /dev/null 2>&1
}
init_jail_bridge ( )
{
local _bridge _int_if _int_ip _ext_if _oldname _ether
_bridge=$1
_ext_if=$2
_int_ip=$3
_int_if=$4
_ether="6a:61:69:6c:00:aa"
# Make sure the interface has been bridged
ngctl info ${_bridge}: > /dev/null 2>&1 && return
# Create bridge
ngctl mkpeer $_ext_if: bridge lower link0 || print_error init_jail_bridge ${LINENO}
ngctl name $_ext_if:lower ${_bridge} || print_error init_jail_bridge ${LINENO}
ngctl mkpeer ${_bridge}: eiface link1 ether || print_error init_jail_bridge ${LINENO}
# Disconnect from external interface
ngctl rmhook ${_bridge}: link0 || print_error init_jail_bridge ${LINENO}
_oldname=`ngctl show -n ${_bridge}:link1 | cut -f3 -w`
ngctl name ${_bridge}:link1 ${_int_if} || print_error init_jail_bridge ${LINENO}
ifconfig ${_oldname} name ${_int_if} > /dev/null || print_error init_jail_bridge ${LINENO}
ifconfig ${_int_if} inet alias ${_int_ip} > /dev/null || print_error init_jail_bridge ${LINENO}
ifconfig ${_int_if} ether ${_ether} || print_error create_interface ${LINENO}
print "Let packets continue with after being (de)aliased"
sysctl net.inet.ip.fw.one_pass=0
sysctl net.inet.ip.forwarding=1
}
create_interface ( )
{
local _num _name _link _ifname _oldname _ether _bridge
_num=2
_name=$1
_ifname="${NG_IFPREFIX}${_name}"
_bridge=$2
# Silently exit if interface exists (job is done before)
ngctl msg "$_ifname:" getifname > /dev/null 2>&1 && \
echo ">>>> Interface already exists" && return
while ngctl msg ${_bridge}: getstats $_num > /dev/null 2>&1
do
_num=$(( $_num + 1 ))
done
_link="link${_num}"
# 6a:61:69:6c means "jail"
_ether="6a:61:69:6c:00:${_num}"
print "Create interface ${_ifname} with MAC ${_ether}"
ngctl mkpeer ${_bridge}: eiface ${_link} ether || print_error create_interface ${LINENO}
_oldname=`ngctl show -n ${_bridge}:${_link} | cut -f3 -w`
print "... Adjust names (netgraph) ${_oldname} -> ${_ifname}"
ngctl name ${_bridge}:${_link} ${_ifname} || print_error create_interface ${LINENO}
print "... Adjust names (if) ${_oldname} -> ${_ifname}"
ifconfig ${_oldname} name ${_ifname} > /dev/null || print_error create_interface ${LINENO}
print "... Set MAC address: ${_ether}"
ifconfig ${_ifname} ether ${_ether} || print_error create_interface ${LINENO}
print "Done"
}
delete_interface ( )
{
local _ifname _name
_name=$1
_ifname="${NG_IFPREFIX}${_name}"
ngctl shutdown ${_ifname}: 2> /dev/null
}
init ( )
{
load_kld
init_jail_bridge ${NG_BRGNAME} ${EXTERNAL_IF} ${INTERNAL_IP} ${INTERNAL_IF}
init_ipfw_nat ${NG_NATNAME} ${EXTERNAL_IP} ${EXTERNAL_IF} ${INTERNAL_IP} ${INTERNAL_IF}
dhcpd ${INTERNAL_IF}
}
# MAIN
if [ "$1" = "create" ]; then
shift
# Make sure the interface has been bridged
ngctl info ${NG_BRGNAME}: > /dev/null 2>&1 || init
create_interface $1 ${NG_BRGNAME}
exit 0
fi
if [ "$1" = "delete" ]; then
shift
delete_interface $*
exit 0
fi
if [ "$1" = "init" ]; then
shift
init
exit 0
fi
if [ "$1" = "deinit" ]; then
shift
pkill -f "dhcpd ${INTERNAL_IF}"
destroy_ng_node ${NG_NATNAME}
destroy_ng_node ${NG_BRGNAME}
destroy_ng_node ${INTERNAL_IF}
destroy_ipfw_rules
exit 0
fi
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment