From 361058999baf2b533d143dc34f48890a41ac8377 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Sun, 29 Nov 2020 16:22:36 +0100 Subject: [PATCH 01/25] switched half of the functions to getopt() work in progress!!! --- jaildk | 213 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 139 insertions(+), 74 deletions(-) diff --git a/jaildk b/jaildk index 971bedf..72f66a6 100644 --- a/jaildk +++ b/jaildk @@ -11,14 +11,14 @@ This is jaildk version $version, a jail management toolkit. Usage: $0 ${beg}Building Jails:${end} -base - build a new base -build - install a build chroot of a jail -create - create a new jail from a template -clone - clone an existing jail or jail version -fetch - fetch current port collection +base -b [-w] - build a new base +build [-b ] [-v ] - install a build chroot of a jail +create - create a new jail from a template +clone -s -d [-o ] [-n ] - clone an existing jail or jail version +fetch - fetch current port collection ${beg}Installing Jails:${end} -install - install a jail (prepare mounts, devfs etc) +install [-r function] - install a jail (prepare mounts, devfs etc) uninstall - uninstall a jail remove - remove a jail or a jail version reinstall - stop, remove, install and start a jail @@ -31,12 +31,12 @@ status - display a jail's status rc - execute an rc-script inside a jail ${beg}Managing Jails:${end} -login - login into a jail (also available as separate command) -blogin - chroot into a build jail (dito) +login - login into a jail (also available as separate command) +blogin - chroot into a build jail (dito) ${beg}Transferring Jails:${end} -freeze - freeze (build an image of) a jail -thaw - thaw (install) an image of a jail somewhere else +freeze [-a -b -v ] - freeze (build an image of) a jail +thaw - thaw (install) an image of a jail Run the without arguments to get usage help about the command. @@ -101,28 +101,44 @@ die_if_not_exist() { fi } +usage_build() { + die "Usage: $0 build [-b ] [-v ]" +} + jaildk_build() { jail=$1 mode=$2 - base=$3 - version=$4 + shift + shift + + base='' + version='' - load-jail-config $jail + while getopts "b:v:" arg; do + case $arg in + b) base=1;; + v) version=${OPTARG};; + *) usage_build;; + esac + done if test -z "$mode"; then - echo "Usage: $0 build [] []" - exit 1 + usage_build fi + die_if_not_exist $jail $version + + load-jail-config $jail + if test -n "$buildbase"; then base="$buildbase" elif test -z "$base"; then - # not configured, use default: latest + # nothing configured, use default: latest base=`ls $j/base | tail -1` fi # install the jail to build/ - jaildk_install $jail all $mode rw $base $version + jaildk_install $jail $mode -r all -w -b $base -v $version case $mode in start) @@ -342,46 +358,55 @@ jaildk_rc_mount() { done } -jaildk_install_usage() { - err "Usage: $0 install [[] ]" - err "If is 'all' every script will be executed in rc-order." - err "If is not specified, just execute all scripts with ." - err "Available rc.d-scripts: $RCSCRIPTS_START" - exit 1 +usage_install() { + die "Usage: $0 install [] [-r rc-function] +Install according to its config. Options: + Mode can either be start, stop or status. default: start +-r Only execute function with parameter. default: all. + +Available rc.d-scripts: $RCSCRIPTS_START" } jaildk_install() { jail=$1 - rcd=$2 - mode=$3 + mode=$2 + shift + shift + rcd='' - # used by jaildk_build() only - rw=$4 - base=$5 - version=$6 + # options -b -w -v are undocumented, used by jaildk_build() only + rw='' + base='' + version='' + + while getopts "r:wb:v:" arg; do + case $arg in + w) rw=1;; + b) base=${OPTARG};; + v) version=${OPTARG};; + r) rcd=${OPTARG};; + *) freeze_usage;; + esac + done if test -z "$jail"; then - jaildk_install_usage - fi - - if test -z "$rcd"; then - # default just install all - mode=start - rcd=all - else - case $rcd in - start|stop|restart|status) - # shift args - mode=$rcd - rcd=all - ;; - esac + usage_install fi if test -z "$mode"; then - jaildk_install_usage + mode=start fi + if test -z "$rcd"; then + # default just install everything + rcd=all + fi + + case $mode in + start|stop|restart|status) :;; + *) usage_install;; + esac + die_if_not_exist $jail if test "$rcd" = "all"; then @@ -413,7 +438,7 @@ jaildk_install() { jaildk_uninstall() { # wrapper around _install jail=$1 - rw=$2 + rw=$2 # FIXME !!!!!!!!!! getopt !!!!!!!!!! if test -z "$jail"; then err "Usage: $0 uninstall []" @@ -426,18 +451,33 @@ jaildk_uninstall() { die "Jail $jail($version) is still running, stop it before removing!" fi - jaildk_install $jail all stop $rw + jaildk_install $jail stop -r all -w +} + + +usage_base() { + die "Usage: $0 base -b [-w] +-b can be the name of a base (e.g. 12.2-RELEASE) + or a directory where it shall be created +-w Create a writable base, including compiler and other + build stuff. Use this if you want to use the ports + collection." } jaildk_base() { - base=$1 - rw=$2 + base="" + rw="" + + while getopts "b:w" arg; do + case $arg in + w) rw=1;; + b) base=${OPTARG};; + *) usage_base;; + esac + done if test -z "$base"; then - err "Usage: $0 base []" - err "If the has been set, the base will not cleaned up" - err "and will contain compilers and other build stuff. Use" - err "this if you want to use the ports collection." + usage_base fi removelist="tests @@ -565,21 +605,40 @@ clone() { fi } +usage_clone() { + die "Usage: $0 clone -s -d [-o ] [-n ] +-s Source jail to clone from +-d Destionation jail to create from source +-o Old version +-n New version + +Hints: +- if no source version has been given, tha latest version will be used. +- if no new version has been given, source version will be used. +- if source and new jail are the same, both versions must be given + and a new version of the same jail will be created (update)" +} + jaildk_clone() { - src=$1 - new=$2 - srcversion=$3 - newversion=$4 - update="" + src='' + new='' + srcversion='' + newversion='' + update='' + + while getopts "s:d:o:n:" arg; do + case $arg in + o) srcversion=${OPTARG};; + n) newversion=${OPTARG};; + s) src=${OPTARG};; + d) new=${OPTARG};; + *) usage_clone;; + esac + done + if test -z "$new"; then - echo "Usage: $0 clone [ []]" - echo "Hints:" - echo "- if no source version has been given, tha latest version will be used." - echo "- if no new version has been given, source version will be used." - echo "- if source and new jail are the same, both versions must be given" - echo " and a new version of the same jail will be created (update)" - exit 1 + usage_clone fi if test "$src" = "$new"; then @@ -661,12 +720,16 @@ jaildk_clone() { fi } +usage_create() { + die "Usage: $0 create " +} + jaildk_create() { jail=$1 src=.template if test -z "$jail"; then - die "Usage: $0 create " + usage_create fi . $j/etc/$src/jail.conf @@ -675,7 +738,7 @@ jaildk_create() { mkdir -p $j/etc/$jail - jaildk_clone $src $jail $srcversion $newversion + jaildk_clone -s $src -d $jail -o $srcversion -n $newversion } remove() { @@ -1063,7 +1126,7 @@ endif read yesno case $yesno in y|Y|yes|YES) - jaildk_base $j/base/$os + jaildk_base -b $j/base/$os ;; esac } @@ -1092,7 +1155,7 @@ jaildk_fetch_ports() { ex rm -rf $j/ports/tmp/ports* } -freeze_usage() { +usage_freeze() { echo "Usage: $0 freeze [options] Options: -v freeze of @@ -1123,12 +1186,12 @@ jaildk_freeze() { a) ADDAPPL=1;; b) ADDBASE=1;; v) VERSION=${OPTARG};; - *) freeze_usage;; + *) usage_freeze;; esac done if test -z "$jail"; then - freeze_usage + usage_freeze fi die_if_not_exist $jail "Jail to freeze" $VERSION @@ -1231,9 +1294,12 @@ thaw_tarball() { ex rm -f $srcdir/$tarball } +usage_thaw() { + die "Usage: $0 thaw " +} + jaildk_thaw() { image=$1 - J=$2 # just for testing if test -n "$J"; then j=$J @@ -1243,8 +1309,7 @@ jaildk_thaw() { version=$(echo $image | cut -d\- -f3 | cut -d\. -f1) if ! test -n "$version" -o -n "$jail"; then - err "Usage: $0 thaw " - die "Image filename pattern: --.tgz" + usage_thaw fi if test -d $j/etc/$jail/etc-$version; then From 11c1cd4b19aaf9eccfd59d9aa4d3965aca970702 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Sun, 29 Nov 2020 18:46:50 +0100 Subject: [PATCH 02/25] switch to getopts finished. More changes: - every interactive function has now its own help function - added help command which calls these help functions - made 'start' the default mode in jaildk_build() --- jaildk | 228 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 158 insertions(+), 70 deletions(-) diff --git a/jaildk b/jaildk index 72f66a6..d10604c 100644 --- a/jaildk +++ b/jaildk @@ -1,6 +1,6 @@ #!/bin/sh -version=1.07 +version=1.08 usage_jaildk() { beg=`tput -T ${TERM:-cons25} md` @@ -19,31 +19,43 @@ fetch - fetch current port collection ${beg}Installing Jails:${end} install [-r function] - install a jail (prepare mounts, devfs etc) -uninstall - uninstall a jail -remove - remove a jail or a jail version -reinstall - stop, remove, install and start a jail +uninstall [-w] - uninstall a jail +remove - remove a jail or a jail version +reinstall - stop, remove, install and start a jail ${beg}Maintaining Jails:${end} -start - start a jail -stop - stop a jail -restart - restart a jail -status - display a jail's status -rc - execute an rc-script inside a jail +start - start a jail +stop - stop a jail +restart - restart a jail +status [] - display a jail's status +rc [-r ] - execute an rc-script inside a jail ${beg}Managing Jails:${end} -login - login into a jail (also available as separate command) -blogin - chroot into a build jail (dito) +login [] - login into a jail +blogin - chroot into a build jail ${beg}Transferring Jails:${end} -freeze [-a -b -v ] - freeze (build an image of) a jail -thaw - thaw (install) an image of a jail +freeze [-a -b -v ] - freeze (build an image of) a jail +thaw - thaw (install) an image of a jail -Run the without arguments to get usage help about the command. +${beg}Getting help:${end} +help - request help on EOF ) - echo "$usage" - exit 1 + echo "$usage" + exit 1 +} + +usage_help() { + command=$1 + + usage="usage_${command}" + if ! type "$usage" > /dev/null 2>&1; then + die "Unknown command $command!" + else + $usage + fi } ex() { @@ -67,6 +79,11 @@ bold() { echo -n "$BOLD_OFF" } +fin() { + echo "$*" >&2 + exit +} + die() { bold "$*" >&2 exit 1 @@ -102,7 +119,11 @@ die_if_not_exist() { } usage_build() { - die "Usage: $0 build [-b ] [-v ]" + fin "Usage: $0 build [] [-b ] [-v ] +Mount to $j/build read-writable for maintenance. Options: +-b Use specified . default: use configured base. +-v Mount of . + One of start, stop or status. default: start." } jaildk_build() { @@ -116,14 +137,14 @@ jaildk_build() { while getopts "b:v:" arg; do case $arg in - b) base=1;; + b) base=${OPTARG};; v) version=${OPTARG};; *) usage_build;; esac done if test -z "$mode"; then - usage_build + mode=start fi die_if_not_exist $jail $version @@ -155,6 +176,7 @@ jaildk_rc_mtree() { base=$3 version=$4 rw=$5 + rcscript=mtree if [ $mode = "start" ]; then if test -n "$rw"; then @@ -359,7 +381,7 @@ jaildk_rc_mount() { } usage_install() { - die "Usage: $0 install [] [-r rc-function] + fin "Usage: $0 install [] [-r rc-function] Install according to its config. Options: Mode can either be start, stop or status. default: start -r Only execute function with parameter. default: all. @@ -379,7 +401,7 @@ jaildk_install() { base='' version='' - while getopts "r:wb:v:" arg; do + while getopts "r:b:v:w" arg; do case $arg in w) rw=1;; b) base=${OPTARG};; @@ -435,14 +457,27 @@ jaildk_install() { done } +usage_uninstall() { + fin "Usage: $0 uninstall [-w] +Uninstall . Options: +-w Uninstall writable build chroot." +} + jaildk_uninstall() { # wrapper around _install jail=$1 - rw=$2 # FIXME !!!!!!!!!! getopt !!!!!!!!!! + shift + rw='' + + while getopts "w" arg; do + case $arg in + w) rw=1;; + *) usage_uninstall;; + esac + done if test -z "$jail"; then - err "Usage: $0 uninstall []" - exit 1 + usage_uninstall fi die_if_not_exist $jail @@ -456,7 +491,8 @@ jaildk_uninstall() { usage_base() { - die "Usage: $0 base -b [-w] + fin "Usage: $0 base -b [-w] +Build a base directory from bsd install media. Options: -b can be the name of a base (e.g. 12.2-RELEASE) or a directory where it shall be created -w Create a writable base, including compiler and other @@ -555,7 +591,7 @@ var/tmp" exit 1 else ex mkdir -p $basedir - bsdinstall jail $basedir + bsdinstall jail $basedir || exit 1 if test -z "$rw"; then # run base @@ -606,7 +642,7 @@ clone() { } usage_clone() { - die "Usage: $0 clone -s -d [-o ] [-n ] + fin "Usage: $0 clone -s -d [-o ] [-n ] -s Source jail to clone from -d Destionation jail to create from source -o Old version @@ -721,7 +757,8 @@ jaildk_clone() { } usage_create() { - die "Usage: $0 create " + fin "Usage: $0 create +Create a new jail from template." } jaildk_create() { @@ -751,12 +788,25 @@ remove() { fi } +usage_remove() { + fin "Usage: $0 remove [-v ] +Remove from disk." +} + jaildk_remove() { jail=$1 - version=$2 + shift + version='' + + while getopts "v:" arg; do + case $arg in + v) version=${OPTARG};; + *) usage_remove;; + esac + done if test -z "$jail"; then - die "Usage: $0 remove []" + usage_remove fi if jls | egrep -q "${jail}"; then @@ -789,19 +839,37 @@ jaildk_remove() { } jaildk_jail_usage() { - die "Usage: $0 | status" + fin "Usage: $0 | status" +} + +usage_start() { + fin "Usage $0 start +Start ." +} + +usage_stop() { + fin "Usage $0 stop +Stop ." +} + +usage_restart() { + fin "Usage $0 restart +Restart ." +} + +usage_status() { + fin "Usage $0 status [] +Show status of . Without , show status of all jails." } jaildk_jail() { - mode=$1 jail=$2 + mode=$1 - if test -z "$mode"; then - jaildk_jail_usage - fi - - if test -z "$jail" -a $mode = "status"; then + if test -z "$jail"; then + usage_$mode + elif test -z "$jail" -a $mode = "status"; then bold "Running jails:" bold " JID IP Address Hostname Path" jls | grep -v JID @@ -817,8 +885,6 @@ jaildk_jail() { jls | grep -v JID | awk '{print $3}' | while read J; do jaildk_rc $J status done - elif test -z "$jail"; then - jaildk_jail_usage else bold "Jail $jail $mode:" case $mode in @@ -846,35 +912,33 @@ get_rc_scripts() { done } -jaildk_rc_usage() { - err "Usage: $0 rc { [] | }" - err "If is all, execute for every rc script" - err " must be a parameter of " - err "if only has been given, execute all scripts" - exit 1 +usage_rc() { + fin "Usage: $0 rc [] [-r with parameter . Options: +-r Execute . default: execute all enabled scripts." } jaildk_rc() { jail=$1 - rc=$2 - mode=$3 + mode=$1 + shift + shift + + rc='' + + while getopts "r:" arg; do + case $arg in + r) rcd=${OPTARG};; + *) usage_rc;; + esac + done if test -z "$rc"; then - jaildk_rc_usage + rc='all' fi - if test -z "$mode"; then - # shift args - case $rc in - start|stop|restart|status) - # shift args - mode=$rc - rc=all - ;; - *) - jaildk_rc_usage - ;; - esac + if test -z "$jail" -o -z "$mode"; then + usage_rc fi if ! jls | egrep -q "${jail}"; then @@ -903,6 +967,14 @@ jaildk_rc() { fi } +usage_blogin() { + err "Usage: $file +Chroot into a build jail. + +Mounted build chroot's:" + mount|egrep "base.*build" | awk '{print $3}' | cut -d/ -f 4 + exit 1 +} jaildk_blogin() { jail=$1 @@ -914,10 +986,7 @@ jaildk_blogin() { else file="$0" fi - echo "Usage: $file []" - echo "mounted build jails:" - mount|egrep "base.*build" | awk '{print $3}' | cut -d/ -f 4 - exit + usage_blogin fi chroot="$j/build/$jail" @@ -941,6 +1010,16 @@ jaildk_blogin() { env - HOME=$home TERM=$term SHELL=$shell PATH=$path chroot $chroot $shell } +usage_login() { + err "Usage: $file [] +Login into a jail by name, ip or domain. If has not been +specified, login as root. + +Available jails:" + jls + exit 1 +} + jaildk_login() { jail=$1 user=$2 @@ -954,10 +1033,7 @@ jaildk_login() { else file="$0" fi - echo "Usage: $file []" - echo "available jails:" - jls - exit + usage_login fi jid="" @@ -995,10 +1071,19 @@ jaildk_login() { env - JAIL=$jail HOME=$home TERM=$term SHELL=$shell PATH=$path $jexec -U $user $jid $shell } +usage_reinstall() { + fin "Usage: $0 reinstall +Stop, uninstall, install and start . +" +} jaildk_reinstall() { jail=$1 + if test -z "$jail"; then + usage_reinstall + fi + die_if_not_exist $jail if jls | egrep -q "${jail}"; then @@ -1023,7 +1108,7 @@ jaildk_setup() { j=$1 if test -z "$j"; then - die "Usage: $0 setup " + fin "Usage: $0 setup " fi bold "preparing directories" @@ -1295,7 +1380,7 @@ thaw_tarball() { } usage_thaw() { - die "Usage: $0 thaw " + fin "Usage: $0 thaw " } jaildk_thaw() { @@ -1396,6 +1481,9 @@ case $runner in setup|reinstall|install|uninstall|build|blogin|login|clone|create|remove|rc|base|fetch|freeze|thaw) jaildk_$runner $* ;; + help) + usage_help $* + ;; *) usage_jaildk $* ;; From e2193aba1337b0b185064dc180cdb37e4c8f3ae6 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Sun, 29 Nov 2020 18:52:14 +0100 Subject: [PATCH 03/25] documented changed commandline syntax --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f07ecf1..293695d 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Create the file `/etc/jail.conf` with the following innitial contents: sysvshm = "new"; host.hostname = $name; path = "/jail/run/$name"; - exec.prestart = "/jail/bin/jaildk install $name all start"; + exec.prestart = "/jail/bin/jaildk install $name start"; exec.clean = "true"; } @@ -135,7 +135,7 @@ A normal base directory cannot be used with the ports collection because jaildk removes libraries and binaries for security reasons from normal bases. To create a build base, execute: -`jaildk base 12-RELEASE-build rw` +`jaildk base -b 12-RELEASE-build -w` Next, add the following entry to the configuration of you jail. To stay with our example, edit `/jail/etc/myjail/jail.conf` and add: @@ -209,22 +209,22 @@ The very first thing to do is to update the host system using `freebsd-update`. Next create a new base version: ``` -jaildk base `uname -r` +jaildk base -b `uname -r` ``` Now you can create clone of your jail with a new version: ``` -jaildk clone myjail myjail 20201106 20210422 +jaildk clone -s myjail -d myjail -o 20201106 -n 20210422 ``` Mount the build chroot for the new version: ``` -jaildk build myjail start `uname -r` 20210422 +jaildk build myjail start -b `uname -r` -v 20210422 ``` And finally chroot into the new jail and update it: ``` -blogin myjail +jaildk blogin myjail pkg update ... ``` From 90b462b46a634d1205351bc295ba2700943e5270 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Sun, 29 Nov 2020 19:03:57 +0100 Subject: [PATCH 04/25] fix typo --- jaildk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jaildk b/jaildk index d10604c..b4cf273 100644 --- a/jaildk +++ b/jaildk @@ -407,7 +407,7 @@ jaildk_install() { b) base=${OPTARG};; v) version=${OPTARG};; r) rcd=${OPTARG};; - *) freeze_usage;; + *) usage_install;; esac done From 6d75ff25bf30565f0aca76975a0063200a448f7e Mon Sep 17 00:00:00 2001 From: Culsu Date: Sun, 29 Nov 2020 20:44:34 +0100 Subject: [PATCH 05/25] Altered the NIC IP alias to match the example --- README.md | 2 +- jaildk | 0 2 files changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 jaildk diff --git a/README.md b/README.md index 293695d..6f69b88 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Refer to [jail(8)](https://www.freebsd.org/cgi/man.cgi?query=jail&sektion=8) for Next add the following lines to your `/etc/rc.conf`: ``` -ifconfig_em0_alias0="inet 144.76.67.168/32" +ifconfig_em0_alias0="inet 172.16.1.1/32" jail_enable="YES" ``` diff --git a/jaildk b/jaildk old mode 100644 new mode 100755 From 61ae2100c3bf36ee21f9c97f5ebec2f3a615865e Mon Sep 17 00:00:00 2001 From: Culsu Date: Sun, 29 Nov 2020 22:18:34 +0100 Subject: [PATCH 06/25] Added support to automagically set the hostname in the jails rc.conf based on the hostname in /etc/jail.conf --- jaildk | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/jaildk b/jaildk index b4cf273..910f547 100755 --- a/jaildk +++ b/jaildk @@ -751,6 +751,7 @@ jaildk_clone() { echo else . $j/etc/$src/jail.conf + jail=$new bold "To mount the build chroot of the new jail, execute:" echo "jaildk build $new start $base $newversion" fi @@ -763,6 +764,9 @@ Create a new jail from template." jaildk_create() { jail=$1 + # $jail gets overwritten in jaildk_clone or some subcall to .template :-( ... + newjail=$jail + src=.template if test -z "$jail"; then @@ -774,8 +778,13 @@ jaildk_create() { newversion=`date +%Y%m%d` mkdir -p $j/etc/$jail - + jaildk_clone -s $src -d $jail -o $srcversion -n $newversion + # some perl magic to extract the hostname (if any) from /etc/jail.conf - and write it into the jails rc.conf + jailhostname=$(cat /etc/jail.conf | tr -d '\t\r\n ' | perl -ne '$_ =~ /.*'"$newjail"'(\{(?:\{.*\}|[^{])*\})|\w+/; print $1;' | grep -oE 'hostname=[^;]+' | cut -d= -f2) + sed -iE 's/^hostname.*$/hostname="'"$jailhostname"'"/' $j/etc/$newjail/local-etc-$newversion/rc.conf + + } remove() { From f59920e1197ec1df17f8c6132027b938988c6e8c Mon Sep 17 00:00:00 2001 From: Culsu Date: Sun, 29 Nov 2020 22:20:46 +0100 Subject: [PATCH 07/25] added a safety check --- jaildk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jaildk b/jaildk index 910f547..ac98e0e 100755 --- a/jaildk +++ b/jaildk @@ -782,7 +782,7 @@ jaildk_create() { jaildk_clone -s $src -d $jail -o $srcversion -n $newversion # some perl magic to extract the hostname (if any) from /etc/jail.conf - and write it into the jails rc.conf jailhostname=$(cat /etc/jail.conf | tr -d '\t\r\n ' | perl -ne '$_ =~ /.*'"$newjail"'(\{(?:\{.*\}|[^{])*\})|\w+/; print $1;' | grep -oE 'hostname=[^;]+' | cut -d= -f2) - sed -iE 's/^hostname.*$/hostname="'"$jailhostname"'"/' $j/etc/$newjail/local-etc-$newversion/rc.conf + [ -n "$jailhostname" ] && sed -iE 's/^hostname.*$/hostname="'"$jailhostname"'"/' $j/etc/$newjail/local-etc-$newversion/rc.conf } From 21800fe55ef55e6318cdcf405731d4ec737e13b3 Mon Sep 17 00:00:00 2001 From: Culsu Date: Sun, 29 Nov 2020 22:30:56 +0100 Subject: [PATCH 08/25] Added hint how to restart the network interface (after adding alias) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6f69b88..df8994b 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ jail_enable="YES" ``` You may need to replace the interface name `em0` with the one in use on your system. - +To apply the alias to the interface you can use the netif rc script: `/etc/rc.d/netif restart`. ### Create the jail ``` From 82999c9c7a1ce57debe893b25ca752d3bbc949fb Mon Sep 17 00:00:00 2001 From: Culsu Date: Sun, 29 Nov 2020 22:32:24 +0100 Subject: [PATCH 09/25] Added hint how to restart the network interface (after adding alias) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index df8994b..8f2641a 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ jail_enable="YES" ``` You may need to replace the interface name `em0` with the one in use on your system. -To apply the alias to the interface you can use the netif rc script: `/etc/rc.d/netif restart`. +You might need to restart the interface to apply the alias: `/etc/rc.d/netif restart`. ### Create the jail ``` From fd005a540405da7b9b4997d8f5053f5d94321b27 Mon Sep 17 00:00:00 2001 From: Culsu Date: Sun, 29 Nov 2020 22:34:41 +0100 Subject: [PATCH 10/25] jlogin -> login --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8f2641a..10e9989 100644 --- a/README.md +++ b/README.md @@ -197,7 +197,7 @@ fcgiwrap is running as pid 37682. ### Login into the running jail for administration ``` -# jaildk jlogin myjail +# jaildk login myjail ``` You can use this to login into a database or execute commands inside the jail. From fc8fb3bb9476831c8554f8c9453a3b4c8a7bf9ff Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Mon, 30 Nov 2020 19:22:02 +0100 Subject: [PATCH 11/25] more doc --- README.md | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 140 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 10e9989..41fd758 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,145 @@ used to build, update, manage and run jails in a versioned environment. Every jail consists of layers of directories mounted on top of each other using nullfs mounts. Some of them can be shared among jails, -some are versioned. +some are versioned. By using shared and versioned layers of mounts it +is easy to update jails in a new version while the current version is +still running, you can switch back to an older version of a jail. + +Most of the layers are mounted read-only for security reasons. + +Let's take a look at the layers of a typical running jail built with `jaildk`: +``` + 1 /jail/base/12.1-RELEASE-p10 /jail/run/db read-only + 2 /dev/md12 /jail/run/db/tmp nosuid + 3 devfs /jail/run/db/dev multilabel + 4 /jail/log/db-20201026 /jail/run/db/var/log + 5 /jail/appl/db-20201026 /jail/run/db/usr/local read-only + 6 /jail/etc/db/etc-20201026 /jail/run/db/etc read-only + 7 /jail/etc/db/local-etc-20201026 /jail/run/db/usr/local/etc read-only + 8 /jail/etc/db/cron-20201026 /jail/run/db/var/cron + 9 /jail/home/db/root-20201026 /jail/run/db/root + 10 /jail/data/db/mysql-20201026 /jail/run/db/usr/local/data/mysql + 11 /backup/db /jail/run/db/var/backups + | + +--- root of the jail +``` + +As can be easily deduced this is a database jail with the following layers: + +1. **base layer**: This is basically the same as a FreeBSD base, which + contains all biinaries, libraries and other files required to boot + up a FreeBSD system. Our base doesn't contain a kernel by default, + but you could add one, required if you want to use the ports + collection and compile `lsof` yourself.
+ This particular base is based on 12.1-RELEASE-p10, that is, I + created it while I had this release installed and running on the + host system. +2. **tmp layer**: Just a ramdisk for `/tmp`, the size can be tuned. +3. **dev layer**: Contains /dev/null and friends, required by every jail. +4. **log layer**: Here we have our first versioned layer for + `/var/log`. Notise how all other layers are using the same version, + this is done by purpose (but can be changed if you like). The + version is a jail variable (see below) which is being used for all + layers. +5. **application layer**: As you know if you're using FreeBSD, any + additional software, wether installed from a port or as package, + will be installed to `/usr/local`. In our case it contains the + mysql server software, bash and a couple of supporting + utilities. It is being mounted read-only, so no new software can be + installed in the running jail. This might sound annoying at first, + because you can't just install stuff inside the jail anytime. But + it forces you to work more disciplined. Once a jail has been + completely built you can be sure, all components match with each + other. Read below how to install or update software in a jail. +6. **/etc layer**: this just contains the normal etc, it is basically + a stripped copy of the host `/etc`. We do not use it at all inside + a jail, but it's required nontheless. There are some exceptions + however, like `/etc/resolv.conf`. +7. **/usr/local/etc layer**: This is the place we configure all + aspects of the jail, all configs reside here (like in our case the + mysql config). It is also being mounted read-only, just like + the etc layer. +8. **cron layer**: A writable mount for the crontabs of users inside + the jail. That way one can modify crontabs with `crontab + -e`. However, if you don't want or need this, just remove the layer + and add cronjobs to `/etc/crontab`. +9. **/root layer**: most of the administrative work inside a jail must + be done as the root user and it would be a pity not to have a + writable history. So, `/root` is mounted writable to add more + comfort. +10. **a data layer**: A versioned data layer which contains the binary + data of our mysql server. This is very jail specific and you have + to add such layers yourself. Variants of such a layer include the + document root of a webserver or the repositories of a git server. +11. **backup layer**: Another custom layer, here we've mounted a + global backup directory of our host which contains all backups. + +All layers are configured in a `mount.conf` file specific for each +jail. The one for this jail looks like this: +``` +base/$base $name nullfs ro +md $name/tmp mfs rw,nosuid,async 500m 1777 +dev $name/dev devfs +log/$name-$version $name/var/log nullfs rw +appl/db-$version $name/usr/local nullfs ro +etc/$name/etc-$version $name/etc nullfs ro +etc/$name/local-etc-$version $name/usr/local/etc nullfs ro +etc/$name/cron-$version $name/var/cron nullfs rw +home/$name/root-$version $name/root nullfs rw +data/$name/mysql-$version $name/usr/local/data/mysql nullfs rw +/backup/db $name/var/backups nullfs rw +``` + +Now, as you can see, we're using variables here. Those are defined in +the `jail.conf` (not to be confused with `/etc/jail.conf` on the +host!): +``` +name=db +version=20201026 +base=12.1-RELEASE-p10 +``` + +You might wonder how the other aspects of a jail are configured like +ip addresses, routing, jail parameters, sysctls etc. Well, that's +beyond the purpose of `jaildk`. You just use the standard FreeBSD +mechanism for these things, that is `/ect/rc.conf`, `/etc/jail.conf`, +`service jail ...`, `jexec`, etc. However, `jaildk` provides some +handy wrappers to make live easier. + +For an overview of the provided commands, here's the usage screen: +``` +Usage: jaildk + +Building Jails: +base - build a new base +build - install a build chroot of a jail +create - create a new jail from a template +clone - clone an existing jail or jail version +fetch - fetch current port collection + +Installing Jails: +install - install a jail (prepare mounts, devfs etc) +uninstall - uninstall a jail +remove - remove a jail or a jail version +reinstall - stop, remove, install and start a jail + +Maintaining Jails: +start - start a jail +stop - stop a jail +restart - restart a jail +status - display a jail's status +rc - execute an rc-script inside a jail + +Managing Jails: +login - login into a jail (also available as separate command) +blogin - chroot into a build jail (dito) + +Transferring Jails: +freeze - freeze (build an image of) a jail +thaw - thaw (install) an image of a jail somewhere else + +Run the without arguments to get usage help about the command. +``` ## Installation @@ -250,6 +388,7 @@ This software is licensed under the BSD license. ## Authors T.v.Dein +F.Sass (Culsu) ## Project homepage From 29e51de9bd104a2061d0bbd626de949bb57f5165 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Mon, 30 Nov 2020 19:23:21 +0100 Subject: [PATCH 12/25] fix --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 41fd758..6dfc632 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,8 @@ Most of the layers are mounted read-only for security reasons. Let's take a look at the layers of a typical running jail built with `jaildk`: ``` 1 /jail/base/12.1-RELEASE-p10 /jail/run/db read-only - 2 /dev/md12 /jail/run/db/tmp nosuid - 3 devfs /jail/run/db/dev multilabel + 2 /dev/md12 /jail/run/db/tmp + 3 devfs /jail/run/db/dev 4 /jail/log/db-20201026 /jail/run/db/var/log 5 /jail/appl/db-20201026 /jail/run/db/usr/local read-only 6 /jail/etc/db/etc-20201026 /jail/run/db/etc read-only From 3840643ec6bd098161c162c50ee9c5b9813e8040 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Mon, 30 Nov 2020 19:28:41 +0100 Subject: [PATCH 13/25] wrong help screen --- README.md | 53 +++++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 6dfc632..1fa90e4 100644 --- a/README.md +++ b/README.md @@ -41,20 +41,20 @@ As can be easily deduced this is a database jail with the following layers: 2. **tmp layer**: Just a ramdisk for `/tmp`, the size can be tuned. 3. **dev layer**: Contains /dev/null and friends, required by every jail. 4. **log layer**: Here we have our first versioned layer for - `/var/log`. Notise how all other layers are using the same version, + `/var/log`. Notice how all other layers are using the same version, this is done by purpose (but can be changed if you like). The version is a jail variable (see below) which is being used for all layers. 5. **application layer**: As you know if you're using FreeBSD, any additional software, wether installed from a port or as package, will be installed to `/usr/local`. In our case it contains the - mysql server software, bash and a couple of supporting + mysql server software, bash and a couple of supporting utilities. It is being mounted read-only, so no new software can be installed in the running jail. This might sound annoying at first, - because you can't just install stuff inside the jail anytime. But - it forces you to work more disciplined. Once a jail has been - completely built you can be sure, all components match with each - other. Read below how to install or update software in a jail. + because you can't just install stuff inside the jail anytime you + like. But it forces you to work more disciplined. Once a jail has + been completely built you can be sure, all components match with + each other. Read below how to install or update software in a jail. 6. **/etc layer**: this just contains the normal etc, it is basically a stripped copy of the host `/etc`. We do not use it at all inside a jail, but it's required nontheless. There are some exceptions @@ -112,37 +112,38 @@ handy wrappers to make live easier. For an overview of the provided commands, here's the usage screen: ``` -Usage: jaildk +Usage: /usr/local/bin/jaildk Building Jails: -base - build a new base -build - install a build chroot of a jail -create - create a new jail from a template -clone - clone an existing jail or jail version -fetch - fetch current port collection +base -b [-w] - build a new base +build [-b ] [-v ] - install a build chroot of a jail +create - create a new jail from a template +clone -s -d [-o ] [-n ] - clone an existing jail or jail version +fetch - fetch current port collection Installing Jails: -install - install a jail (prepare mounts, devfs etc) -uninstall - uninstall a jail -remove - remove a jail or a jail version -reinstall - stop, remove, install and start a jail +install [-r function] - install a jail (prepare mounts, devfs etc) +uninstall [-w] - uninstall a jail +remove - remove a jail or a jail version +reinstall - stop, remove, install and start a jail Maintaining Jails: -start - start a jail -stop - stop a jail -restart - restart a jail -status - display a jail's status -rc - execute an rc-script inside a jail +start - start a jail +stop - stop a jail +restart - restart a jail +status [] - display a jail's status +rc [-r ] - execute an rc-script inside a jail Managing Jails: -login - login into a jail (also available as separate command) -blogin - chroot into a build jail (dito) +login [] - login into a jail +blogin - chroot into a build jail Transferring Jails: -freeze - freeze (build an image of) a jail -thaw - thaw (install) an image of a jail somewhere else +freeze [-a -b -v ] - freeze (build an image of) a jail +thaw - thaw (install) an image of a jail -Run the without arguments to get usage help about the command. +Getting help: +help - request help on ``` ## Installation From 46b298f0167af07717a532c3883217367c1d57d7 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Mon, 30 Nov 2020 19:30:12 +0100 Subject: [PATCH 14/25] hups --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1fa90e4..a698f0b 100644 --- a/README.md +++ b/README.md @@ -148,7 +148,7 @@ help - request help on ## Installation -Execute the following command: +Download the file `jaildk` or clone this repository to your FreeBSD server and execute the following command: ``` ./jaildk setup ``` From f0690c74eb2e839bff12fe9ad03d5561c3bdfc4b Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Mon, 30 Nov 2020 19:31:22 +0100 Subject: [PATCH 15/25] satzbau zefix --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a698f0b..912e2b3 100644 --- a/README.md +++ b/README.md @@ -153,8 +153,8 @@ Download the file `jaildk` or clone this repository to your FreeBSD server and e ./jaildk setup ``` -This will create the directory structure required for the tool install -the tool itself, create a template jail and build a base directory. +This will create the directory structure required for the tool itself, +create a template jail and build a base directory. ## Basic usage From a041a0d0cbaa08fa0485435507ca89eb94258427 Mon Sep 17 00:00:00 2001 From: Culsu Date: Mon, 30 Nov 2020 22:17:49 +0100 Subject: [PATCH 16/25] Added ipfw.conf functions for jail start/stop, to manage firewalling --- jaildk | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/jaildk b/jaildk index ac98e0e..f2086ca 100755 --- a/jaildk +++ b/jaildk @@ -764,7 +764,7 @@ Create a new jail from template." jaildk_create() { jail=$1 - # $jail gets overwritten in jaildk_clone or some subcall to .template :-( ... + # $jail gets overwritten in jaildk_clone or somewhere... newjail=$jail src=.template @@ -782,7 +782,9 @@ jaildk_create() { jaildk_clone -s $src -d $jail -o $srcversion -n $newversion # some perl magic to extract the hostname (if any) from /etc/jail.conf - and write it into the jails rc.conf jailhostname=$(cat /etc/jail.conf | tr -d '\t\r\n ' | perl -ne '$_ =~ /.*'"$newjail"'(\{(?:\{.*\}|[^{])*\})|\w+/; print $1;' | grep -oE 'hostname=[^;]+' | cut -d= -f2) - [ -n "$jailhostname" ] && sed -iE 's/^hostname.*$/hostname="'"$jailhostname"'"/' $j/etc/$newjail/local-etc-$newversion/rc.conf + echo "new name: $jailhostname" + echo "in path $j/etc/$jail/local-etc-$newversion/rc.conf" + sed -iE 's/^hostname.*$/hostname="'"$jailhostname"'"/' $j/etc/$newjail/local-etc-$newversion/rc.conf } @@ -903,6 +905,7 @@ jaildk_jail() { ;; *) service jail $mode $jail + jaildk_ipfw $jail $mode ;; esac fi @@ -1460,6 +1463,31 @@ jaildk_thaw() { bold "Done. Thawed jail $jail $version from $image." } +jaildk_ipfw() { + jail=$1 + mode=$2 + if [ -f "$j/etc/$jail/ipfw.conf" ]; then + echo + bold "Managing IPFW Rules..." + case $mode in + start) + # Deleting existing rules first to avoid duplicates. + ipfw show | grep -E "// $jail\$" | while read rule; do sh -c "ipfw delete $(echo $rule| awk '{print $1}')"; done + # Getting current jails IP.. + jailip=$(jls | grep -E "$jail\$" | awk '{print $2}') + # Adding rules + cat /jail/etc/revprx/ipfw.conf | awk -v jailname="$jail" '{print "ipfw add "$0" // " jailname}' | sed -E "s/\\\$ip/$jailip/g" | while read rule; do $rule; done + ;; + stop) + # Deleting rules + ipfw show | grep -E "// $jail\$" | while read rule; do bold "Deleting rule $rule"; sh -c "ipfw delete $(echo $rule| awk '{print $1}')"; done + ;; + esac + bold "... done" + echo + fi +} + ########################## # From 62617b89cf11da4b63b1760d50c6d3236882eb8b Mon Sep 17 00:00:00 2001 From: Culsu Date: Mon, 30 Nov 2020 22:22:36 +0100 Subject: [PATCH 17/25] added a security check for overwriting the hostname inside the jails rc.conf --- jaildk | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/jaildk b/jaildk index f2086ca..f2c7d7f 100755 --- a/jaildk +++ b/jaildk @@ -764,7 +764,7 @@ Create a new jail from template." jaildk_create() { jail=$1 - # $jail gets overwritten in jaildk_clone or somewhere... + # $jail gets overwritten in jaildk_clone or some subcall to .template :-( ... newjail=$jail src=.template @@ -782,11 +782,11 @@ jaildk_create() { jaildk_clone -s $src -d $jail -o $srcversion -n $newversion # some perl magic to extract the hostname (if any) from /etc/jail.conf - and write it into the jails rc.conf jailhostname=$(cat /etc/jail.conf | tr -d '\t\r\n ' | perl -ne '$_ =~ /.*'"$newjail"'(\{(?:\{.*\}|[^{])*\})|\w+/; print $1;' | grep -oE 'hostname=[^;]+' | cut -d= -f2) - echo "new name: $jailhostname" - echo "in path $j/etc/$jail/local-etc-$newversion/rc.conf" - sed -iE 's/^hostname.*$/hostname="'"$jailhostname"'"/' $j/etc/$newjail/local-etc-$newversion/rc.conf - - + if [ -n "$jailhostname" ]; then + echo "new name: $jailhostname" + echo "in path $j/etc/$jail/local-etc-$newversion/rc.conf" + sed -iE 's/^hostname.*$/hostname="'"$jailhostname"'"/' $j/etc/$newjail/local-etc-$newversion/rc.conf + fi } remove() { From de04b88e196e958de885e916123d1bd0d6439df2 Mon Sep 17 00:00:00 2001 From: Culsu Date: Mon, 30 Nov 2020 22:37:18 +0100 Subject: [PATCH 18/25] Added ipfw.conf functions for jail start/stop, to manage firewalling --- jaildk | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/jaildk b/jaildk index f2c7d7f..b416867 100755 --- a/jaildk +++ b/jaildk @@ -715,7 +715,7 @@ jaildk_clone() { clone $j/data/$src/www $j/data/$new/www clone $j/data/$src/spool $j/data/$new/spool - ex cp -pRp $j/etc/$src/mount.conf $j/etc/$src/ports.conf $j/etc/$src/mtree.conf $j/etc/$new/ + ex cp -pRp $j/etc/$src/mount.conf $j/etc/$src/ports.conf $j/etc/$src/mtree.conf $j/etc/$src/ipfw.conf $j/etc/$new/ echo "Creating $j/etc/$src/jail.conf" cat $j/etc/$src/jail.conf | egrep -v "^(name|version)=" > $j/etc/$new/jail.conf @@ -1165,6 +1165,9 @@ home/$name/root-$version $name/root nullfs rw' > bold "creating template config $j/etc/.template/ports.conf" (echo bash; echo ca_root_nss) > $j/etc/.template/ports.conf + bold "creating template config $j/etc/.template/ipfw.conf" + touch $j/etc/.template/ipfw.conf + bold "creating template config $j/etc/.template/mtree.conf" # touch $j/etc/.template/mtree.conf echo '/set type=dir uid=0 gid=0 mode=01777 From 3270db0d78c87d721af788c61cb069f792d1466a Mon Sep 17 00:00:00 2001 From: Culsu Date: Mon, 30 Nov 2020 22:42:48 +0100 Subject: [PATCH 19/25] added ipfw section to the readme --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 912e2b3..9675eff 100644 --- a/README.md +++ b/README.md @@ -372,6 +372,18 @@ The last step is to remove the current running jail, change the version in `etc/ If there's anything wrong you can always go back to the previous version using the above steps. +## Advanced Features +Jaildk also offers some advanced features like automatically setting up and deleting ipfw rules or freezing and thawing a jail (to make it easily portable). +### Using the IPFW +To use the IPFW on your host you first have to enable ipfw in your hosts rc.conf `firewall_enable="YES"`. +You probably want to set the default firewalling-type there aswell, check out the [FreeBSD handbook](https://www.freebsd.org/doc/handbook/firewalls-ipfw.html) for further information. +Once enabled you also need to start ipfw by executing the rc script: `/etc/rc.d/ipfw start`. +Be aware that inter-jail communication is transfered via the loopback interface (normally lo0) for which there is a high priority allow any to any rule by default: `allow ip from any to any via lo` +In order to control the inter-jail communication you have to delete this rule first. + +If an ipfw.conf exists for a jail (e.g. /jail/etc/myjail/ipfw.conf) the rules inside that config file are added when starting, and deleted when stopping the jail. +E.g. allowing HTTP/HTTPS traffic for that jail (webserver): `allow tcp from any to $ip setup keep-state` +As in the above rule demonstrated `$ip` is reserved and automatically replaced with the jails own ip (as reported by `jls`). ## Getting help From 5a779ea249800b54b21e6cb2d270951d1ac68653 Mon Sep 17 00:00:00 2001 From: Culsu Date: Mon, 30 Nov 2020 22:45:24 +0100 Subject: [PATCH 20/25] some readme styling.. :-) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9675eff..74bacab 100644 --- a/README.md +++ b/README.md @@ -401,6 +401,7 @@ This software is licensed under the BSD license. ## Authors T.v.Dein + F.Sass (Culsu) ## Project homepage From dd55fb6ca5c50d1c375a8c9ccbd413e1a299b34b Mon Sep 17 00:00:00 2001 From: Culsu Date: Mon, 30 Nov 2020 22:48:11 +0100 Subject: [PATCH 21/25] changed some of the new text... --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 74bacab..1938543 100644 --- a/README.md +++ b/README.md @@ -383,7 +383,7 @@ In order to control the inter-jail communication you have to delete this rule fi If an ipfw.conf exists for a jail (e.g. /jail/etc/myjail/ipfw.conf) the rules inside that config file are added when starting, and deleted when stopping the jail. E.g. allowing HTTP/HTTPS traffic for that jail (webserver): `allow tcp from any to $ip setup keep-state` -As in the above rule demonstrated `$ip` is reserved and automatically replaced with the jails own ip (as reported by `jls`). +As demonstrated in the previous rule `$ip` is reserved and automatically replaced with the jails own ip (as reported by `jls`). ## Getting help From 6c544268ed9b66c441614509d767c86045eadd60 Mon Sep 17 00:00:00 2001 From: Culsu Date: Mon, 30 Nov 2020 23:04:30 +0100 Subject: [PATCH 22/25] separated add and delete into their own functions. --- jaildk | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/jaildk b/jaildk index b416867..f30cb85 100755 --- a/jaildk +++ b/jaildk @@ -1474,16 +1474,11 @@ jaildk_ipfw() { bold "Managing IPFW Rules..." case $mode in start) - # Deleting existing rules first to avoid duplicates. - ipfw show | grep -E "// $jail\$" | while read rule; do sh -c "ipfw delete $(echo $rule| awk '{print $1}')"; done - # Getting current jails IP.. - jailip=$(jls | grep -E "$jail\$" | awk '{print $2}') - # Adding rules - cat /jail/etc/revprx/ipfw.conf | awk -v jailname="$jail" '{print "ipfw add "$0" // " jailname}' | sed -E "s/\\\$ip/$jailip/g" | while read rule; do $rule; done + jaildk_ipfw_delete $jail "y" + jaildk_ipfw_add $jail ;; stop) - # Deleting rules - ipfw show | grep -E "// $jail\$" | while read rule; do bold "Deleting rule $rule"; sh -c "ipfw delete $(echo $rule| awk '{print $1}')"; done + jaildk_ipfw_delete $jail ;; esac bold "... done" @@ -1491,6 +1486,22 @@ jaildk_ipfw() { fi } +jaildk_ipfw_add() { + jail=$1 + # Getting current jails IP.. + jailip=$(jls | grep -E "$jail\$" | awk '{print $2}') + # Adding rules + cat $j/etc/$jail/ipfw.conf | awk -v jailname="$jail" '{print "ipfw add "$0" // " jailname}' | sed -E "s/\\\$ip/$jailip/g" | while read rule; do $rule; done + +} + +jaildk_ipfw_delete() { + jail=$1 + noout=$2 + # Deleting rules + ipfw show | grep -E "// $jail\$" | while read rule; do [ -z "$2" ] && bold "Deleting rule $rule"; sh -c "ipfw delete $(echo $rule| awk '{print $1}')"; done + +} ########################## # From 615939bccdca11d5193e541a0d7c107ec478c732 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Tue, 1 Dec 2020 18:40:32 +0100 Subject: [PATCH 23/25] various modifications to pull request #10: - re-fill paragraphs in README - added section about booting ipfw rules - added way to execute ipfw function from commandline (required for booting) - enhanced ipfw.conf parser - enhanced ip address parsing - added v6 support - added jail.conf variable support --- README.md | 54 ++++++++++++++++++++++++++++++++++++++++++++---------- jaildk | 41 +++++++++++++++++++++++++++++++++++------ 2 files changed, 79 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 1938543..8a4da3a 100644 --- a/README.md +++ b/README.md @@ -373,17 +373,51 @@ The last step is to remove the current running jail, change the version in `etc/ If there's anything wrong you can always go back to the previous version using the above steps. ## Advanced Features -Jaildk also offers some advanced features like automatically setting up and deleting ipfw rules or freezing and thawing a jail (to make it easily portable). -### Using the IPFW -To use the IPFW on your host you first have to enable ipfw in your hosts rc.conf `firewall_enable="YES"`. -You probably want to set the default firewalling-type there aswell, check out the [FreeBSD handbook](https://www.freebsd.org/doc/handbook/firewalls-ipfw.html) for further information. -Once enabled you also need to start ipfw by executing the rc script: `/etc/rc.d/ipfw start`. -Be aware that inter-jail communication is transfered via the loopback interface (normally lo0) for which there is a high priority allow any to any rule by default: `allow ip from any to any via lo` -In order to control the inter-jail communication you have to delete this rule first. -If an ipfw.conf exists for a jail (e.g. /jail/etc/myjail/ipfw.conf) the rules inside that config file are added when starting, and deleted when stopping the jail. -E.g. allowing HTTP/HTTPS traffic for that jail (webserver): `allow tcp from any to $ip setup keep-state` -As demonstrated in the previous rule `$ip` is reserved and automatically replaced with the jails own ip (as reported by `jls`). +Jaildk also offers some advanced features like automatically setting +up and deleting ipfw rules or freezing and thawing a jail (to make it +easily portable). + +### Using the IPFW + +To use the IPFW on your host you first have to enable ipfw in your +hosts rc.conf `firewall_enable="YES"`. You probably want to set the +default firewalling-type there aswell, check out the +[FreeBSD handbook](https://www.freebsd.org/doc/handbook/firewalls-ipfw.html) +for further information. + +Once enabled you also need to start ipfw by executing the rc script: + +`/etc/rc.d/ipfw start`. + +Be aware that inter-jail communication is transfered via the loopback +interface (normally lo0) for which there is a high priority allow any +to any rule by default: + +`allow ip from any to any via lo` + +In order to control the inter-jail communication you have to delete +this rule first. + +If an ipfw.conf exists for a jail (e.g. /jail/etc/myjail/ipfw.conf) +the rules inside that config file are added when starting, and deleted +when stopping the jail. E.g. allowing HTTP/HTTPS traffic for that +jail (webserver): + +`allow tcp from any to $ip setup keep-state` + +As demonstrated in the previous rule `$ip` is reserved and +automatically replaced with the jails own ip (as reported by +`jls`). The same applies to the ipv6 address which will be available +as variable `$ip6`. Also, all variables in the jails `jail.conf` can +be used. + +In order to make these ipfw rules available on boot, you need to add +the following line to `/etc/jail.conf` in the section of the jail +which uses custom ipfw rules: + +`exec.prestart = "/jail/bin/jaildk ipfw $name"` + ## Getting help diff --git a/jaildk b/jaildk index f30cb85..0939ca8 100755 --- a/jaildk +++ b/jaildk @@ -29,6 +29,7 @@ stop - stop a jail restart - restart a jail status [] - display a jail's status rc [-r ] - execute an rc-script inside a jail +ipfw - add or remove ipfw rules ${beg}Managing Jails:${end} login [] - login into a jail @@ -380,6 +381,8 @@ jaildk_rc_mount() { done } + + usage_install() { fin "Usage: $0 install [] [-r rc-function] Install according to its config. Options: @@ -1169,7 +1172,6 @@ home/$name/root-$version $name/root nullfs rw' > touch $j/etc/.template/ipfw.conf bold "creating template config $j/etc/.template/mtree.conf" -# touch $j/etc/.template/mtree.conf echo '/set type=dir uid=0 gid=0 mode=01777 . type=dir mode=0755 tmp @@ -1466,10 +1468,24 @@ jaildk_thaw() { bold "Done. Thawed jail $jail $version from $image." } +usage_ipfw() { + echo "Usage: $0 ipfw +[Un]install ipfw rules. can be start or stop. +The jail needs to have a ipfw.conf file, containing +ipfw rules. You can use variables like \$ip and \$ip6 +and you need to omit the 'ipfw add' of the command." + exit 1 +} + jaildk_ipfw() { jail=$1 mode=$2 - if [ -f "$j/etc/$jail/ipfw.conf" ]; then + + if test -z "$mode"; then + usage_ipfw + fi + + if test -f "$j/etc/$jail/ipfw.conf"; then echo bold "Managing IPFW Rules..." case $mode in @@ -1488,11 +1504,24 @@ jaildk_ipfw() { jaildk_ipfw_add() { jail=$1 + + # support jail variables as well + load-jail-config $jail + # Getting current jails IP.. - jailip=$(jls | grep -E "$jail\$" | awk '{print $2}') + ip=`jls -n -j $jail ip4.addr | cut -d= -f2` + if test -z "$ip"; then + die "Jail $jail doesn't have an ipv4 address!" + fi + + ip6=`jls -n -j $jail ip6.addr | cut -d= -f2` # optional, no checks + # Adding rules - cat $j/etc/$jail/ipfw.conf | awk -v jailname="$jail" '{print "ipfw add "$0" // " jailname}' | sed -E "s/\\\$ip/$jailip/g" | while read rule; do $rule; done - + egrep "^[a-z]" $j/etc/$jail/ipfw.conf | while read LINE; do + rule=$(eval echo "ipfw add $LINE // $jail") + echo $rule + $rule + done } jaildk_ipfw_delete() { @@ -1529,7 +1558,7 @@ case $runner in start|stop|status|restart) jaildk_jail $runner $* ;; - setup|reinstall|install|uninstall|build|blogin|login|clone|create|remove|rc|base|fetch|freeze|thaw) + setup|reinstall|install|uninstall|build|blogin|login|clone|create|remove|rc|base|fetch|freeze|thaw|ipfw) jaildk_$runner $* ;; help) From 8f10788e556c43a535b07cb23bc4d75eac1d3e0b Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Thu, 3 Dec 2020 19:01:05 +0100 Subject: [PATCH 24/25] added pf support --- README.md | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ jaildk | 85 ++++++++++++++++++++++++++++++++++-- 2 files changed, 208 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8a4da3a..150d59f 100644 --- a/README.md +++ b/README.md @@ -418,6 +418,132 @@ which uses custom ipfw rules: `exec.prestart = "/jail/bin/jaildk ipfw $name"` +Be aware, that the ipfw module will only be executed if the jail is +running so that we can properly determine the ip addresses of the +running jail. **Note**: this might change in the future. + +### Using pf + +Beside ipfw, Free supports +[pf](https://www.freebsd.org/doc/de_DE.ISO8859-1/books/handbook/firewalls-pf.html) +as well. You can use pf with `jaildk`. Unlike the ipfw module (see +above) it is a normal `install` module. That is it can be installed or +reloaded before the jail is running (i.e. like the mount module). + +In order to use `pf` with a jail, enable and configure it according to +the FreeBSD handbook linked above. It is recommended to include +general block, scrup, state rules, communication to and fro localhost +etc and just leave everything which is related to your jail. + +Just so that you know how such a global `/etc/pf.conf` file might look +like, here's a simple one: +```shell +# variables +ext = "em0" +me = "your ipv4 address here" +me5 = "your ipv6 address here/64" +loginports = "{ 22, 5222, 443 }" +icmp_types = "echoreq" + +# tables. look at the contents of a table: +# pfctl -t bad_hosts -T show +# remove an entry from a table: +# pfctl -t bad_hosts -T delete $ip +table persist + +# default policy +set block-policy drop + +# optimize according to rfc's +set optimization aggressive + +# normalisation +scrub in all +antispoof for $ext + +# allow localhost +pass quick on $local + +# additional default block rules w/ logging. to view the log: +# tcpdump -n -e -ttt -r /var/log/pflog +# to view live log: +# tcpdump -n -e -ttt -i pflog0 +block in log on $ext +block in log on $ext inet6 + +# whoever makes it into those tables: you loose +block quick from + +# allow outgoing established sessions +pass out keep state +pass out inet6 keep state + +# allow troubleshooting +pass in on $ext inet proto icmp all icmp-type $icmp_types keep state +pass in on $ext inet proto udp from any to any port 33433 >< 33626 keep state + +# allow all icmpv6 +pass in quick inet6 proto icmp6 all keep state + +# allow login but punish offenders +block quick from +pass in quick on $ext inet proto tcp from any to $me port $loginports \ + flags S/SAFR keep state \ + (max-src-conn-rate 10/60, \ + overload flush global) label ServicesTCP +pass in quick on $ext inet6 proto tcp from any to $me6 port $loginports \ + flags S/SAFR keep state \ + (max-src-conn-rate 10/60, \ + overload flush global) label ServicesTCP +``` + +Install the ruleset with `service pf start`. + +Now that everything is prepared you can create a pf.conf file for your +jail. Here's an example I use for a webserver jail, which includes a +git server: +```shell +ip = "jail ip4 addr" +ip6 = "jail ip6 addr" +loginports = "{ 22 }" +prodports = "{ 80, 443 }" +ext = "em0" + +# dynamic block list +table + +# restrict foreigners +block quick from +pass in quick on $ext inet proto tcp from any to $ip port $loginports \ + flags S/SAFR keep state \ + (max-src-conn-rate 10/60, \ + overload flush global) label ServicesTCP + +# allow production traffic v4 +pass in quick on $ext proto tcp from any to $ip port $prodports keep state + +# allow production traffic v6 +pass in quick inet6 proto tcp from any to $ip6 port $prodports keep state +``` + +That's it already. Now install the jail as usual. You can also install +the pf ruleset for the jail separately: + +`jaildk install myjail start -r pf` + +To take look at the rules, execute: + +`jaildk install myjail status -r pf` + +You can of course manipulate the ruleset manually. `jaildk` installs +rulesets into a jail specific anchor using the following naming +scheme: `/jail/`. So, for example to view the rules, execute: + +`pfctl -a /jail/myjail -s rules` + +Manipulate a jail specific table: + +`pfctl -a /jail/myjail -t blocked -T show` ## Getting help diff --git a/jaildk b/jaildk index 0939ca8..9e2c928 100755 --- a/jaildk +++ b/jaildk @@ -1,6 +1,6 @@ #!/bin/sh -version=1.08 +version=1.09 usage_jaildk() { beg=`tput -T ${TERM:-cons25} md` @@ -119,6 +119,58 @@ die_if_not_exist() { fi } +parse_jail_conf() { + # + # just in case we want or have to fetch variables out of + # /etc/jail.conf, this is the way to go. Call it like this: + # + # ip=`parse_jail_conf $jail ip4.addr` + # + # Output may be empty, so check before using. Multiple variables + # of the same type (like multiple ip addresses) will be returned + # comma separated. + jail=$1 + search=$2 + JAIL='' + list='' + + # fetch 20 lines after "^$jail {", ignore comments + egrep -A20 "^$jail" jail.conf | egrep -v "^ *#" | \ + # turn each line into an evaluable shell expression \ + sed -e 's/ *{//g' -e 's/}//g' -e 's/ *= */=/g' -e 's/;$//' | \ + # ignore empty lines \ + egrep -v '^$' | while read LINE; do + if echo "$LINE" | egrep -q "="; then + case $JAIL in + $jail) + var=`echo "$LINE" | cut -d= -f1` + opt=`echo "$LINE" | cut -d= -f2 | sed -e 's/^"//' -e 's/"$//'` + case $var in + $search) + if test -z "$list"; then + list="$opt" + else + list="$list,$opt" + fi + ;; + esac + ;; + *) + echo $list + return + ;; + esac + else + case $LINE in + \*) JAIL=any;; + *) JAIL="$LINE";; + esac + fi + done +} + + + usage_build() { fin "Usage: $0 build [] [-b ] [-v ] Mount to $j/build read-writable for maintenance. Options: @@ -171,6 +223,33 @@ jaildk_build() { esac } +jaildk_rc_pf() { + jail=$1 + mode=$2 + conf=$j/etc/$jail/pf.conf + + # FIXME: maybe we use parse_jail_conf() to fetch ip addresses, + # generate a config file containing pf macros, which the user + # needs to include in the jails pf.conf? On the other hand, + # there's not that much duplication in the config. So, maybe not. + if test -f $conf; then + case $mode in + start) + bold "Installing PF rules for jail $jail:" + pfctl -a /jail/$jail -f $conf -v + ;; + status) + bold "PF rules for jail $jail:" + pfctl -a /jail/$jail -s rules -v + ;; + stop) + bold "Removing PF rules for jail $jail:" + pfctl -a /jail/$jail -f $conf -v -F all + ;; + esac + fi +} + jaildk_rc_mtree() { jail=$1 mode=$2 @@ -1540,8 +1619,8 @@ jaildk_ipfw_delete() { JAILDIR=/jail # install modules -RCSCRIPTS_START="jaildk_rc_mount jaildk_rc_rcoff jaildk_rc_ports jaildk_rc_mtree" -RCSCRIPTS_STOP="jaildk_rc_rcoff jaildk_rc_mount jaildk_rc_ports" +RCSCRIPTS_START="jaildk_rc_mount jaildk_rc_rcoff jaildk_rc_ports jaildk_rc_mtree jaildk_rc_pf" +RCSCRIPTS_STOP="jaildk_rc_pf jaildk_rc_rcoff jaildk_rc_mount jaildk_rc_ports" # globals j=$JAILDIR From b26f64ed4e1842e1b741a2319f631a7bd1c98c94 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Thu, 3 Dec 2020 19:06:03 +0100 Subject: [PATCH 25/25] +path --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 150d59f..dbaf75c 100644 --- a/README.md +++ b/README.md @@ -499,7 +499,7 @@ pass in quick on $ext inet6 proto tcp from any to $me6 port $loginports \ Install the ruleset with `service pf start`. -Now that everything is prepared you can create a pf.conf file for your +Now that everything is prepared you can create a `/jail/etc/myjail/pf.conf` file for your jail. Here's an example I use for a webserver jail, which includes a git server: ```shell