Last active
April 8, 2021 22:16
-
-
Save paulc/cc561978122b7c9736dc4e4502e56cc5 to your computer and use it in GitHub Desktop.
Another jail wrapper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
set -e | |
JAIL_IF=${JAIL_IF:-lo1} | |
JAIL_IP=172.16.0 | |
JAIL_MAX=16 | |
clean() { | |
set +e | |
for j in $(jls jid) | |
do | |
jail -r $j | |
done | |
service zfs stop | |
service pf onestop | |
zpool destroy -f pool | |
rm -f /zpool | |
ifconfig $JAIL_IF destroy | |
sysrc -x gateway_enable zfs_enable pf_enable cloned_interfaces | |
} | |
init() { | |
sysrc gateway_enable=yes | |
sysrc pf_enable=no | |
sysrc zfs_enable=yes | |
sysrc jail_enable=yes | |
sysrc cloned_interfaces=$JAIL_IF | |
service zfs start | |
cat >/etc/jail.conf <<EOM | |
interface = "$JAIL_IF"; | |
host.hostname = "\$name"; | |
ip4.addr = "$JAIL_IP.\$ip"; | |
path = "/jail/run/\$name"; | |
exec.prestart = "$(readlink -f $0) pf_rules | lockf /tmp/pf-jail.lock pfctl -a jail -f -"; | |
exec.start = "/bin/sh /etc/rc"; | |
exec.stop = "/bin/sh /etc/rc.shutdown"; | |
allow.chflags; | |
mount.devfs; | |
exec.clean; | |
EOM | |
cat >/etc/pf.conf <<'EOM' | |
ext_if = "hn0" | |
jail_if = "lo1" | |
nat-anchor jail | |
rdr-anchor jail | |
EOM | |
ifconfig lo1 create | |
sysctl net.inet.ip.forwarding=1 | |
service pf onestart | |
} | |
dist() { | |
truncate -s 8G /zpool | |
zpool create pool /zpool | |
zfs create -o mountpoint=/jail -o compression=lz4 pool/jail | |
zfs create pool/jail/run | |
local release=$(sysctl -n kern.osrelease | sed -e 's/-p[0-9]*$//') | |
local arch=$(sysctl -n hw.machine_arch) | |
local dist=http://ftp.freebsd.org/pub/FreeBSD/releases/$arch/$release | |
local template_dir=/jail/template-$arch | |
local f | |
zfs create pool$template_dir | |
for f in base.txz doc.txz $([ $arch = amd64 ] && echo lib32.txz) | |
do | |
fetch -o - $dist/$f | tar -C $template_dir -xf - | |
done | |
zfs snapshot pool$template_dir@dist | |
if [ $arch = amd64 ] | |
then | |
arch=i386 | |
local dist=http://ftp.freebsd.org/pub/FreeBSD/releases/$arch/$release | |
local template_dir=/jail/template-$arch | |
zfs create pool$template_dir | |
for f in base.txz doc.txz | |
do | |
fetch -o - $dist/$f | tar -C $template_dir -xf - | |
done | |
zfs snapshot pool$template_dir@dist | |
fi | |
} | |
configure() { | |
local t f | |
for t in /jail/template-* | |
do | |
sysrc -f $t/etc/rc.conf sendmail_enable=NO \ | |
sendmail_submit_enable=NO \ | |
sendmail_outbound_enable=NO \ | |
sendmail_msp_queue_enable=NO \ | |
syslogd_enable=No \ | |
sshd_enable=YES \ | |
sshd_flags="-o PermitRootLogin=yes" | |
/usr/sbin/pw -R $t usermod -n root -w no -s /bin/sh | |
for f in /etc/resolv.conf /etc/localtime | |
do | |
cp $f $t/$f | |
done | |
zfs snapshot pool$t@base | |
done | |
} | |
next_ip() { | |
awk -v max=$JAIL_MAX -f - /etc/jail.conf <<'EOM' | |
function strip(s) {gsub("^[ \t\n\"]+","",s);gsub("[ \t\n\"]+$","",s);return s} | |
function readblock(l) {l=$0;while($NF != "}"){getline;l=l$0};return l } | |
$1 ~ "[a-zA-Z0-9]+" && $2 == "{" { | |
split(readblock(),a,";|}|{|=") | |
name = strip(a[1]) | |
for (i=2;i<length(a);i=i+2) { | |
k = strip(a[i]) | |
if (k == "$ip") { ip[strip(a[i+1])]=name } | |
} | |
} | |
END { for (i=1;i<max;++i) { if (ip[i] == "") { print i; exit }}} | |
EOM | |
} | |
pf_rules() { | |
awk -v jail_ip=$JAIL_IP -f - /etc/jail.conf <<'EOM' | |
function parray(a) {for (i in a) { print i ":" a[i] }} | |
function strip(s) {gsub("^[ \t\n\"]+","",s);gsub("[ \t\n\"]+$","",s);return s} | |
function readblock(l) {l=$0;while($NF != "}"){getline;l=l$0};return l } | |
BEGIN { | |
printf("ext_if = \"hn0\"\n") | |
printf("jail_if = \"lo1\"\n") | |
} | |
$1 ~ "[a-zA-Z0-9]+" && $2 == "{" { | |
delete ports | |
split(readblock(),a,";|}|{|=") | |
name = strip(a[1]) | |
for (i=2;i<length(a);i=i+2) { | |
k = strip(a[i]) | |
if (k == "$ip") { ip = strip(a[i+1]) } | |
if (k == "$ports") { split(strip(a[i+1]),ports,",") } | |
} | |
printf("nat on $ext_if from %s.%d to any -> $ext_if\n",jail_ip,ip) | |
for (p in ports) { | |
split(ports[p],a,":") | |
printf("rdr on $ext_if inet proto tcp to port %d -> %s.%d port %d\n",a[1],jail_ip,ip,a[2]) | |
} | |
} | |
EOM | |
} | |
pf_reload() { | |
pf_rules | pfctl -a jail -f - -vP | |
} | |
new() { | |
local name=${1:?Usage: $0 new <name> [arch]} | |
local arch=${2:-$(sysctl -n hw.machine_arch)} | |
local ip=$(next_ip) | |
: ${ip:?Error: Cant allocate Jail IP} | |
if [ -d /jail/run/$name ] | |
then | |
echo "Error: Path /jail/run/$name exists" | |
exit | |
fi | |
zfs clone pool/jail/template-$arch@base pool/jail/run/$name | |
sysrc -f /jail/run/$name/etc/rc.conf hostname=$name | |
pw -R /jail/run/$name usermod root -w random | |
printf "%s { \$ip = %d; \$ports = \"%d:22\"; }\n" $name $ip $((3000+$ip)) >> /etc/jail.conf | |
pf_rules | pfctl -a jail -f - -v | |
jail -c $name | |
} | |
remove() { | |
local name=${1:?Usage: $0 remove <name>} | |
jls -j $name >/dev/null 2>&1 && jail -r $name | |
sed -i .old -e '/^ *'${name}' [^}]*$/,/} *$/d' -e '/^ *'${name}'.*} *$/d' /etc/jail.conf | |
zfs destroy pool/jail/run/$name | |
pf_rules | pfctl -a jail -f - -v | |
} | |
# Main | |
cmd=$1 | |
shift | |
if [ $cmd = "help" ] | |
then | |
echo "Usage: $0" | |
echo | |
sed -ne 's/^\([A-Za-z0-9\-_]*\)().*/ \1/p' $0 | |
else | |
$cmd $@ | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment