From 7e5c2ad591f4eab3dfa11948bb89afb008b28329 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Fri, 2 Jul 2021 13:03:33 +0200 Subject: [PATCH] added pf rule generator --- jaildk | 183 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 160 insertions(+), 23 deletions(-) diff --git a/jaildk b/jaildk index 39cf012..9a71165 100755 --- a/jaildk +++ b/jaildk @@ -1,6 +1,6 @@ #!/bin/sh -version=1.20 +version=1.21 usage_jaildk() { beg=`tput -T ${TERM:-cons25} md` @@ -242,34 +242,162 @@ jaildk_build() { esac } +jaildk_pf_ruleset() { + # internal helper to [un]install a pf ruleset + conf=$1 + mode=$2 + anchor=$3 + jail=$4 + + case $mode in + start) + bold "Installing PF rules for jail $jail:" + pfctl -a /jail/$anchor -f $conf -v + ;; + status) + bold "PF NAT rules for jail $jail:" + pfctl -a /jail/$anchor -s nat -v + echo + bold "PF rules for jail $jail:" + pfctl -a /jail/$anchor -s rules -v + ;; + stop) + bold "Removing PF rules for jail $jail:" + pfctl -a /jail/$anchor -v -F all + ;; + restart) + jaildk_pf_ruleset $jail $conf stop $anchor $jail + jaildk_pf_ruleset $jail $conf start $anchor $jail + ;; + esac +} + +jaildk_pf_map() { + extif=$1 + proto=$2 + eip=$3 + eport=$4 + mport=$5 + ip=$6 + v6=$7 + + echo "rdr pass on $extif $v6 proto ${proto} from any to ${eip} port ${port} -> ${ip} port ${mport}" +} + +jaildk_pf_rule() { + extif=$1 + proto=$2 + eip=$3 + eport=$4 + v6=$5 + + echo "pass in quick on $extif $v6 proto ${eproto} from any to ${eip} port ${eport}" +} + + jaildk_rc_pf() { jail=$1 mode=$2 conf=$j/etc/$jail/pf.conf + ruleset=$j/etc/$jail/pf-ruleset.conf + + load-jail-config $jail + + if test -n "$rules" -o -n "$maps"; then + # generate a pf.conf based on config variables + echo "# generated pf ruleset for jail, generated on ` date`" > $ruleset + extif=$(netstat -rnfinet | grep default | cut -f4 -w) + fi + + if test -n "$ip" -a -n "$maps"; then + # nat and rdr come first + + # SAMPLE ruleset + # maps="web ntp kjk" + # map_web_proto="tcp" + # map_web_exposed_port=80 + # map_web_mapped_port=8080 + # map_web_exposed_ip="123.12.12.3" + # map_web_exposed_ip6="2a01::ff" + # map_ntp_proto="udp" + # map_ntp_exposed_port=123 + # map_ntp_mapped_port=1234 + # map_ntp_exposed_ip="123.12.12.33" + # map_kjk_proto="tcp" + # map_kjk_exposed_ports="1501 1502 1502" # maped 1:1 + # map_kjk_exposed_ip="123.12.12.33" + + for map in $maps; do + # slurp in the values for this map + eval _proto=\${map_${map}_proto:-tcp} + eval _eport=\${map_${map}_exposed_port} + eval _mport=\${map_${map}_mapped_port:-${_eport}} + eval _eports=\${map_${map}_exposed_ports} + eval _eip=\${map_${map}_exposed_ip:-$extif} + eval _eip6=\${map_${map}_exposed_ip6:-$extif} + + if test -z ${_eport} -o -z ${_eip}; then + echo "Warning: ignoring incomplete map: $map!" + continue + fi + + if test -n "${_eport}"; then + if test -z "{_mport}"; then + # map ports 1:1 + _mport=${_eport} + fi + echo "# from map $map" >> $ruleset + jaildk_pf_map $extif ${_eproto} ${_eip} ${_eport} ${_mport} ${ip} >> $ruleset + + if test -n "${_eip6}" -a -n "$ip6"; then + jaildk_pf_map $extif ${_eproto} ${_eip6} ${_eport} ${_mport} ${ip6} inet6 >> $ruleset + fi + fi + + for port in ${_eports}; do + jaildk_pf_map $extif ${_eproto} ${_eip} ${port} ${port} ${ip} >> $ruleset + + if test -n "${_eip6}" -a -n "$ip6"; then + jaildk_pf_map $extif ${_eproto} ${_eip6} ${port} ${port} ${ip6} inet6 >> $ruleset + fi + done + done + fi + + if test -n "$ip" -a -n "$rules"; then + # rules="open web" + # rule_open="any" + # rule_web_proto="tcp"_ + # rule_web_port="80,443" + + # pass in quick on $ext proto tcp from any to $extip port 80 keep state + + for rule $rules; do + eval _proto=\${rule_${rule}_proto:-tcp} + eval _port=\${rule_${rule}_port} + + if test -n "${_port}"; then + echo "# from map $map" >> $ruleset + jaildk_pf_rule $extif ${_proto} ${ip} ${_port} >> $ruleset + else + echo "Warning: incomplete rule: $rule!" + continue + fi + + if test -n "${ip6}"; then + jaildk_pf_rule $extif ${_proto} ${ip6} ${_port} inet6 >> $ruleset + fi + done + fi + + if test -s $ruleset; then + anchor="$jail/jaildk" + jaildk_pf_ruleset $ruleset $mode $anchor $jail + fi - # 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 -v -F all - ;; - restart) - jaildk_rc_pf $jail stop - jaildk_rc_pf $jail start - ;; - esac + anchor="$jail/custom" + jaildk_pf_ruleset $conf $mode $anchor $jail fi } @@ -1838,9 +1966,14 @@ usage_vnet() { echo "You'll also need PF nat rules in order to be able to reach the outside" echo "from the jail or vice versa." + + exit } jaildk_vnet() { + # + # This is no rc.d subcommand, but a standalone command, because it must + # be executed by jail(8) via exec.created hook. jail=$1 mode=$2 shift @@ -1863,6 +1996,10 @@ jaildk_vnet() { load-jail-config $jail + if test -z "$ip" -a -z "$gw"; then + usage_vnet + fi + vnethost="ep${jail}.h" vnetjail="ep${jail}.j"