Skip to content

Commit

Permalink
mt: update pfrule.sh, improve table handling (#602)
Browse files Browse the repository at this point in the history
- mt: default NTPd is now openntpd
- mt: install pfrule from GH repo (vs inline)
  - add mt6-fetch, get_jail_data
- pfrule.sh:
  - adds a -n option
  - adds binat loading support
  - loads tables in pf.conf.d
  - unload is smarter now
- host: ntpd stop -> onestop
- base: fix jail config so `service jail start base` works
  • Loading branch information
msimerson authored Nov 13, 2024
1 parent 9c1dd7d commit 34ea03b
Show file tree
Hide file tree
Showing 12 changed files with 216 additions and 145 deletions.
80 changes: 59 additions & 21 deletions contrib/pfrule.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,78 @@

# pfrule.sh
#
# Use pfctl to load and unload PF config files into named PF anchors.
# Config files are named for the anchor they'll be inserted
# at. See https://github.com/msimerson/Mail-Toaster-6/wiki/PF
# Matt Simerson, matt@tnpi.net, 2024-11
#
# Matt Simerson, matt@tnpi.net, 2023-06
# Use pfctl to load and unload PF rules into named anchors from config
# files. See https://github.com/msimerson/Mail-Toaster-6/wiki/PF

_etcpath="$(dirname -- "$( readlink -f -- "$0"; )";)"
ETC_PATH="$(dirname -- "$( readlink -f -- "$0"; )";)"
JAIL_NAME=$(basename "$(dirname "$(dirname $ETC_PATH)")")
PREVIEW="$2"

usage() {
echo " usage: $0 [ load | unload ]"
echo " usage: $0 [ load | unload ] [-n]"
echo " "
exit 1
}

for _f in "$_etcpath"/*.conf; do
[ -f "$_f" ] || continue
cleanup() {
if [ -f allow.conf ] && [ ! -f filter.conf ]; then
echo "mv allow.conf filter.conf"
mv allow.conf filter.conf
fi
}

load_tables() {
for _f in "$ETC_PATH"/*.table; do
[ -f "$_f" ] || continue
_table_name=$(basename $_f .table)
do_cmd "pfctl -t $_table_name -T replace -f $_f"
done
}

_anchor=$(basename $_f .conf) # nat, rdr, allow
_jailname=$(basename "$(dirname "$(dirname $_etcpath)")")
flush_tables() {
for _f in "$ETC_PATH"/*.table; do
[ -f "$_f" ] || continue
_table_name=$(basename $_f .table)
do_cmd "pfctl -t $_table_name -T flush"
done
}

do_cmd() {
if [ "$PREVIEW" = "-n" ]; then
echo "$1"
else
$1 || exit 1
fi
}

flush() {
case "$1" in
"load" )
_cmd="pfctl -a $_anchor/$_jailname -f $_f"
;;
"unload" )
_cmd="pfctl -a $_anchor/$_jailname -F all"
;;
*)
usage
;;
"nat" ) do_cmd "$2 -F nat" ;;
"rdr" ) do_cmd "$2 -F nat" ;;
"filter") do_cmd "$2 -F rules" ;;
esac
}

echo "$_cmd"
$_cmd || exit 1
cleanup

# load tables first, they may be referenced in anchored files
if [ "$1" = "load" ]; then load_tables; fi

for _anchor in binat nat rdr filter; do
_f="$ETC_PATH/$_anchor.conf"
[ -f "$_f" ] || continue

_pfctl="pfctl -a $_anchor/$JAIL_NAME"

case "$1" in
"load" ) do_cmd "$_pfctl -f $_f" ;;
"unload" ) flush "$_anchor" "$_pfctl" ;;
* ) usage ;;
esac
done

if [ "$1" = "unload" ]; then flush_tables; fi

exit
7 changes: 7 additions & 0 deletions include/shell.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ install_zsh()
stage_exec chpass -s /usr/local/bin/zsh
}

install_fish()
{
tell_status "installing fish"
stage_pkg_install fish
stage_exec chpass -s /usr/local/bin/fish
}

configure_bash()
{
if ! grep -q profile "$1/root/.profile"; then
Expand Down
112 changes: 49 additions & 63 deletions mail-toaster.sh
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ export TOASTER_EDITOR_PORT=${TOASTER_EDITOR_PORT:="vim-tiny"}
# See https://github.com/msimerson/Mail-Toaster-6/wiki/MySQL
export TOASTER_MYSQL=${TOASTER_MYSQL:="1"}
export TOASTER_MARIADB=${TOASTER_MARIADB:="0"}
export TOASTER_NTP=${TOASTER_NTP:="ntp"}
export TOASTER_NTP=${TOASTER_NTP:="openntpd"}
export TOASTER_MSA=${TOASTER_MSA:="haraka"}
export TOASTER_PKG_AUDIT=${TOASTER_PKG_AUDIT:="0"}
export TOASTER_PKG_BRANCH=${TOASTER_PKG_BRANCH:="latest"}
Expand Down Expand Up @@ -353,12 +353,15 @@ base_snapshot_exists()

jail_conf_header()
{
local _path="$ZFS_JAIL_MNT/$1"
if [ "$1" = "base" ]; then _path="$BASE_MNT"; fi

cat <<EO_JAIL_CONF_HEAD
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.clean;
devfs_ruleset=5;
path = "$ZFS_JAIL_MNT/\$name";
path = "$_path";
interface = $JAIL_NET_INTERFACE;
host.hostname = \$name;
Expand Down Expand Up @@ -468,7 +471,7 @@ add_jail_conf()

if [ ! -e /etc/jail.conf ]; then
tell_status "adding /etc/jail.conf header"
jail_conf_header | tee -a /etc/jail.conf
jail_conf_header $1 | tee -a /etc/jail.conf
fi

if grep -q "^$1\\>" /etc/jail.conf; then
Expand All @@ -495,17 +498,26 @@ get_safe_jail_path()
fi
}

get_jail_data()
{
if [ "$1" = "base" ]; then
echo "$BASE_MNT/data"
else
echo "$ZFS_DATA_MNT/$1"
fi
}

add_jail_conf_d()
{
store_config "/etc/jail.conf.d/$(safe_jailname $1).conf" <<EO_JAIL_RC
$(jail_conf_header)
$(jail_conf_header $1)
$(safe_jailname $1) {$(get_safe_jail_path $1)
mount.fstab = "$ZFS_DATA_MNT/$1/etc/fstab";
mount.fstab = "$(get_jail_data $1)/etc/fstab";
ip4.addr = $JAIL_NET_INTERFACE|${_jail_ip};
ip6.addr = $JAIL_NET_INTERFACE|$(get_jail_ip6 $1);${JAIL_CONF_EXTRA}
exec.created = "$ZFS_DATA_MNT/$1/etc/pf.conf.d/pfrule.sh load";
exec.poststop = "$ZFS_DATA_MNT/$1/etc/pf.conf.d/pfrule.sh unload";
exec.created = "$(get_jail_data $1)/etc/pf.conf.d/pfrule.sh load";
exec.poststop = "$(get_jail_data $1)/etc/pf.conf.d/pfrule.sh unload";
}
EO_JAIL_RC
}
Expand Down Expand Up @@ -584,43 +596,12 @@ cleanup_staged_fs()

install_pfrule()
{
store_exec "$ZFS_DATA_MNT/$1/etc/pf.conf.d/pfrule.sh" <<'EO_PF_RULE'
#!/bin/sh
# pfrule.sh
#
# Matt Simerson, matt@tnpi.net, 2023-06
#
# Use pfctl to load and unload PF rules into named anchors from config
# files. See https://github.com/msimerson/Mail-Toaster-6/wiki/PF
_etcpath="$(dirname -- "$( readlink -f -- "$0"; )";)"
local _pfdir
_pfdir="$(get_jail_data $1)/etc/pf.conf.d"

usage() {
echo " usage: $0 [ load | unload ]"
echo " "
exit 1
}
for _f in "$_etcpath"/*.conf; do
[ -f "$_f" ] || continue
_anchor=$(basename $_f .conf) # nat, rdr, allow
_jailname=$(basename "$(dirname "$(dirname $_etcpath)")")
_pfctl="pfctl -a $_anchor/$_jailname"
case "$1" in
"load" ) _cmd="$_pfctl -f $_f" ;;
"unload" ) _cmd="$_pfctl -F all" ;;
* ) usage ;;
esac
echo "$_cmd"
$_cmd || exit 1
done
exit
EO_PF_RULE
mt6-fetch contrib pfrule.sh
install -d "$_pfdir"
install -C -m 0755 contrib/pfrule.sh "$_pfdir/pfrule.sh"
}

install_fstab()
Expand Down Expand Up @@ -744,9 +725,10 @@ start_staged_jail()
{
local _name=${1:-"$SAFE_NAME"}
local _path=${2:-"$STAGE_MNT"}
local _fstab="$ZFS_DATA_MNT/$_name/etc/fstab.stage"
local _fstab

if [ "$_name" = "base" ]; then _fstab="$BASE_MNT/data/etc/fstab"; fi
_fstab="$(get_jail_data $_name)/etc/fstab"
if [ "$_name" != "base" ]; then _fstab="$_fstab.stage"; fi

tell_status "stage jail $_name startup"

Expand Down Expand Up @@ -1103,14 +1085,7 @@ get_public_ip()

fetch_and_exec()
{
if [ ! -d provision ]; then mkdir provision; fi

if [ -d ".git" ]; then
tell_status "running from git, skipping fetch"
else
fetch -o provision -m "$TOASTER_SRC_URL/provision/$1.sh"
fi

mt6-fetch provision "$1.sh"
sh "provision/$1.sh"
}

Expand Down Expand Up @@ -1282,21 +1257,32 @@ unprovision()
echo "done"
}

mt6-include()
mt6-fetch()
{
if [ ! -d include ]; then
mkdir include || exit
local _dir="$1"
local _file="$2"

if [ -z "$_dir" ] || [ -z "$_file" ]; then
echo "FATAL: invalid args to mt6-fetch"; return 1
fi

if [ -d ".git" ]; then
tell_status "skipping include d/l, running from git"
else
fetch -m -o "include/$1.sh" "$TOASTER_SRC_URL/include/$1.sh"
tell_status "running from git, skipping fetch"
return
fi

if [ ! -f "include/$1.sh" ]; then
echo "unable to download include/$1.sh"
exit
fi
if [ ! -d "$_dir" ]; then mkdir "$_dir"; fi

fetch -o "$_dir" -m "$TOASTER_SRC_URL/$_dir/$2"
}

mt6-include()
{
mt6-fetch include "$1.sh"

if [ ! -f "include/$1.sh" ]; then
echo "unable to download include/$1.sh"
exit
fi

# shellcheck source=include/$.sh disable=SC1091
Expand Down
12 changes: 6 additions & 6 deletions provision/base.sh
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,7 @@ EO_MAKE_CONF
configure_fstab() {
local _sub_dir=${1:-""}
local _etc_path="$BASE_MNT/${_sub_dir}etc"
if [ ! -d "$_etc_path" ]; then
mkdir -p "$_etc_path"
fi
if [ ! -d "$_etc_path" ]; then mkdir -p "$_etc_path"; fi

tee "$_etc_path/fstab" <<EO_FSTAB
# Device Mountpoint FStype Options Dump Pass#
Expand All @@ -192,16 +190,17 @@ EO_FSTAB

configure_base()
{
if [ ! -d "$BASE_MNT/usr/ports" ]; then
mkdir "$BASE_MNT/usr/ports"
fi
if [ ! -d "$BASE_MNT/usr/ports" ]; then mkdir "$BASE_MNT/usr/ports"; fi

tell_status "adding base jail resolv.conf"
cp /etc/resolv.conf "$BASE_MNT/etc"

tell_status "setting base jail timezone (to hosts)"
cp /etc/localtime "$BASE_MNT/etc"

tell_status "installing $BASE_MNT/etc/hosts"
cp /etc/hosts "$BASE_MNT/etc"

configure_make_conf

tell_status "adding base rc.conf settings"
Expand All @@ -221,6 +220,7 @@ configure_base()
configure_bourne_shell "$BASE_MNT"
configure_csh_shell "$BASE_MNT"
configure_fstab "data/"
install_pfrule base
}

install_periodic_conf()
Expand Down
19 changes: 14 additions & 5 deletions provision/dcc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,20 @@ configure_dcc()
"$STAGE_MNT/var/db/dcc/dcc_conf"

_pf_etc="$ZFS_DATA_MNT/dcc/etc/pf.conf.d"
store_config "$_pf_etc/allow.conf" <<EO_PF_ALLOW
table <dcc_server> { $(get_jail_ip dcc), $(get_jail_ip6 dcc) }
pass in quick proto udp from any port 6277 to <ext_ip>
pass in quick proto udp from any port 6277 to <dcc_server>
EO_PF_ALLOW

get_public_ip
get_public_ip ipv6

store_config "$_pf_etc/dcc.table" <<EO_DCC_TABLE
$PUBLIC_IP4
$PUBLIC_IP6
$(get_jail_ip dcc)
$(get_jail_ip6 dcc)
EO_DCC_TABLE

store_config "$_pf_etc/filter.conf" <<EO_PF_FILTER
pass in quick proto udp from any port 6277 to <dcc>
EO_PF_FILTER

store_config "$_pf_etc/rdr.conf" <<EO_PF_RDR
rdr inet proto tcp from any to <ext_ip4> port 6277 -> $(get_jail_ip dcc)
Expand Down
Loading

0 comments on commit 34ea03b

Please sign in to comment.