From 381d09592b5e297fe51295e4ffb492b404fe1ab2 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:53:37 -0700 Subject: [PATCH 01/76] Allow setting custom interface when doing "rdr" --- usr/local/share/bastille/rdr.sh | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 6bd7fbcd..1b25e930 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -81,16 +81,17 @@ check_jail_validity() { fi fi - # Check if rdr-anchor is defined in pf.conf if ! (pfctl -sn | grep rdr-anchor | grep 'rdr/\*' >/dev/null); then error_exit "rdr-anchor not found in pf.conf" fi # Check if ext_if is defined in pf.conf + # If EXT_IF is set, use it instead of the default if [ -n "${bastille_pf_conf}" ]; then - EXT_IF=$(grep "^[[:space:]]*${bastille_network_pf_ext_if}[[:space:]]*=" ${bastille_pf_conf}) if [ -z "${EXT_IF}" ]; then + EXT_IF=$(grep "^[[:space:]]*${bastille_network_pf_ext_if}[[:space:]]*=" ${bastille_pf_conf}) + else error_exit "bastille_network_pf_ext_if (${bastille_network_pf_ext_if}) not defined in pf.conf" fi fi @@ -98,8 +99,8 @@ check_jail_validity() { # function: write rule to rdr.conf persist_rdr_rule() { -if ! grep -qs "$1 $2 $3" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then - echo "$1 $2 $3" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" +if ! grep -qs "$IF_NAME $1 $2 $3" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then + echo "$IF_NAME $1 $2 $3" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" fi } @@ -107,8 +108,8 @@ persist_rdr_log_rule() { proto=$1;host_port=$2;jail_port=$3; shift 3; log=$@; -if ! grep -qs "$proto $host_port $jail_port $log" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then - echo "$proto $host_port $jail_port $log" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" +if ! grep -qs "$IF_NAME $proto $host_port $jail_port $log" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then + echo "$IF_NAME $proto $host_port $jail_port $log" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" fi } @@ -142,6 +143,12 @@ fi } while [ $# -gt 0 ]; do + # Check if interface was specified, and use it instead of default + if echo "${1}" | ifconfig | grep -wo "${1}"; then + IF_NAME="${1}" + EXT_IF=ext_if="${1}" + shift + fi case "$1" in list) if [ "${TARGET}" = 'ALL' ]; then From dc9822a01317e652a8a4262138574369684d0a9c Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:01:17 -0700 Subject: [PATCH 02/76] also list interface when doing "list all" for published ports --- usr/local/share/bastille/list.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/list.sh b/usr/local/share/bastille/list.sh index ebb28cc4..211f2f99 100644 --- a/usr/local/share/bastille/list.sh +++ b/usr/local/share/bastille/list.sh @@ -108,7 +108,7 @@ list_all(){ if [ "${JAIL_IP}" = "-" ]; then JAIL_IP=$(/usr/sbin/jls -j ${JAIL_NAME} ip6.addr 2> /dev/null); fi fi JAIL_HOSTNAME=$(/usr/sbin/jls -j ${JAIL_NAME} host.hostname 2> /dev/null) - JAIL_PORTS=$(pfctl -a "rdr/${JAIL_NAME}" -Psn 2> /dev/null | awk '{ printf "%s/%s:%s"",",$7,$14,$18 }' | sed "s/,$//") + JAIL_PORTS=$(pfctl -a "rdr/${JAIL_NAME}" -Psn 2> /dev/null | awk '{ printf "%s %s/%s:%s"",",$4,$7,$14,$18 }' | sed "s/,$//") JAIL_PATH=$(/usr/sbin/jls -j ${JAIL_NAME} path 2> /dev/null) if [ "${IS_FREEBSD_JAIL}" -eq 1 ]; then JAIL_RELEASE=$(jexec -l ${JAIL_NAME} freebsd-version -u 2> /dev/null) From 1c807bbef98507707815b30ffb55cdaf5644a4fc Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:26:44 -0700 Subject: [PATCH 03/76] Add docs about RDR multiple interfaces --- docs/chapters/subcommands/rdr.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index a65375a2..ac7af3c6 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -24,3 +24,17 @@ specify the interface they run on in rc.conf (or other config files) rdr on em0 inet proto udp from any to any port = 2053 -> 10.17.89.1 port 53 # bastille rdr dev1 clear nat cleared + +If you have a host with multiple interfaces, and you want to specify which +one to use, `bastille rdr` allows you to pass any interface to the command. +If you do not specify an interface, the default one will be used. + +.. code-block:: shell + + # bastille rdr em0 dev1 tcp 2001 22 + # bastille rdr dev1 list + rdr on em0 inet proto tcp from any to any port = 2001 -> 10.17.89.1 port 22 + # bastille rdr dev1 vtnet0 udp 2053 53 + # bastille rdr dev1 list + rdr on em0 inet proto tcp from any to any port = 2001 -> 10.17.89.1 port 22 + rdr on vtnet0 inet proto udp from any to any port = 2053 -> 10.17.89.1 port 53 From 2b6a7e83f940a564c34581696708641a2fba24c2 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:58:55 -0700 Subject: [PATCH 04/76] add new interface option to docs --- docs/chapters/subcommands/rdr.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index ac7af3c6..8a6e2fd0 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -14,7 +14,7 @@ specify the interface they run on in rc.conf (or other config files) .. code-block:: shell # bastille rdr --help - Usage: bastille rdr TARGET [clear] | [list] | [tcp ] | [udp ] + Usage: bastille rdr TARGET [clear] | [list] | [ tcp ] | [ udp ] # bastille rdr dev1 tcp 2001 22 # bastille rdr dev1 list rdr on em0 inet proto tcp from any to any port = 2001 -> 10.17.89.1 port 22 From bafa183b08a92fc27f96c011e5ff402f7add804e Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 9 Dec 2024 19:27:08 -0700 Subject: [PATCH 05/76] remove unecessary "echo" --- usr/local/share/bastille/rdr.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 1b25e930..92f6d4ab 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -144,7 +144,7 @@ fi while [ $# -gt 0 ]; do # Check if interface was specified, and use it instead of default - if echo "${1}" | ifconfig | grep -wo "${1}"; then + if ifconfig | grep -wo "${1}"; then IF_NAME="${1}" EXT_IF=ext_if="${1}" shift From eb65800a0cd5b345bd202fce911cb88f85ab35a4 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 9 Dec 2024 22:02:01 -0700 Subject: [PATCH 06/76] show output when creating rdr rule --- usr/local/share/bastille/rdr.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 92f6d4ab..24733628 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -124,6 +124,9 @@ if [ -n "$JAIL_IP6" ]; then printf '%s\nrdr pass on $%s inet proto %s to port %s -> %s port %s\n' "$EXT_IF" "${bastille_network_pf_ext_if}" "$1" "$2" "$JAIL_IP6" "$3" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f- fi +local interface="$( echo $EXT_IF | awk -F'"' '{print $2}')" +info "[${JAIL_NAME}]:" +info "Redirecting: ${1} port ${2} to ${3} on ${interface}" } # function: load rdr rule with log via pfctl @@ -139,14 +142,16 @@ if [ -n "$JAIL_IP6" ]; then printf '%s\nrdr pass %s on $%s inet proto %s to port %s -> %s port %s\n' "$EXT_IF" "$log" "${bastille_network_pf_ext_if}" "$proto" "$host_port" "$JAIL_IP6" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f- fi - +local interface="$( echo $EXT_IF | awk -F'"' '{print $2}')" +info "[${JAIL_NAME}]:" +info "Redirecting: ${1} port ${2} to ${3} on ${interface}" } while [ $# -gt 0 ]; do # Check if interface was specified, and use it instead of default if ifconfig | grep -wo "${1}"; then IF_NAME="${1}" - EXT_IF=ext_if="${1}" + EXT_IF=ext_if=\"${1}\" shift fi case "$1" in From 622d84b6be69f6f505ca31ab708e262da425f30a Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 10 Dec 2024 18:45:06 -0700 Subject: [PATCH 07/76] allow specifying IP to redirect traffic to This is for the folks who have multiple IP addresses on a single interface. --- usr/local/share/bastille/rdr.sh | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 24733628..666d0666 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -99,8 +99,8 @@ check_jail_validity() { # function: write rule to rdr.conf persist_rdr_rule() { -if ! grep -qs "$IF_NAME $1 $2 $3" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then - echo "$IF_NAME $1 $2 $3" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" +if ! grep -qs "$IF_NAME $RDR_DST $1 $2 $3" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then + echo "$IF_NAME $RDR_DST $1 $2 $3" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" fi } @@ -108,25 +108,28 @@ persist_rdr_log_rule() { proto=$1;host_port=$2;jail_port=$3; shift 3; log=$@; -if ! grep -qs "$IF_NAME $proto $host_port $jail_port $log" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then - echo "$IF_NAME $proto $host_port $jail_port $log" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" +if ! grep -qs "$IF_NAME $RDR_DST $proto $host_port $jail_port $log" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then + echo "$IF_NAME $RDR_DST $proto $host_port $jail_port $log" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" fi } - # function: load rdr rule via pfctl load_rdr_rule() { ( pfctl -a "rdr/${JAIL_NAME}" -Psn; - printf '%s\nrdr pass on $%s inet proto %s to port %s -> %s port %s\n' "$EXT_IF" "${bastille_network_pf_ext_if}" "$1" "$2" "$JAIL_IP" "$3" ) \ + printf '%s\nrdr pass on $%s inet proto %s from any to %s port %s -> %s port %s\n' "$EXT_IF" "${bastille_network_pf_ext_if}" "$1" "$RDR_DST" "$2" "$JAIL_IP" "$3" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f- if [ -n "$JAIL_IP6" ]; then ( pfctl -a "rdr/${JAIL_NAME}" -Psn; - printf '%s\nrdr pass on $%s inet proto %s to port %s -> %s port %s\n' "$EXT_IF" "${bastille_network_pf_ext_if}" "$1" "$2" "$JAIL_IP6" "$3" ) \ + printf '%s\nrdr pass on $%s inet proto %s from any to %s port %s -> %s port %s\n' "$EXT_IF" "${bastille_network_pf_ext_if}" "$1" "$RDR_DST" "$2" "$JAIL_IP6" "$3" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f- fi local interface="$( echo $EXT_IF | awk -F'"' '{print $2}')" info "[${JAIL_NAME}]:" -info "Redirecting: ${1} port ${2} to ${3} on ${interface}" +if [ "${RDR_DST}" != "any" ]; then + info "Redirecting: ${1} port ${2} to ${3} on ${interface}:${RDR_DST}" +else + info "Redirecting: ${1} port ${2} to ${3} on ${interface}" +fi } # function: load rdr rule with log via pfctl @@ -149,11 +152,19 @@ info "Redirecting: ${1} port ${2} to ${3} on ${interface}" while [ $# -gt 0 ]; do # Check if interface was specified, and use it instead of default + # Set default RDR rule to "any to any" + RDR_DST="any" if ifconfig | grep -wo "${1}"; then - IF_NAME="${1}" - EXT_IF=ext_if=\"${1}\" + IF_NAME="${1}" + EXT_IF=ext_if=\"${1}\" + shift + # Check if IP was specified for given interface + if ifconfig | grep -o "inet ${1}"; then + RDR_DST="${1}" shift + fi fi + case "$1" in list) if [ "${TARGET}" = 'ALL' ]; then From 471a91ca248bc91af85fab4fd59548f3e215c54d Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 10 Dec 2024 18:46:36 -0700 Subject: [PATCH 08/76] print IP in addition to interface when listing RDR --- usr/local/share/bastille/list.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/list.sh b/usr/local/share/bastille/list.sh index 211f2f99..e7d09e2c 100644 --- a/usr/local/share/bastille/list.sh +++ b/usr/local/share/bastille/list.sh @@ -108,7 +108,7 @@ list_all(){ if [ "${JAIL_IP}" = "-" ]; then JAIL_IP=$(/usr/sbin/jls -j ${JAIL_NAME} ip6.addr 2> /dev/null); fi fi JAIL_HOSTNAME=$(/usr/sbin/jls -j ${JAIL_NAME} host.hostname 2> /dev/null) - JAIL_PORTS=$(pfctl -a "rdr/${JAIL_NAME}" -Psn 2> /dev/null | awk '{ printf "%s %s/%s:%s"",",$4,$7,$14,$18 }' | sed "s/,$//") + JAIL_PORTS=$(pfctl -a "rdr/${JAIL_NAME}" -Psn 2> /dev/null | awk '{ printf "%s:%s %s/%s:%s"",",$4,$11,$7,$14,$18 }' | sed "s/,$//") JAIL_PATH=$(/usr/sbin/jls -j ${JAIL_NAME} path 2> /dev/null) if [ "${IS_FREEBSD_JAIL}" -eq 1 ]; then JAIL_RELEASE=$(jexec -l ${JAIL_NAME} freebsd-version -u 2> /dev/null) From 035855bf018d8e1b4eb4b3153d6bd2ea43ab06f1 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 10:57:07 -0700 Subject: [PATCH 09/76] major rewrite to allow setting TO+FROM --- usr/local/share/bastille/rdr.sh | 131 ++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 42 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 666d0666..3028ac03 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -53,6 +53,9 @@ JAIL_NAME="" JAIL_IP="" JAIL_IP6="" EXT_IF="" +RDR_IF="" +RDR_SRC="" +RDR_DST="" shift check_jail_validity() { @@ -99,71 +102,108 @@ check_jail_validity() { # function: write rule to rdr.conf persist_rdr_rule() { -if ! grep -qs "$IF_NAME $RDR_DST $1 $2 $3" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then - echo "$IF_NAME $RDR_DST $1 $2 $3" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" + local if="${1}" + local src="${2}" + local dst="${3}" + local proto="${4}" + local host_port="${5}" + local jail_port="${6}" +if ! grep -qs "$if $src $dst $proto $host_port $jail_port" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then + echo "$if $src $dst $proto $host_port $jail_port" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" fi } persist_rdr_log_rule() { -proto=$1;host_port=$2;jail_port=$3; -shift 3; + local if="${1}" + local src="${2}" + local dst="${3}" + local proto="${4}" + local host_port="${5}" + local jail_port="${6}" +shift 6; log=$@; -if ! grep -qs "$IF_NAME $RDR_DST $proto $host_port $jail_port $log" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then - echo "$IF_NAME $RDR_DST $proto $host_port $jail_port $log" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" +if ! grep -qs "$if $src $dst $proto $host_port $jail_port $log" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then + echo "$if $src $dst $proto $host_port $jail_port $log" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" fi } # function: load rdr rule via pfctl load_rdr_rule() { -( pfctl -a "rdr/${JAIL_NAME}" -Psn; - printf '%s\nrdr pass on $%s inet proto %s from any to %s port %s -> %s port %s\n' "$EXT_IF" "${bastille_network_pf_ext_if}" "$1" "$RDR_DST" "$2" "$JAIL_IP" "$3" ) \ + local if=ext_if=\"${1}\" + local src="${2}" + local dst="${3}" + local proto="${4}" + local host_port="${5}" + local jail_port="${6}" +( pfctl -a "rdr/${JAIL_NAME}" -Psn 2>/dev/null; + printf '%s\nrdr pass on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f- if [ -n "$JAIL_IP6" ]; then - ( pfctl -a "rdr/${JAIL_NAME}" -Psn; - printf '%s\nrdr pass on $%s inet proto %s from any to %s port %s -> %s port %s\n' "$EXT_IF" "${bastille_network_pf_ext_if}" "$1" "$RDR_DST" "$2" "$JAIL_IP6" "$3" ) \ +( pfctl -a "rdr/${JAIL_NAME}" -Psn; + printf '%s\nrdr pass on $%s inet proto %s to port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f- fi -local interface="$( echo $EXT_IF | awk -F'"' '{print $2}')" info "[${JAIL_NAME}]:" -if [ "${RDR_DST}" != "any" ]; then - info "Redirecting: ${1} port ${2} to ${3} on ${interface}:${RDR_DST}" -else - info "Redirecting: ${1} port ${2} to ${3} on ${interface}" -fi +info "Redirecting:" +info "${src}:${host_port} -> ${dst}:${jail_port} on ${1}" } # function: load rdr rule with log via pfctl load_rdr_log_rule() { -proto=$1;host_port=$2;jail_port=$3; -shift 3; + local if=ext_if=\"${1}\" + local src="${2}" + local dst="${3}" + local proto="${4}" + local host_port="${5}" + local jail_port="${6}" +shift 6; log=$@ ( pfctl -a "rdr/${JAIL_NAME}" -Psn; - printf '%s\nrdr pass %s on $%s inet proto %s to port %s -> %s port %s\n' "$EXT_IF" "$log" "${bastille_network_pf_ext_if}" "$proto" "$host_port" "$JAIL_IP" "$jail_port" ) \ + printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f- if [ -n "$JAIL_IP6" ]; then ( pfctl -a "rdr/${JAIL_NAME}" -Psn; - printf '%s\nrdr pass %s on $%s inet proto %s to port %s -> %s port %s\n' "$EXT_IF" "$log" "${bastille_network_pf_ext_if}" "$proto" "$host_port" "$JAIL_IP6" "$jail_port" ) \ + printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f- fi -local interface="$( echo $EXT_IF | awk -F'"' '{print $2}')" info "[${JAIL_NAME}]:" -info "Redirecting: ${1} port ${2} to ${3} on ${interface}" +info "Redirecting:" +info "${src}:${host_port} -> ${dst}:${jail_port} on ${1}" } + while [ $# -gt 0 ]; do - # Check if interface was specified, and use it instead of default - # Set default RDR rule to "any to any" + while getopts "i:s:d:" opt; do + case $opt in + i) if ifconfig | grep -ow "${OPTARG}:"; then + RDR_IF="${OPTARG}" + else + error_exit "$OPTARG is not a valid interface on this system." + fi + ;; + s) RDR_SRC="$OPTARG" + ;; + d) if ifconfig | grep -ow "inet ${OPTARG}"; then + RDR_DST="$OPTARG" + else + error_exit "$OPTARG is not an IP on this system." + fi + ;; + *) usage ;; + esac + done + shift $((OPTIND - 1)) + + # Set default interface, source, and destination if not set by options + if [ -z $RDR_IF ]; then + RDR_IF="$(grep "^[[:space:]]*${bastille_network_pf_ext_if}[[:space:]]*=" ${bastille_pf_conf} | awk -F'"' '{print $2}')" + fi + if [ -z $RDR_SRC ]; then + RDR_SRC="any" + fi + if [ -z $RDR_DST ]; then RDR_DST="any" - if ifconfig | grep -wo "${1}"; then - IF_NAME="${1}" - EXT_IF=ext_if=\"${1}\" - shift - # Check if IP was specified for given interface - if ifconfig | grep -o "inet ${1}"; then - RDR_DST="${1}" - shift - fi - fi + fi case "$1" in list) @@ -195,9 +235,9 @@ while [ $# -gt 0 ]; do usage elif [ $# -eq 3 ]; then check_jail_validity - persist_rdr_rule $1 $2 $3 - load_rdr_rule $1 $2 $3 - shift 3 + persist_rdr_rule $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 + load_rdr_rule $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 + shift "$#" else case "$4" in log) @@ -211,16 +251,16 @@ while [ $# -gt 0 ]; do done if [ $2 == "(" ] && [ $last == ")" ] ; then check_jail_validity - persist_rdr_log_rule $proto $host_port $jail_port "$@" - load_rdr_log_rule $proto $host_port $jail_port "$@" + persist_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" + load_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" shift $# else usage fi elif [ $# -eq 1 ]; then check_jail_validity - persist_rdr_log_rule $proto $host_port $jail_port "$@" - load_rdr_log_rule $proto $host_port $jail_port "$@" + persist_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" + load_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" shift 1 else usage @@ -233,7 +273,14 @@ while [ $# -gt 0 ]; do fi ;; *) - usage + if [ $# -gt 5 ]; then + check_jail_validity + persist_rdr_rule "$@" + load_rdr_rule "$@" + shift $# + else + usage + fi ;; esac done From d21b5166d76164e797ad3c61addbc1f3c30cdde5 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:05:47 -0700 Subject: [PATCH 10/76] add usage command with new switches --- usr/local/share/bastille/rdr.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 3028ac03..0304af4d 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -32,7 +32,17 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_exit "Usage: bastille rdr TARGET [clear|list|(tcp|udp host_port jail_port [log ['(' logopts ')'] ] )]" + error_notify "Usage: bastille rdr TARGET [options(s)] [clear|list|(tcp|udp host_port jail_port [log ['(' logopts ')'] ] )]" + + cat << EOF + Options: + + -i [interface] | -- Set the interface to create the rdr rule on. Useful if you have multiple interfaces. + -s [source ip] | -- Limit rdr to a source IP. Useful to only allow access from a certian IP or subnet. + -d [destination ip ] | -- Limit rdr to a destination IP. Useful if you have multiple IPs on one interface. + +EOF + exit 1 } # Handle special-case commands first. From f627aadac2105b702a44eb9ee4221111f45fbe28 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:06:16 -0700 Subject: [PATCH 11/76] spacing --- usr/local/share/bastille/rdr.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 0304af4d..c3d81196 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -37,9 +37,9 @@ usage() { cat << EOF Options: - -i [interface] | -- Set the interface to create the rdr rule on. Useful if you have multiple interfaces. - -s [source ip] | -- Limit rdr to a source IP. Useful to only allow access from a certian IP or subnet. - -d [destination ip ] | -- Limit rdr to a destination IP. Useful if you have multiple IPs on one interface. + -i [interface] | -- Set the interface to create the rdr rule on. Useful if you have multiple interfaces. + -s [source ip] | -- Limit rdr to a source IP. Useful to only allow access from a certian IP or subnet. + -d [destination ip] | -- Limit rdr to a destination IP. Useful if you have multiple IPs on one interface. EOF exit 1 From 7f1be3d480fb9fa843937fb0de478b12e78c5ce4 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:06:33 -0700 Subject: [PATCH 12/76] more spacing --- usr/local/share/bastille/rdr.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index c3d81196..f2a2c118 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -37,8 +37,8 @@ usage() { cat << EOF Options: - -i [interface] | -- Set the interface to create the rdr rule on. Useful if you have multiple interfaces. - -s [source ip] | -- Limit rdr to a source IP. Useful to only allow access from a certian IP or subnet. + -i [interface] | -- Set the interface to create the rdr rule on. Useful if you have multiple interfaces. + -s [source ip] | -- Limit rdr to a source IP. Useful to only allow access from a certian IP or subnet. -d [destination ip] | -- Limit rdr to a destination IP. Useful if you have multiple IPs on one interface. EOF From 2cff4048d18abfdef7fa8a15d75aa6d5510471b9 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:35:14 -0700 Subject: [PATCH 13/76] document new changes to rdr --- docs/chapters/subcommands/rdr.rst | 61 +++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index 8a6e2fd0..0b86c640 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -14,27 +14,64 @@ specify the interface they run on in rc.conf (or other config files) .. code-block:: shell # bastille rdr --help - Usage: bastille rdr TARGET [clear] | [list] | [ tcp ] | [ udp ] + Usage: bastille rdr TARGET [options(s)] [clear|list|(tcp|udp host_port jail_port [log ['(' logopts ')'] ] )] + Options: + + -i [interface] | -- Set the interface to create the rdr rule on. Useful if you have multiple interfaces. + -s [source ip] | -- Limit rdr to a source IP. Useful to only allow access from a certian IP or subnet. + -d [destination ip] | -- Limit rdr to a destination IP. Useful if you have multiple IPs on one interface. + # bastille rdr dev1 tcp 2001 22 + [jail1]: + Redirecting: + tcp any:2001 -> any:22 on em0 + # bastille rdr dev1 list rdr on em0 inet proto tcp from any to any port = 2001 -> 10.17.89.1 port 22 + # bastille rdr dev1 udp 2053 53 + [jail1]: + Redirecting: + udp any:2001 -> any:22 on em0 + # bastille rdr dev1 list - rdr on em0 inet proto tcp from any to any port = 2001 -> 10.17.89.1 port 22 - rdr on em0 inet proto udp from any to any port = 2053 -> 10.17.89.1 port 53 + rdr pass on em0 inet proto tcp from any to any port = 2001 -> 10.17.89.1 port 22 + rdr pass on em0 inet proto udp from any to any port = 2053 -> 10.17.89.1 port 53 + # bastille rdr dev1 clear nat cleared -If you have a host with multiple interfaces, and you want to specify which -one to use, `bastille rdr` allows you to pass any interface to the command. -If you do not specify an interface, the default one will be used. +Bastille included 3 options for the three following scenarios. +- Setting a non-default interface on which to create the rdr rule. +- Limiting the source IP on the rdr rule. +- Limiting the destination IP on the rdr rule. .. code-block:: shell - # bastille rdr em0 dev1 tcp 2001 22 - # bastille rdr dev1 list - rdr on em0 inet proto tcp from any to any port = 2001 -> 10.17.89.1 port 22 - # bastille rdr dev1 vtnet0 udp 2053 53 + # bastille rdr dev1 -i vtnet0 udp 2001 22 + [jail1]: + Redirecting: + tcp any:8000 -> any:80 on vtnet0 + + # bastille rdr dev1 -s 192.168.0.1 tcp 8080 81 + [jail1]: + Redirecting: + tcp 192.168.0.1:8080 -> any:81 on em0 + + # bastille rdr dev1 -d 192.168.0.84 tcp 8082 82 + [jail1]: + Redirecting: + tcp any:8082 -> 192.168.0.84:82 on em0 + + # bastille rdr dev1 -i vtnet0 -d 192.168.0.45 tcp 9000 9000 + [jail1]: + Redirecting: + tcp any:9000 -> 192.168.0.45:9000 on vtnet0 + # bastille rdr dev1 list - rdr on em0 inet proto tcp from any to any port = 2001 -> 10.17.89.1 port 22 - rdr on vtnet0 inet proto udp from any to any port = 2053 -> 10.17.89.1 port 53 + rdr pass on vtnet0 inet proto udp from any to any port = 2001 -> 10.17.89.1 port 22 + rdr pass on em0 inet proto tcp from 192.168.0.1 to any port = 8080 -> 10.17.89.1 port 81 + rdr pass on em0 inet proto tcp from any to 192.168.0.84 port = 8082 -> 10.17.89.1 port 82 + rdr pass on vtnet0 inet proto tcp from any to 192.168.0.45 port = 9000 -> 10.17.89.1 port 9000 + +The options can be used together, as seen above. From 4b5655470a663df9d62f2bb9568ae4f3640d9c2b Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:36:10 -0700 Subject: [PATCH 14/76] add protocol to printed info --- usr/local/share/bastille/rdr.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index f2a2c118..92733ada 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -155,7 +155,7 @@ if [ -n "$JAIL_IP6" ]; then fi info "[${JAIL_NAME}]:" info "Redirecting:" -info "${src}:${host_port} -> ${dst}:${jail_port} on ${1}" +info "${proto} ${src}:${host_port} -> ${dst}:${jail_port} on ${1}" } # function: load rdr rule with log via pfctl @@ -178,7 +178,7 @@ if [ -n "$JAIL_IP6" ]; then fi info "[${JAIL_NAME}]:" info "Redirecting:" -info "${src}:${host_port} -> ${dst}:${jail_port} on ${1}" +info "${proto} ${src}:${host_port} -> ${dst}:${jail_port} on ${1}" } From 5b7b848b12599ff617b845d30dbc01b52601bd80 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:37:16 -0700 Subject: [PATCH 15/76] revert listing of IP and interface --- usr/local/share/bastille/list.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/list.sh b/usr/local/share/bastille/list.sh index e7d09e2c..ebb28cc4 100644 --- a/usr/local/share/bastille/list.sh +++ b/usr/local/share/bastille/list.sh @@ -108,7 +108,7 @@ list_all(){ if [ "${JAIL_IP}" = "-" ]; then JAIL_IP=$(/usr/sbin/jls -j ${JAIL_NAME} ip6.addr 2> /dev/null); fi fi JAIL_HOSTNAME=$(/usr/sbin/jls -j ${JAIL_NAME} host.hostname 2> /dev/null) - JAIL_PORTS=$(pfctl -a "rdr/${JAIL_NAME}" -Psn 2> /dev/null | awk '{ printf "%s:%s %s/%s:%s"",",$4,$11,$7,$14,$18 }' | sed "s/,$//") + JAIL_PORTS=$(pfctl -a "rdr/${JAIL_NAME}" -Psn 2> /dev/null | awk '{ printf "%s/%s:%s"",",$7,$14,$18 }' | sed "s/,$//") JAIL_PATH=$(/usr/sbin/jls -j ${JAIL_NAME} path 2> /dev/null) if [ "${IS_FREEBSD_JAIL}" -eq 1 ]; then JAIL_RELEASE=$(jexec -l ${JAIL_NAME} freebsd-version -u 2> /dev/null) From 9ce301b7323cc12e721666300b3146e6b4951bd3 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:38:53 -0700 Subject: [PATCH 16/76] spacing --- docs/chapters/subcommands/rdr.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index 0b86c640..d87147ad 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -41,10 +41,11 @@ specify the interface they run on in rc.conf (or other config files) # bastille rdr dev1 clear nat cleared -Bastille included 3 options for the three following scenarios. -- Setting a non-default interface on which to create the rdr rule. -- Limiting the source IP on the rdr rule. -- Limiting the destination IP on the rdr rule. +Bastille includes 3 options for the three following scenarios. + + - Setting a non-default interface on which to create the rdr rule. + - Limiting the source IP on the rdr rule. + - Limiting the destination IP on the rdr rule. .. code-block:: shell From ac8d71bb94b1627f6bd7684633ec99c0a0b27f46 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:40:33 -0700 Subject: [PATCH 17/76] Update rdr.rst --- docs/chapters/subcommands/rdr.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index d87147ad..463b0a26 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -41,11 +41,11 @@ specify the interface they run on in rc.conf (or other config files) # bastille rdr dev1 clear nat cleared -Bastille includes 3 options for the three following scenarios. +`bastille rdr` includes 3 options. - - Setting a non-default interface on which to create the rdr rule. - - Limiting the source IP on the rdr rule. - - Limiting the destination IP on the rdr rule. +-i - Set a non-default interface on which to create the rdr rule. +-s - Limit the source IP on the rdr rule. +-d - Limit the destination IP on the rdr rule. .. code-block:: shell From 02e76f5d5f92c6347e8131720348d35a9c065132 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:40:56 -0700 Subject: [PATCH 18/76] Update rdr.rst --- docs/chapters/subcommands/rdr.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index 463b0a26..85224192 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -43,9 +43,9 @@ specify the interface they run on in rc.conf (or other config files) `bastille rdr` includes 3 options. --i - Set a non-default interface on which to create the rdr rule. --s - Limit the source IP on the rdr rule. --d - Limit the destination IP on the rdr rule. + -i - Set a non-default interface on which to create the rdr rule. + -s - Limit the source IP on the rdr rule. + -d - Limit the destination IP on the rdr rule. .. code-block:: shell From 356840a065a5243e6df259109d8be1873782c3a6 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:41:19 -0700 Subject: [PATCH 19/76] Update rdr.rst --- docs/chapters/subcommands/rdr.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index 85224192..96aa6dcd 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -43,9 +43,11 @@ specify the interface they run on in rc.conf (or other config files) `bastille rdr` includes 3 options. - -i - Set a non-default interface on which to create the rdr rule. - -s - Limit the source IP on the rdr rule. - -d - Limit the destination IP on the rdr rule. +-i - Set a non-default interface on which to create the rdr rule. + +-s - Limit the source IP on the rdr rule. + +-d - Limit the destination IP on the rdr rule. .. code-block:: shell From a52b53d6561f21082e96ed9c657c01f044e43cfd Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:43:08 -0700 Subject: [PATCH 20/76] spacing --- docs/chapters/subcommands/rdr.rst | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index 96aa6dcd..e22196f1 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -2,7 +2,7 @@ rdr === -`bastille rdr` allows you to configure dynamic rdr rules for your containers +bastille rdr allows you to configure dynamic rdr rules for your containers without modifying pf.conf (assuming you are using the `bastille0` interface for a private network and have enabled `rdr-anchor 'rdr/*'` in /etc/pf.conf as described in the Networking section). @@ -41,13 +41,11 @@ specify the interface they run on in rc.conf (or other config files) # bastille rdr dev1 clear nat cleared -`bastille rdr` includes 3 options. +The rdr command includes 3 additional options. --i - Set a non-default interface on which to create the rdr rule. - --s - Limit the source IP on the rdr rule. - --d - Limit the destination IP on the rdr rule. + -i | - Set a non-default interface on which to create the rdr rule. + -s | - Limit the source IP on the rdr rule. + -d | - Limit the destination IP on the rdr rule. .. code-block:: shell From e5acf6f10385596a9c495e7827c80fe204f0c492 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:09:09 -0700 Subject: [PATCH 21/76] spacing --- docs/chapters/subcommands/rdr.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index e22196f1..fda13d0e 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -41,11 +41,11 @@ specify the interface they run on in rc.conf (or other config files) # bastille rdr dev1 clear nat cleared -The rdr command includes 3 additional options. +The `rdr` command includes 3 additional options: - -i | - Set a non-default interface on which to create the rdr rule. - -s | - Limit the source IP on the rdr rule. - -d | - Limit the destination IP on the rdr rule. +- **-i** | Set a non-default interface on which to create the `rdr` rule. +- **-s** | Limit the source IP on the `rdr` rule. +- **-d** | Limit the destination IP on the `rdr` rule. .. code-block:: shell From 8f3ad2f97271fc7c83f841e0171d5e83fdb0a911 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:13:05 -0700 Subject: [PATCH 22/76] change to -ge 6 --- usr/local/share/bastille/rdr.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 92733ada..a8bdb479 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -283,7 +283,7 @@ while [ $# -gt 0 ]; do fi ;; *) - if [ $# -gt 5 ]; then + if [ $# -ge 6 ]; then check_jail_validity persist_rdr_rule "$@" load_rdr_rule "$@" From 74eab248ca9401c473395cf6c393cb711481273e Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:56:31 -0700 Subject: [PATCH 23/76] add error notify to pfctl commands/add better info commands --- usr/local/share/bastille/rdr.sh | 67 ++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index a8bdb479..f06cdab5 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -62,7 +62,6 @@ TARGET="${1}" JAIL_NAME="" JAIL_IP="" JAIL_IP6="" -EXT_IF="" RDR_IF="" RDR_SRC="" RDR_DST="" @@ -98,16 +97,6 @@ check_jail_validity() { if ! (pfctl -sn | grep rdr-anchor | grep 'rdr/\*' >/dev/null); then error_exit "rdr-anchor not found in pf.conf" fi - - # Check if ext_if is defined in pf.conf - # If EXT_IF is set, use it instead of the default - if [ -n "${bastille_pf_conf}" ]; then - if [ -z "${EXT_IF}" ]; then - EXT_IF=$(grep "^[[:space:]]*${bastille_network_pf_ext_if}[[:space:]]*=" ${bastille_pf_conf}) - else - error_exit "bastille_network_pf_ext_if (${bastille_network_pf_ext_if}) not defined in pf.conf" - fi - fi } # function: write rule to rdr.conf @@ -139,27 +128,40 @@ fi # function: load rdr rule via pfctl load_rdr_rule() { + local if_name="${1}" local if=ext_if=\"${1}\" local src="${2}" local dst="${3}" local proto="${4}" local host_port="${5}" local jail_port="${6}" -( pfctl -a "rdr/${JAIL_NAME}" -Psn 2>/dev/null; +# Create IPv4 rdr rule +if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn 2>/dev/null; printf '%s\nrdr pass on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ - | pfctl -a "rdr/${JAIL_NAME}" -f- + | pfctl -a "rdr/${JAIL_NAME}" -f-; then + error_notify "Failed to create IPv4 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" +else + info "[${JAIL_NAME}]:" + info "Redirecting IPv4:" + info "${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" +fi +# Create IPv6 rdr rule (if ip6.addr is enabled) if [ -n "$JAIL_IP6" ]; then -( pfctl -a "rdr/${JAIL_NAME}" -Psn; - printf '%s\nrdr pass on $%s inet proto %s to port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ - | pfctl -a "rdr/${JAIL_NAME}" -f- + if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; + printf '%s\nrdr pass on $%s inet proto %s to port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ + | pfctl -a "rdr/${JAIL_NAME}" -f-; then + error_notify "Failed to create IPv6 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + else + info "[${JAIL_NAME}]:" + info "Redirecting IPv6:" + info "${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + fi fi -info "[${JAIL_NAME}]:" -info "Redirecting:" -info "${proto} ${src}:${host_port} -> ${dst}:${jail_port} on ${1}" } # function: load rdr rule with log via pfctl load_rdr_log_rule() { + local if_name="${1}" local if=ext_if=\"${1}\" local src="${2}" local dst="${3}" @@ -168,17 +170,28 @@ load_rdr_log_rule() { local jail_port="${6}" shift 6; log=$@ -( pfctl -a "rdr/${JAIL_NAME}" -Psn; +# Create IPv4 rule with log +if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ - | pfctl -a "rdr/${JAIL_NAME}" -f- + | pfctl -a "rdr/${JAIL_NAME}" -f-; then + error_notify "Failed to create logged IPv4 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" +else + info "[${JAIL_NAME}]:" + info "Redirecting logged IPv4:" + info "${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" +fi +# Create IPv6 rdr rule with log (if ip6.addr is enabled) if [ -n "$JAIL_IP6" ]; then - ( pfctl -a "rdr/${JAIL_NAME}" -Psn; - printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ - | pfctl -a "rdr/${JAIL_NAME}" -f- + if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; + printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ + | pfctl -a "rdr/${JAIL_NAME}" -f-; then + error_notify "Failed to create logged IPv6 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + else + info "[${JAIL_NAME}]:" + info "Redirecting logged IPv6:" + info "${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + fi fi -info "[${JAIL_NAME}]:" -info "Redirecting:" -info "${proto} ${src}:${host_port} -> ${dst}:${jail_port} on ${1}" } From 53b47306f53b3241fdb9ec3abb12e3196a1d3a82 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 16:10:11 -0700 Subject: [PATCH 24/76] better error handling --- usr/local/share/bastille/rdr.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index f06cdab5..1a625cf7 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -174,7 +174,7 @@ log=$@ if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f-; then - error_notify "Failed to create logged IPv4 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + error_notify "Failed to create logged IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${JAIL_NAME}]:" info "Redirecting logged IPv4:" @@ -185,7 +185,7 @@ if [ -n "$JAIL_IP6" ]; then if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f-; then - error_notify "Failed to create logged IPv6 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + error_notify "Failed to create logged IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${JAIL_NAME}]:" info "Redirecting logged IPv6:" @@ -296,11 +296,16 @@ while [ $# -gt 0 ]; do fi ;; *) - if [ $# -ge 6 ]; then + if [ $# -eq 6 ]; then check_jail_validity persist_rdr_rule "$@" load_rdr_rule "$@" shift $# + elif [ $# -ge 7 ] && [ "${7}" = "log" ]; then + check_jail_validity + persist_rdr_log_rule "$@" + load_rdr_log_rule "$@" + shift $# else usage fi From 4984f684e112fe43774f70181b8c98d855e67dd7 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 16:40:21 -0700 Subject: [PATCH 25/76] Update docs --- docs/chapters/subcommands/rdr.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index fda13d0e..e922701b 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -23,7 +23,7 @@ specify the interface they run on in rc.conf (or other config files) # bastille rdr dev1 tcp 2001 22 [jail1]: - Redirecting: + Redirecting IPv4: tcp any:2001 -> any:22 on em0 # bastille rdr dev1 list @@ -51,22 +51,22 @@ The `rdr` command includes 3 additional options: # bastille rdr dev1 -i vtnet0 udp 2001 22 [jail1]: - Redirecting: + Redirecting IPv4: tcp any:8000 -> any:80 on vtnet0 # bastille rdr dev1 -s 192.168.0.1 tcp 8080 81 [jail1]: - Redirecting: + Redirecting IPv4: tcp 192.168.0.1:8080 -> any:81 on em0 # bastille rdr dev1 -d 192.168.0.84 tcp 8082 82 [jail1]: - Redirecting: + Redirecting IPv4: tcp any:8082 -> 192.168.0.84:82 on em0 # bastille rdr dev1 -i vtnet0 -d 192.168.0.45 tcp 9000 9000 [jail1]: - Redirecting: + Redirecting IPv4: tcp any:9000 -> 192.168.0.45:9000 on vtnet0 # bastille rdr dev1 list From 6945781e15fa708be522bc7314a2c0c0da9738b5 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 16:41:18 -0700 Subject: [PATCH 26/76] Add / --- docs/chapters/subcommands/rdr.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index e922701b..9febbd24 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -24,7 +24,7 @@ specify the interface they run on in rc.conf (or other config files) # bastille rdr dev1 tcp 2001 22 [jail1]: Redirecting IPv4: - tcp any:2001 -> any:22 on em0 + tcp/any:2001 -> any:22 on em0 # bastille rdr dev1 list rdr on em0 inet proto tcp from any to any port = 2001 -> 10.17.89.1 port 22 @@ -32,7 +32,7 @@ specify the interface they run on in rc.conf (or other config files) # bastille rdr dev1 udp 2053 53 [jail1]: Redirecting: - udp any:2001 -> any:22 on em0 + udp/any:2001 -> any:22 on em0 # bastille rdr dev1 list rdr pass on em0 inet proto tcp from any to any port = 2001 -> 10.17.89.1 port 22 @@ -52,22 +52,22 @@ The `rdr` command includes 3 additional options: # bastille rdr dev1 -i vtnet0 udp 2001 22 [jail1]: Redirecting IPv4: - tcp any:8000 -> any:80 on vtnet0 + tcp/any:8000 -> any:80 on vtnet0 # bastille rdr dev1 -s 192.168.0.1 tcp 8080 81 [jail1]: Redirecting IPv4: - tcp 192.168.0.1:8080 -> any:81 on em0 + tcp/192.168.0.1:8080 -> any:81 on em0 # bastille rdr dev1 -d 192.168.0.84 tcp 8082 82 [jail1]: Redirecting IPv4: - tcp any:8082 -> 192.168.0.84:82 on em0 + tcp/any:8082 -> 192.168.0.84:82 on em0 # bastille rdr dev1 -i vtnet0 -d 192.168.0.45 tcp 9000 9000 [jail1]: Redirecting IPv4: - tcp any:9000 -> 192.168.0.45:9000 on vtnet0 + tcp/any:9000 -> 192.168.0.45:9000 on vtnet0 # bastille rdr dev1 list rdr pass on vtnet0 inet proto udp from any to any port = 2001 -> 10.17.89.1 port 22 From 492b64b302bdeee410b832fafe8bea7f202fa221 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 11 Dec 2024 18:28:10 -0700 Subject: [PATCH 27/76] fix help usage command --- usr/local/share/bastille/rdr.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 1a625cf7..f6e9f4d5 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -32,7 +32,7 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_notify "Usage: bastille rdr TARGET [options(s)] [clear|list|(tcp|udp host_port jail_port [log ['(' logopts ')'] ] )]" + error_notify "Usage: bastille rdr TARGET [options(s)] [clear|list|(tcp|udp)] host_port jail_port [log ['(' logopts ')'] ] )]" cat << EOF Options: From 449a0ae8e182f7ac97b6805fc241a62ce474a081 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 12 Dec 2024 07:41:23 -0700 Subject: [PATCH 28/76] add check when setting source IP + supress echo output --- usr/local/share/bastille/rdr.sh | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index f6e9f4d5..ad158f8d 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -99,6 +99,29 @@ check_jail_validity() { fi } +check_rdr_ip_validity() { + local ip="$1" + local ip6=$(echo "${ip}" | grep -E '^(([a-fA-F0-9:]+$)|([a-fA-F0-9:]+\/[0-9]{1,3}$)|SLAAC)') + if [ -n "${ip6}" ]; then + info "Valid: (${ip6})." + else + local IFS + if echo "${ip}" | grep -Eq '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))?$'; then + TEST_IP=$(echo "${ip}" | cut -d / -f1) + IFS=. + set ${TEST_IP} + for quad in 1 2 3 4; do + if eval [ \$$quad -gt 255 ]; then + error_exit "Invalid: (${TEST_IP})" + fi + done + info "Valid: (${ip})." + else + error_exit "Invalid: (${ip})." + fi + fi +} + # function: write rule to rdr.conf persist_rdr_rule() { local if="${1}" @@ -198,15 +221,16 @@ fi while [ $# -gt 0 ]; do while getopts "i:s:d:" opt; do case $opt in - i) if ifconfig | grep -ow "${OPTARG}:"; then + i) if ifconfig | grep -owq "${OPTARG}:"; then RDR_IF="${OPTARG}" else error_exit "$OPTARG is not a valid interface on this system." fi ;; - s) RDR_SRC="$OPTARG" + s) check_rdr_ip_validity "${OPTARG}" + RDR_SRC="$OPTARG" ;; - d) if ifconfig | grep -ow "inet ${OPTARG}"; then + d) if ifconfig | grep -owq "inet ${OPTARG}"; then RDR_DST="$OPTARG" else error_exit "$OPTARG is not an IP on this system." From 606d8da0def35d0c33554ab068e8fc9fccc6f7fc Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:55:56 -0700 Subject: [PATCH 29/76] only persist rdr rule if it can be properly loaded, else exit --- usr/local/share/bastille/rdr.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index ad158f8d..cd8c180c 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -162,7 +162,7 @@ load_rdr_rule() { if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn 2>/dev/null; printf '%s\nrdr pass on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f-; then - error_notify "Failed to create IPv4 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + error_exit "Failed to create IPv4 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${JAIL_NAME}]:" info "Redirecting IPv4:" @@ -173,7 +173,7 @@ if [ -n "$JAIL_IP6" ]; then if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; printf '%s\nrdr pass on $%s inet proto %s to port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f-; then - error_notify "Failed to create IPv6 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + error_exit "Failed to create IPv6 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${JAIL_NAME}]:" info "Redirecting IPv6:" @@ -197,7 +197,7 @@ log=$@ if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f-; then - error_notify "Failed to create logged IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + error_exit "Failed to create logged IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${JAIL_NAME}]:" info "Redirecting logged IPv4:" @@ -208,7 +208,7 @@ if [ -n "$JAIL_IP6" ]; then if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f-; then - error_notify "Failed to create logged IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + error_exit "Failed to create logged IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${JAIL_NAME}]:" info "Redirecting logged IPv6:" @@ -282,8 +282,8 @@ while [ $# -gt 0 ]; do usage elif [ $# -eq 3 ]; then check_jail_validity - persist_rdr_rule $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 load_rdr_rule $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 + persist_rdr_rule $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 shift "$#" else case "$4" in @@ -298,16 +298,16 @@ while [ $# -gt 0 ]; do done if [ $2 == "(" ] && [ $last == ")" ] ; then check_jail_validity - persist_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" load_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" + persist_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" shift $# else usage fi elif [ $# -eq 1 ]; then check_jail_validity - persist_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" load_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" + persist_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" shift 1 else usage @@ -322,13 +322,13 @@ while [ $# -gt 0 ]; do *) if [ $# -eq 6 ]; then check_jail_validity - persist_rdr_rule "$@" load_rdr_rule "$@" + persist_rdr_rule "$@" shift $# elif [ $# -ge 7 ] && [ "${7}" = "log" ]; then check_jail_validity - persist_rdr_log_rule "$@" load_rdr_log_rule "$@" + persist_rdr_log_rule "$@" shift $# else usage From 7ab9188b3a94b8f065e60a02c092b73e909c2a07 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 12 Dec 2024 17:23:21 -0700 Subject: [PATCH 30/76] Use case command instead of getopts to remain consistent --- usr/local/share/bastille/rdr.sh | 67 +++++++++++++++++---------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index cd8c180c..9fb5e782 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -217,42 +217,43 @@ if [ -n "$JAIL_IP6" ]; then fi } +# Set defaults +RDR_IF="$(grep "^[[:space:]]*${bastille_network_pf_ext_if}[[:space:]]*=" ${bastille_pf_conf} | awk -F'"' '{print $2}')" +RDR_SRC="any" +RDR_DST="any" while [ $# -gt 0 ]; do - while getopts "i:s:d:" opt; do - case $opt in - i) if ifconfig | grep -owq "${OPTARG}:"; then - RDR_IF="${OPTARG}" - else - error_exit "$OPTARG is not a valid interface on this system." - fi - ;; - s) check_rdr_ip_validity "${OPTARG}" - RDR_SRC="$OPTARG" - ;; - d) if ifconfig | grep -owq "inet ${OPTARG}"; then - RDR_DST="$OPTARG" - else - error_exit "$OPTARG is not an IP on this system." - fi - ;; - *) usage ;; - esac - done - shift $((OPTIND - 1)) - - # Set default interface, source, and destination if not set by options - if [ -z $RDR_IF ]; then - RDR_IF="$(grep "^[[:space:]]*${bastille_network_pf_ext_if}[[:space:]]*=" ${bastille_pf_conf} | awk -F'"' '{print $2}')" - fi - if [ -z $RDR_SRC ]; then - RDR_SRC="any" - fi - if [ -z $RDR_DST ]; then - RDR_DST="any" - fi - case "$1" in + -i|--interface) + if [ -z "${2}" ]; then + error_exit "Must specify an interface with [-i|--interface]" + fi + if ifconfig | grep -owq "${1}:"; then + RDR_IF="${2}" + shift 2 + else + error_exit "${2} is not a valid interface." + fi + ;; + -s|--source) + if [ -z "${2}" ]; then + error_exit "Must specify a source IP/subnet with [-s|--source]" + fi + check_ip_validity "${2}" + RDR_SRC="${2}" + shift 2 + ;; + -d|--destination) + if [ -z "${2}" ]; then + error_exit "Must specify a destination IP with [-d|--destination]" + fi + if ifconfig | grep -owq "inet ${2}"; then + RDR_DST="${2}" + shift 2 + else + error_exit "${2} is not an IP on this system." + fi + ;; list) if [ "${TARGET}" = 'ALL' ]; then for JAIL_NAME in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do From 4377e1413a2c24566acc55fdeb6b739e6baf2bed Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 12 Dec 2024 17:25:08 -0700 Subject: [PATCH 31/76] help message conform to case command --- usr/local/share/bastille/rdr.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 9fb5e782..3dae1c6d 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -37,9 +37,9 @@ usage() { cat << EOF Options: - -i [interface] | -- Set the interface to create the rdr rule on. Useful if you have multiple interfaces. - -s [source ip] | -- Limit rdr to a source IP. Useful to only allow access from a certian IP or subnet. - -d [destination ip] | -- Limit rdr to a destination IP. Useful if you have multiple IPs on one interface. + -i | --interface [interface] | -- Set the interface to create the rdr rule on. Useful if you have multiple interfaces. + -s | --source [source ip] | -- Limit rdr to a source IP. Useful to only allow access from a certian IP or subnet. + -d | --destination [destination ip] | -- Limit rdr to a destination IP. Useful if you have multiple IPs on one interface. EOF exit 1 From c6547e97cf684aafce6c7ba4adaad6af1ee83cae Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 12 Dec 2024 17:26:04 -0700 Subject: [PATCH 32/76] help message docs --- docs/chapters/subcommands/rdr.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index 9febbd24..e3be96ad 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -17,9 +17,9 @@ specify the interface they run on in rc.conf (or other config files) Usage: bastille rdr TARGET [options(s)] [clear|list|(tcp|udp host_port jail_port [log ['(' logopts ')'] ] )] Options: - -i [interface] | -- Set the interface to create the rdr rule on. Useful if you have multiple interfaces. - -s [source ip] | -- Limit rdr to a source IP. Useful to only allow access from a certian IP or subnet. - -d [destination ip] | -- Limit rdr to a destination IP. Useful if you have multiple IPs on one interface. + -i | --interface [interface] | -- Set the interface to create the rdr rule on. Useful if you have multiple interfaces. + -s | --source [source ip] | -- Limit rdr to a source IP. Useful to only allow access from a certian IP or subnet. + -d | --destination [destination ip] | -- Limit rdr to a destination IP. Useful if you have multiple IPs on one interface. # bastille rdr dev1 tcp 2001 22 [jail1]: From ab54842061291e77f217fbeedd1e130d5d2897e1 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 12 Dec 2024 18:39:08 -0700 Subject: [PATCH 33/76] error handling + add reset command to remove all rdr rules --- usr/local/share/bastille/rdr.sh | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 3dae1c6d..912ba80e 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -221,6 +221,7 @@ fi RDR_IF="$(grep "^[[:space:]]*${bastille_network_pf_ext_if}[[:space:]]*=" ${bastille_pf_conf} | awk -F'"' '{print $2}')" RDR_SRC="any" RDR_DST="any" +OPTION="0" while [ $# -gt 0 ]; do case "$1" in @@ -230,6 +231,7 @@ while [ $# -gt 0 ]; do fi if ifconfig | grep -owq "${1}:"; then RDR_IF="${2}" + OPTION="1" shift 2 else error_exit "${2} is not a valid interface." @@ -241,6 +243,7 @@ while [ $# -gt 0 ]; do fi check_ip_validity "${2}" RDR_SRC="${2}" + OPTION="1" shift 2 ;; -d|--destination) @@ -249,12 +252,16 @@ while [ $# -gt 0 ]; do fi if ifconfig | grep -owq "inet ${2}"; then RDR_DST="${2}" + OPTION="1" shift 2 else error_exit "${2} is not an IP on this system." fi ;; list) + if [ "${OPTION}" -eq 1 ];then + error_exit "Command \"${1}\" cannot be used with options." + fi if [ "${TARGET}" = 'ALL' ]; then for JAIL_NAME in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do echo "${JAIL_NAME} redirects:" @@ -267,6 +274,9 @@ while [ $# -gt 0 ]; do shift ;; clear) + if [ "${OPTION}" -eq 1 ];then + error_exit "Command \"${1}\" cannot be used with options." + fi if [ "${TARGET}" = 'ALL' ]; then for JAIL_NAME in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do echo "${JAIL_NAME} redirects:" @@ -278,6 +288,23 @@ while [ $# -gt 0 ]; do fi shift ;; + reset) + if [ "${OPTION}" -eq 1 ];then + error_exit "Command \"${1}\" cannot be used with options." + fi + if [ "${TARGET}" = 'ALL' ]; then + for JAIL_NAME in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do + echo "${JAIL_NAME} redirects:" + pfctl -a "rdr/${JAIL_NAME}" -Fn + rm -f "${bastille_jailsdir}"/"${JAIL__NAME}"/rdr.conf + done + else + check_jail_validity + pfctl -a "rdr/${JAIL_NAME}" -Fn + rm -f "${bastille_jailsdir}"/"${JAIL__NAME}"/rdr.conf + fi + shift + ;; tcp|udp) if [ $# -lt 3 ]; then usage @@ -321,7 +348,10 @@ while [ $# -gt 0 ]; do fi ;; *) - if [ $# -eq 6 ]; then + if [ "${OPTION}" -eq 1 ];then + usage + fi + if [ $# -eq 6 ] && [ "${4}" = "tcp" ] || [ "${4}" = "udp" ]; then check_jail_validity load_rdr_rule "$@" persist_rdr_rule "$@" From 9b6261346b0688e23b9548c28ec8698585f4b919 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 12 Dec 2024 18:39:43 -0700 Subject: [PATCH 34/76] Update rdr.rst - add reset to help --- docs/chapters/subcommands/rdr.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index e3be96ad..cf2488ac 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -14,7 +14,7 @@ specify the interface they run on in rc.conf (or other config files) .. code-block:: shell # bastille rdr --help - Usage: bastille rdr TARGET [options(s)] [clear|list|(tcp|udp host_port jail_port [log ['(' logopts ')'] ] )] + Usage: bastille rdr TARGET [options(s)] [clear|reset|list|(tcp|udp host_port jail_port [log ['(' logopts ')'] ] )] Options: -i | --interface [interface] | -- Set the interface to create the rdr rule on. Useful if you have multiple interfaces. From 20a291c689fdb78117bc0d45842e47b6e8678faa Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 12 Dec 2024 18:40:32 -0700 Subject: [PATCH 35/76] add reset to help command --- usr/local/share/bastille/rdr.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 912ba80e..c966c022 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -32,7 +32,7 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_notify "Usage: bastille rdr TARGET [options(s)] [clear|list|(tcp|udp)] host_port jail_port [log ['(' logopts ')'] ] )]" + error_notify "Usage: bastille rdr TARGET [options(s)] [clear|reset|list|(tcp|udp)] host_port jail_port [log ['(' logopts ')'] ] )]" cat << EOF Options: From d6cbbf2ac6dd683cb8c256c86bafc96ef5992e7c Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 12 Dec 2024 18:42:52 -0700 Subject: [PATCH 36/76] quick fix --- usr/local/share/bastille/rdr.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index c966c022..5699f4c2 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -229,7 +229,7 @@ while [ $# -gt 0 ]; do if [ -z "${2}" ]; then error_exit "Must specify an interface with [-i|--interface]" fi - if ifconfig | grep -owq "${1}:"; then + if ifconfig | grep -owq "${2}:"; then RDR_IF="${2}" OPTION="1" shift 2 From 3f97dd7e58bc8732514aa8d9fb611cd69bfc2e14 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 12 Dec 2024 18:52:46 -0700 Subject: [PATCH 37/76] split options and regular case commands --- usr/local/share/bastille/rdr.sh | 74 ++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 5699f4c2..2e28f237 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -223,41 +223,49 @@ RDR_SRC="any" RDR_DST="any" OPTION="0" -while [ $# -gt 0 ]; do - case "$1" in - -i|--interface) - if [ -z "${2}" ]; then - error_exit "Must specify an interface with [-i|--interface]" - fi - if ifconfig | grep -owq "${2}:"; then - RDR_IF="${2}" - OPTION="1" - shift 2 - else - error_exit "${2} is not a valid interface." - fi - ;; - -s|--source) - if [ -z "${2}" ]; then - error_exit "Must specify a source IP/subnet with [-s|--source]" - fi - check_ip_validity "${2}" - RDR_SRC="${2}" +# Check for options +case "$1" in + -i|--interface) + if [ -z "${2}" ]; then + error_exit "Must specify an interface with [-i|--interface]" + fi + if ifconfig | grep -owq "${2}:"; then + RDR_IF="${2}" OPTION="1" shift 2 - ;; - -d|--destination) - if [ -z "${2}" ]; then - error_exit "Must specify a destination IP with [-d|--destination]" - fi - if ifconfig | grep -owq "inet ${2}"; then - RDR_DST="${2}" - OPTION="1" - shift 2 - else - error_exit "${2} is not an IP on this system." - fi - ;; + else + error_exit "${2} is not a valid interface." + fi + ;; + -s|--source) + if [ -z "${2}" ]; then + error_exit "Must specify a source IP/subnet with [-s|--source]" + fi + check_ip_validity "${2}" + RDR_SRC="${2}" + OPTION="1" + shift 2 + ;; + -d|--destination) + if [ -z "${2}" ]; then + error_exit "Must specify a destination IP with [-d|--destination]" + fi + if ifconfig | grep -owq "inet ${2}"; then + RDR_DST="${2}" + OPTION="1" + shift 2 + else + error_exit "${2} is not an IP on this system." + fi + ;; +esac + +if [ $# -lt 2 ]; then + usage +fi + +while [ $# -gt 0 ]; do + case "$1" in list) if [ "${OPTION}" -eq 1 ];then error_exit "Command \"${1}\" cannot be used with options." From 216a4a5412b0858ec34ce8162162abf9d6feb7bd Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 12 Dec 2024 19:41:52 -0700 Subject: [PATCH 38/76] spacing --- usr/local/share/bastille/rdr.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 2e28f237..fc6faf84 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -257,7 +257,7 @@ case "$1" in else error_exit "${2} is not an IP on this system." fi - ;; + ;; esac if [ $# -lt 2 ]; then From ae9a33a50e92315e0c6c20cb4512014502a551dd Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 12 Dec 2024 20:23:50 -0700 Subject: [PATCH 39/76] error handling --- usr/local/share/bastille/rdr.sh | 68 +++++++++++++++++---------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index fc6faf84..c60529d5 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -224,40 +224,44 @@ RDR_DST="any" OPTION="0" # Check for options -case "$1" in - -i|--interface) - if [ -z "${2}" ]; then - error_exit "Must specify an interface with [-i|--interface]" - fi - if ifconfig | grep -owq "${2}:"; then - RDR_IF="${2}" - OPTION="1" - shift 2 - else - error_exit "${2} is not a valid interface." - fi - ;; - -s|--source) - if [ -z "${2}" ]; then - error_exit "Must specify a source IP/subnet with [-s|--source]" - fi - check_ip_validity "${2}" - RDR_SRC="${2}" - OPTION="1" - shift 2 - ;; - -d|--destination) - if [ -z "${2}" ]; then - error_exit "Must specify a destination IP with [-d|--destination]" - fi - if ifconfig | grep -owq "inet ${2}"; then - RDR_DST="${2}" +while [ "$#" -gt 0 ]; do + case "$1" in + -i|--interface) + if [ -z "${2}" ]; then + error_exit "Must specify an interface with [-i|--interface]" + fi + if ifconfig | grep -owq "${2}:"; then + RDR_IF="${2}" + OPTION="1" + shift 2 + else + error_exit "${2} is not a valid interface." + fi + ;; + -s|--source) + if [ -z "${2}" ]; then + error_exit "Must specify a source IP/subnet with [-s|--source]" + fi + check_rdr_ip_validity "${2}" + RDR_SRC="${2}" OPTION="1" shift 2 - else - error_exit "${2} is not an IP on this system." - fi - ;; + ;; + -d|--destination) + if [ -z "${2}" ]; then + error_exit "Must specify a destination IP with [-d|--destination]" + fi + if ifconfig | grep -owq "inet ${2}"; then + RDR_DST="${2}" + OPTION="1" + shift 2 + else + error_exit "${2} is not an IP on this system." + fi + ;; + *) + break + ;; esac if [ $# -lt 2 ]; then From ebf9c8955512cd79f42a4f2564fdf330c3138e2b Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 12 Dec 2024 20:26:06 -0700 Subject: [PATCH 40/76] missing done --- usr/local/share/bastille/rdr.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index c60529d5..919a7be9 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -262,7 +262,8 @@ while [ "$#" -gt 0 ]; do *) break ;; -esac + esac +done if [ $# -lt 2 ]; then usage From 3a16c047d2dcfb704c989bb266add1855ecb6ecb Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 13 Dec 2024 06:57:03 -0700 Subject: [PATCH 41/76] merge case commands, better error handling --- usr/local/share/bastille/rdr.sh | 38 ++++++++++++++------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 919a7be9..fb0b4ea5 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -227,8 +227,8 @@ OPTION="0" while [ "$#" -gt 0 ]; do case "$1" in -i|--interface) - if [ -z "${2}" ]; then - error_exit "Must specify an interface with [-i|--interface]" + if [ -z "${2}" ] || [ -z "${3}" ]; then + usage fi if ifconfig | grep -owq "${2}:"; then RDR_IF="${2}" @@ -239,8 +239,8 @@ while [ "$#" -gt 0 ]; do fi ;; -s|--source) - if [ -z "${2}" ]; then - error_exit "Must specify a source IP/subnet with [-s|--source]" + if [ -z "${2}" ] || [ -z "${3}" ]; then + usage fi check_rdr_ip_validity "${2}" RDR_SRC="${2}" @@ -248,8 +248,8 @@ while [ "$#" -gt 0 ]; do shift 2 ;; -d|--destination) - if [ -z "${2}" ]; then - error_exit "Must specify a destination IP with [-d|--destination]" + if [ -z "${2}" ] || [ -z "${3}" ]; then + usage fi if ifconfig | grep -owq "inet ${2}"; then RDR_DST="${2}" @@ -259,21 +259,11 @@ while [ "$#" -gt 0 ]; do error_exit "${2} is not an IP on this system." fi ;; - *) - break - ;; - esac -done - -if [ $# -lt 2 ]; then - usage -fi - -while [ $# -gt 0 ]; do - case "$1" in list) if [ "${OPTION}" -eq 1 ];then error_exit "Command \"${1}\" cannot be used with options." + elif [ -n "${2}" ]; then + usage fi if [ "${TARGET}" = 'ALL' ]; then for JAIL_NAME in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do @@ -289,7 +279,9 @@ while [ $# -gt 0 ]; do clear) if [ "${OPTION}" -eq 1 ];then error_exit "Command \"${1}\" cannot be used with options." - fi + elif [ -n "${2}" ]; then + usage + fi if [ "${TARGET}" = 'ALL' ]; then for JAIL_NAME in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do echo "${JAIL_NAME} redirects:" @@ -303,18 +295,20 @@ while [ $# -gt 0 ]; do ;; reset) if [ "${OPTION}" -eq 1 ];then - error_exit "Command \"${1}\" cannot be used with options." + error_exit "Command \"${1}\" cannot be used with options." + elif [ -n "${2}" ]; then + usage fi if [ "${TARGET}" = 'ALL' ]; then for JAIL_NAME in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do echo "${JAIL_NAME} redirects:" pfctl -a "rdr/${JAIL_NAME}" -Fn - rm -f "${bastille_jailsdir}"/"${JAIL__NAME}"/rdr.conf + rm -f "${bastille_jailsdir}"/"${JAIL_NAME}"/rdr.conf done else check_jail_validity pfctl -a "rdr/${JAIL_NAME}" -Fn - rm -f "${bastille_jailsdir}"/"${JAIL__NAME}"/rdr.conf + rm -f "${bastille_jailsdir}"/"${JAIL_NAME}"/rdr.conf fi shift ;; From 29bd130b24a9c78fc2b9f8c79844e579409f0944 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 13 Dec 2024 07:31:58 -0700 Subject: [PATCH 42/76] final revision --- usr/local/share/bastille/rdr.sh | 237 ++++++++++++++++---------------- 1 file changed, 116 insertions(+), 121 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index fb0b4ea5..531c2962 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -107,114 +107,114 @@ check_rdr_ip_validity() { else local IFS if echo "${ip}" | grep -Eq '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))?$'; then - TEST_IP=$(echo "${ip}" | cut -d / -f1) - IFS=. - set ${TEST_IP} - for quad in 1 2 3 4; do - if eval [ \$$quad -gt 255 ]; then - error_exit "Invalid: (${TEST_IP})" - fi - done - info "Valid: (${ip})." + TEST_IP=$(echo "${ip}" | cut -d / -f1) + IFS=. + set ${TEST_IP} + for quad in 1 2 3 4; do + if eval [ \$$quad -gt 255 ]; then + error_exit "Invalid: (${TEST_IP})" + fi + done + info "Valid: (${ip})." else - error_exit "Invalid: (${ip})." - fi + error_exit "Invalid: (${ip})." + fi fi } # function: write rule to rdr.conf persist_rdr_rule() { - local if="${1}" - local src="${2}" - local dst="${3}" - local proto="${4}" - local host_port="${5}" - local jail_port="${6}" -if ! grep -qs "$if $src $dst $proto $host_port $jail_port" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then - echo "$if $src $dst $proto $host_port $jail_port" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" -fi + local if="${1}" + local src="${2}" + local dst="${3}" + local proto="${4}" + local host_port="${5}" + local jail_port="${6}" + if ! grep -qs "$if $src $dst $proto $host_port $jail_port" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then + echo "$if $src $dst $proto $host_port $jail_port" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" + fi } persist_rdr_log_rule() { - local if="${1}" - local src="${2}" - local dst="${3}" - local proto="${4}" - local host_port="${5}" - local jail_port="${6}" -shift 6; -log=$@; -if ! grep -qs "$if $src $dst $proto $host_port $jail_port $log" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then - echo "$if $src $dst $proto $host_port $jail_port $log" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" -fi + local if="${1}" + local src="${2}" + local dst="${3}" + local proto="${4}" + local host_port="${5}" + local jail_port="${6}" + shift 6; + log=$@; + if ! grep -qs "$if $src $dst $proto $host_port $jail_port $log" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then + echo "$if $src $dst $proto $host_port $jail_port $log" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" + fi } # function: load rdr rule via pfctl load_rdr_rule() { - local if_name="${1}" - local if=ext_if=\"${1}\" - local src="${2}" - local dst="${3}" - local proto="${4}" - local host_port="${5}" - local jail_port="${6}" -# Create IPv4 rdr rule -if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn 2>/dev/null; - printf '%s\nrdr pass on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ - | pfctl -a "rdr/${JAIL_NAME}" -f-; then - error_exit "Failed to create IPv4 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" -else - info "[${JAIL_NAME}]:" - info "Redirecting IPv4:" - info "${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" -fi -# Create IPv6 rdr rule (if ip6.addr is enabled) -if [ -n "$JAIL_IP6" ]; then - if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; - printf '%s\nrdr pass on $%s inet proto %s to port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ - | pfctl -a "rdr/${JAIL_NAME}" -f-; then - error_exit "Failed to create IPv6 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" - else - info "[${JAIL_NAME}]:" - info "Redirecting IPv6:" - info "${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" - fi -fi + local if_name="${1}" + local if=ext_if=\"${1}\" + local src="${2}" + local dst="${3}" + local proto="${4}" + local host_port="${5}" + local jail_port="${6}" + # Create IPv4 rdr rule + if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn 2>/dev/null; + printf '%s\nrdr pass on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ + | pfctl -a "rdr/${JAIL_NAME}" -f-; then + error_exit "Failed to create IPv4 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + else + info "[${JAIL_NAME}]:" + info "Redirecting IPv4:" + info "${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + fi + # Create IPv6 rdr rule (if ip6.addr is enabled) + if [ -n "$JAIL_IP6" ]; then + if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; + printf '%s\nrdr pass on $%s inet proto %s to port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ + | pfctl -a "rdr/${JAIL_NAME}" -f-; then + error_exit "Failed to create IPv6 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + else + info "[${JAIL_NAME}]:" + info "Redirecting IPv6:" + info "${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + fi + fi } # function: load rdr rule with log via pfctl load_rdr_log_rule() { - local if_name="${1}" - local if=ext_if=\"${1}\" - local src="${2}" - local dst="${3}" - local proto="${4}" - local host_port="${5}" - local jail_port="${6}" -shift 6; -log=$@ -# Create IPv4 rule with log -if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; - printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ - | pfctl -a "rdr/${JAIL_NAME}" -f-; then - error_exit "Failed to create logged IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" -else - info "[${JAIL_NAME}]:" - info "Redirecting logged IPv4:" - info "${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" -fi -# Create IPv6 rdr rule with log (if ip6.addr is enabled) -if [ -n "$JAIL_IP6" ]; then - if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; - printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ - | pfctl -a "rdr/${JAIL_NAME}" -f-; then - error_exit "Failed to create logged IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" - else - info "[${JAIL_NAME}]:" - info "Redirecting logged IPv6:" - info "${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" - fi -fi + local if_name="${1}" + local if=ext_if=\"${1}\" + local src="${2}" + local dst="${3}" + local proto="${4}" + local host_port="${5}" + local jail_port="${6}" + shift 6; + log=$@ + # Create IPv4 rule with log + if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; + printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ + | pfctl -a "rdr/${JAIL_NAME}" -f-; then + error_exit "Failed to create logged IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + else + info "[${JAIL_NAME}]:" + info "Redirecting logged IPv4:" + info "${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + fi + # Create IPv6 rdr rule with log (if ip6.addr is enabled) + if [ -n "$JAIL_IP6" ]; then + if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; + printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ + | pfctl -a "rdr/${JAIL_NAME}" -f-; then + error_exit "Failed to create logged IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + else + info "[${JAIL_NAME}]:" + info "Redirecting logged IPv6:" + info "${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + fi + fi } # Set defaults @@ -229,10 +229,9 @@ while [ "$#" -gt 0 ]; do -i|--interface) if [ -z "${2}" ] || [ -z "${3}" ]; then usage - fi - if ifconfig | grep -owq "${2}:"; then + elif ifconfig | grep -owq "${2}:"; then RDR_IF="${2}" - OPTION="1" + OPTION="1" shift 2 else error_exit "${2} is not a valid interface." @@ -241,19 +240,19 @@ while [ "$#" -gt 0 ]; do -s|--source) if [ -z "${2}" ] || [ -z "${3}" ]; then usage + else + check_rdr_ip_validity "${2}" + RDR_SRC="${2}" + OPTION="1" + shift 2 fi - check_rdr_ip_validity "${2}" - RDR_SRC="${2}" - OPTION="1" - shift 2 ;; -d|--destination) if [ -z "${2}" ] || [ -z "${3}" ]; then usage - fi - if ifconfig | grep -owq "inet ${2}"; then + elif ifconfig | grep -owq "inet ${2}"; then RDR_DST="${2}" - OPTION="1" + OPTION="1" shift 2 else error_exit "${2} is not an IP on this system." @@ -262,10 +261,9 @@ while [ "$#" -gt 0 ]; do list) if [ "${OPTION}" -eq 1 ];then error_exit "Command \"${1}\" cannot be used with options." - elif [ -n "${2}" ]; then + elif [ -n "${2}" ]; then usage - fi - if [ "${TARGET}" = 'ALL' ]; then + elif [ "${TARGET}" = 'ALL' ]; then for JAIL_NAME in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do echo "${JAIL_NAME} redirects:" pfctl -a "rdr/${JAIL_NAME}" -Psn 2>/dev/null @@ -279,10 +277,9 @@ while [ "$#" -gt 0 ]; do clear) if [ "${OPTION}" -eq 1 ];then error_exit "Command \"${1}\" cannot be used with options." - elif [ -n "${2}" ]; then + elif [ -n "${2}" ]; then usage - fi - if [ "${TARGET}" = 'ALL' ]; then + elif [ "${TARGET}" = 'ALL' ]; then for JAIL_NAME in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do echo "${JAIL_NAME} redirects:" pfctl -a "rdr/${JAIL_NAME}" -Fn @@ -296,10 +293,9 @@ while [ "$#" -gt 0 ]; do reset) if [ "${OPTION}" -eq 1 ];then error_exit "Command \"${1}\" cannot be used with options." - elif [ -n "${2}" ]; then + elif [ -n "${2}" ]; then usage - fi - if [ "${TARGET}" = 'ALL' ]; then + elif [ "${TARGET}" = 'ALL' ]; then for JAIL_NAME in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do echo "${JAIL_NAME} redirects:" pfctl -a "rdr/${JAIL_NAME}" -Fn @@ -357,19 +353,18 @@ while [ "$#" -gt 0 ]; do *) if [ "${OPTION}" -eq 1 ];then usage - fi - if [ $# -eq 6 ] && [ "${4}" = "tcp" ] || [ "${4}" = "udp" ]; then - check_jail_validity - load_rdr_rule "$@" - persist_rdr_rule "$@" - shift $# + elif [ $# -eq 6 ] && [ "${4}" = "tcp" ] || [ "${4}" = "udp" ]; then + check_jail_validity + load_rdr_rule "$@" + persist_rdr_rule "$@" + shift $# elif [ $# -ge 7 ] && [ "${7}" = "log" ]; then - check_jail_validity - load_rdr_log_rule "$@" - persist_rdr_log_rule "$@" - shift $# + check_jail_validity + load_rdr_log_rule "$@" + persist_rdr_log_rule "$@" + shift $# else - usage + usage fi ;; esac From 0ce5c27d8e902de8fea37eea30fbcce19bc3b2b0 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 13 Dec 2024 07:41:27 -0700 Subject: [PATCH 43/76] add small info to reset command --- usr/local/share/bastille/rdr.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 531c2962..8cc9b04e 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -299,12 +299,16 @@ while [ "$#" -gt 0 ]; do for JAIL_NAME in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do echo "${JAIL_NAME} redirects:" pfctl -a "rdr/${JAIL_NAME}" -Fn - rm -f "${bastille_jailsdir}"/"${JAIL_NAME}"/rdr.conf + if rm -f "${bastille_jailsdir}"/"${JAIL_NAME}"/rdr.conf; then + info "[${JAIL_NAME}]: rdr.conf removed." + fi done else check_jail_validity pfctl -a "rdr/${JAIL_NAME}" -Fn - rm -f "${bastille_jailsdir}"/"${JAIL_NAME}"/rdr.conf + if rm -f "${bastille_jailsdir}"/"${JAIL_NAME}"/rdr.conf; then + info "[${JAIL_NAME}]: rdr.conf removed." + fi fi shift ;; From 744dd10a1c4cd5d0994ee72df96af801f761085c Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 13 Dec 2024 07:43:03 -0700 Subject: [PATCH 44/76] remove . --- usr/local/share/bastille/rdr.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 8cc9b04e..9eab2cc8 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -300,14 +300,14 @@ while [ "$#" -gt 0 ]; do echo "${JAIL_NAME} redirects:" pfctl -a "rdr/${JAIL_NAME}" -Fn if rm -f "${bastille_jailsdir}"/"${JAIL_NAME}"/rdr.conf; then - info "[${JAIL_NAME}]: rdr.conf removed." + info "[${JAIL_NAME}]: rdr.conf removed" fi done else check_jail_validity pfctl -a "rdr/${JAIL_NAME}" -Fn if rm -f "${bastille_jailsdir}"/"${JAIL_NAME}"/rdr.conf; then - info "[${JAIL_NAME}]: rdr.conf removed." + info "[${JAIL_NAME}]: rdr.conf removed" fi fi shift From 1fcdfa4e9bf0941afaa8fb7018246226c597a55c Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 13 Dec 2024 14:49:36 -0700 Subject: [PATCH 45/76] add "ports" command to list jails and their published ports --- usr/local/share/bastille/list.sh | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/usr/local/share/bastille/list.sh b/usr/local/share/bastille/list.sh index ebb28cc4..d2fd2f89 100644 --- a/usr/local/share/bastille/list.sh +++ b/usr/local/share/bastille/list.sh @@ -32,7 +32,7 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_exit "Usage: bastille list [-j|-a] [release [-p]|template|(jail|container)|log|limit|(import|export|backup)]" + error_exit "Usage: bastille list [-j|-a] [release [-p]|template|(jail|container)|log|limit|ports|(import|export|backup)]" } if [ "${1}" = help -o "${1}" = "-h" -o "${1}" = "--help" ]; then @@ -202,12 +202,28 @@ list_import(){ ls "${bastille_backupsdir}" | grep -v ".sha256$" } +list_ports(){ + if [ -d "${bastille_jailsdir}" ]; then + JAIL_LIST=$(ls "${bastille_jailsdir}" | sed "s/\n//g") + for _JAIL in ${JAIL_LIST}; do + if [ -f "${bastille_jailsdir}/${_JAIL}/rdr.conf" ]; then + _PORTS="$(cat "${bastille_jailsdir}"/"${_JAIL}"/rdr.conf | awk '{print $1":"$4"//"$2":"$5" -> "$3":"$6}')" + info "[${_JAIL}]:" + echo "${_PORTS}" + fi + done + fi +} + if [ $# -gt 0 ]; then # Handle special-case commands first. case "${1}" in all|-a|--all) list_all ;; + port|ports) + list_ports + ;; release|releases) list_release ;; From 8bf734210597210782e90a2137c6c39dadc1e7a9 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 13 Dec 2024 14:52:01 -0700 Subject: [PATCH 46/76] remove / to stay consistent --- usr/local/share/bastille/list.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/list.sh b/usr/local/share/bastille/list.sh index d2fd2f89..a10dc532 100644 --- a/usr/local/share/bastille/list.sh +++ b/usr/local/share/bastille/list.sh @@ -207,7 +207,7 @@ list_ports(){ JAIL_LIST=$(ls "${bastille_jailsdir}" | sed "s/\n//g") for _JAIL in ${JAIL_LIST}; do if [ -f "${bastille_jailsdir}/${_JAIL}/rdr.conf" ]; then - _PORTS="$(cat "${bastille_jailsdir}"/"${_JAIL}"/rdr.conf | awk '{print $1":"$4"//"$2":"$5" -> "$3":"$6}')" + _PORTS="$(cat "${bastille_jailsdir}"/"${_JAIL}"/rdr.conf | awk '{print $1":"$4"/"$2":"$5" -> "$3":"$6}')" info "[${_JAIL}]:" echo "${_PORTS}" fi From e6ae0ebf20d27e2f6be4e749142c370900a81c17 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 13 Dec 2024 14:56:33 -0700 Subject: [PATCH 47/76] too much green, minimize color and info when redirecting --- usr/local/share/bastille/rdr.sh | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 9eab2cc8..431acf4d 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -165,8 +165,7 @@ load_rdr_rule() { error_exit "Failed to create IPv4 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${JAIL_NAME}]:" - info "Redirecting IPv4:" - info "${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + echo "IPv4 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" fi # Create IPv6 rdr rule (if ip6.addr is enabled) if [ -n "$JAIL_IP6" ]; then @@ -176,8 +175,7 @@ load_rdr_rule() { error_exit "Failed to create IPv6 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${JAIL_NAME}]:" - info "Redirecting IPv6:" - info "${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + echo "IPv6 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" fi fi } @@ -200,8 +198,7 @@ load_rdr_log_rule() { error_exit "Failed to create logged IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${JAIL_NAME}]:" - info "Redirecting logged IPv4:" - info "${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + echo "IPv4 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" fi # Create IPv6 rdr rule with log (if ip6.addr is enabled) if [ -n "$JAIL_IP6" ]; then @@ -211,8 +208,7 @@ load_rdr_log_rule() { error_exit "Failed to create logged IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${JAIL_NAME}]:" - info "Redirecting logged IPv6:" - info "${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + echo "IPv6 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" fi fi } From 7cb3e4a8b9407adfdb6186684be71d5111a9a3d0 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 14 Dec 2024 10:46:50 -0700 Subject: [PATCH 48/76] fix ip6 rule syntax --- usr/local/share/bastille/rdr.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 431acf4d..a87d6020 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -170,7 +170,7 @@ load_rdr_rule() { # Create IPv6 rdr rule (if ip6.addr is enabled) if [ -n "$JAIL_IP6" ]; then if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; - printf '%s\nrdr pass on $%s inet proto %s to port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ + printf '%s\nrdr pass on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f-; then error_exit "Failed to create IPv6 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else From 9d37a15703a8a1c1b4095c600251bd562388135b Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 14 Dec 2024 10:49:48 -0700 Subject: [PATCH 49/76] revert/ persist first then load rule --- usr/local/share/bastille/rdr.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index a87d6020..80edcb1c 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -227,7 +227,7 @@ while [ "$#" -gt 0 ]; do usage elif ifconfig | grep -owq "${2}:"; then RDR_IF="${2}" - OPTION="1" + OPTION="1" shift 2 else error_exit "${2} is not a valid interface." @@ -239,7 +239,7 @@ while [ "$#" -gt 0 ]; do else check_rdr_ip_validity "${2}" RDR_SRC="${2}" - OPTION="1" + OPTION="1" shift 2 fi ;; @@ -248,7 +248,7 @@ while [ "$#" -gt 0 ]; do usage elif ifconfig | grep -owq "inet ${2}"; then RDR_DST="${2}" - OPTION="1" + OPTION="1" shift 2 else error_exit "${2} is not an IP on this system." @@ -313,8 +313,8 @@ while [ "$#" -gt 0 ]; do usage elif [ $# -eq 3 ]; then check_jail_validity - load_rdr_rule $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 persist_rdr_rule $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 + load_rdr_rule $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 shift "$#" else case "$4" in @@ -329,16 +329,16 @@ while [ "$#" -gt 0 ]; do done if [ $2 == "(" ] && [ $last == ")" ] ; then check_jail_validity - load_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" - persist_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" + persist_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" + load_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" shift $# else usage fi elif [ $# -eq 1 ]; then check_jail_validity - load_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" persist_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" + load_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" shift 1 else usage @@ -355,13 +355,13 @@ while [ "$#" -gt 0 ]; do usage elif [ $# -eq 6 ] && [ "${4}" = "tcp" ] || [ "${4}" = "udp" ]; then check_jail_validity - load_rdr_rule "$@" persist_rdr_rule "$@" + load_rdr_rule "$@" shift $# elif [ $# -ge 7 ] && [ "${7}" = "log" ]; then check_jail_validity - load_rdr_log_rule "$@" persist_rdr_log_rule "$@" + load_rdr_log_rule "$@" shift $# else usage From 031f47f39484da2f349900ab6d9460ffad14a55b Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 14 Dec 2024 10:53:33 -0700 Subject: [PATCH 50/76] fix ipv6 (inet > inet6) --- usr/local/share/bastille/rdr.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 80edcb1c..2fda0b0c 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -170,7 +170,7 @@ load_rdr_rule() { # Create IPv6 rdr rule (if ip6.addr is enabled) if [ -n "$JAIL_IP6" ]; then if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; - printf '%s\nrdr pass on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ + printf '%s\nrdr pass on $%s inet6 proto %s from %s to %s port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f-; then error_exit "Failed to create IPv6 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else @@ -203,7 +203,7 @@ load_rdr_log_rule() { # Create IPv6 rdr rule with log (if ip6.addr is enabled) if [ -n "$JAIL_IP6" ]; then if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; - printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ + printf '%s\nrdr pass %s on $%s inet6 proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f-; then error_exit "Failed to create logged IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else From 5b4cb721e59c47ce8532a5504158f10650f67ce2 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 14 Dec 2024 12:44:59 -0700 Subject: [PATCH 51/76] add support for dual/ipv4/ipv6 options --- usr/local/share/bastille/rdr.sh | 162 +++++++++++++++++++------------- 1 file changed, 96 insertions(+), 66 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 2fda0b0c..f51ad914 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -40,6 +40,7 @@ usage() { -i | --interface [interface] | -- Set the interface to create the rdr rule on. Useful if you have multiple interfaces. -s | --source [source ip] | -- Limit rdr to a source IP. Useful to only allow access from a certian IP or subnet. -d | --destination [destination ip] | -- Limit rdr to a destination IP. Useful if you have multiple IPs on one interface. + -t | --type [ipv4|ipv6] | -- Specify IP type. Must be used if -s or -d are used. Defaults to both. EOF exit 1 @@ -62,9 +63,6 @@ TARGET="${1}" JAIL_NAME="" JAIL_IP="" JAIL_IP6="" -RDR_IF="" -RDR_SRC="" -RDR_DST="" shift check_jail_validity() { @@ -124,55 +122,60 @@ check_rdr_ip_validity() { # function: write rule to rdr.conf persist_rdr_rule() { - local if="${1}" - local src="${2}" - local dst="${3}" - local proto="${4}" - local host_port="${5}" - local jail_port="${6}" - if ! grep -qs "$if $src $dst $proto $host_port $jail_port" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then - echo "$if $src $dst $proto $host_port $jail_port" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" + local inet="${1}" + local if="${2}" + local src="${3}" + local dst="${4}" + local proto="${5}" + local host_port="${6}" + local jail_port="${7}" + if ! grep -qs "$inet $if $src $dst $proto $host_port $jail_port" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then + echo "$inet $if $src $dst $proto $host_port $jail_port" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" fi } persist_rdr_log_rule() { - local if="${1}" - local src="${2}" - local dst="${3}" - local proto="${4}" - local host_port="${5}" - local jail_port="${6}" - shift 6; + local inet="${1}" + local if="${2}" + local src="${3}" + local dst="${4}" + local proto="${5}" + local host_port="${6}" + local jail_port="${7}" + shift 7; log=$@; - if ! grep -qs "$if $src $dst $proto $host_port $jail_port $log" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then - echo "$if $src $dst $proto $host_port $jail_port $log" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" + if ! grep -qs "$inet $if $src $dst $proto $host_port $jail_port $log" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then + echo "$inet $if $src $dst $proto $host_port $jail_port $log" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" fi } # function: load rdr rule via pfctl load_rdr_rule() { - local if_name="${1}" - local if=ext_if=\"${1}\" - local src="${2}" - local dst="${3}" - local proto="${4}" - local host_port="${5}" - local jail_port="${6}" + local inet="${1}" + local if_name="${2}" + local if=ext_if=\"${2}\" + local src="${3}" + local dst="${4}" + local proto="${5}" + local host_port="${6}" + local jail_port="${7}" # Create IPv4 rdr rule - if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn 2>/dev/null; - printf '%s\nrdr pass on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ - | pfctl -a "rdr/${JAIL_NAME}" -f-; then - error_exit "Failed to create IPv4 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" - else - info "[${JAIL_NAME}]:" - echo "IPv4 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + if [ "${inet}" = "ipv4" ] || [ "${inet}" = "dual" ]; then + if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn 2>/dev/null; + printf '%s\nrdr pass on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ + | pfctl -a "rdr/${JAIL_NAME}" -f-; then + error_exit "Failed to create IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + else + info "[${JAIL_NAME}]:" + echo "IPv4 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + fi fi # Create IPv6 rdr rule (if ip6.addr is enabled) - if [ -n "$JAIL_IP6" ]; then + if [ -n "$JAIL_IP6" ] && [ "${inet}" = "ipv6" ] || [ "${inet}" = "dual" ]; then if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; printf '%s\nrdr pass on $%s inet6 proto %s from %s to %s port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f-; then - error_exit "Failed to create IPv6 rdr rule \"${1} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + error_exit "Failed to create IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${JAIL_NAME}]:" echo "IPv6 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" @@ -182,26 +185,29 @@ load_rdr_rule() { # function: load rdr rule with log via pfctl load_rdr_log_rule() { - local if_name="${1}" - local if=ext_if=\"${1}\" - local src="${2}" - local dst="${3}" - local proto="${4}" - local host_port="${5}" - local jail_port="${6}" - shift 6; + local inet="${1}" + local if_name="${2}" + local if=ext_if=\"${2}\" + local src="${3}" + local dst="${4}" + local proto="${5}" + local host_port="${6}" + local jail_port="${7}" + shift 7; log=$@ # Create IPv4 rule with log - if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; - printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ - | pfctl -a "rdr/${JAIL_NAME}" -f-; then - error_exit "Failed to create logged IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" - else - info "[${JAIL_NAME}]:" - echo "IPv4 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + if [ "${inet} = "ipv4" ] || [ "${inet} = "dual" ]; then + if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; + printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ + | pfctl -a "rdr/${JAIL_NAME}" -f-; then + error_exit "Failed to create logged IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + else + info "[${JAIL_NAME}]:" + echo "IPv4 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + fi fi # Create IPv6 rdr rule with log (if ip6.addr is enabled) - if [ -n "$JAIL_IP6" ]; then + if [ -n "$JAIL_IP6" ] && [ "${inet} = "ipv6" ] || [ "${inet} = "dual" ]; then if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; printf '%s\nrdr pass %s on $%s inet6 proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f-; then @@ -218,6 +224,11 @@ RDR_IF="$(grep "^[[:space:]]*${bastille_network_pf_ext_if}[[:space:]]*=" ${basti RDR_SRC="any" RDR_DST="any" OPTION="0" +RDR_INET="dual" +OPTION_IF=0 +OPTION_SRC=0 +OPTION_DST=0 +OPTION_TYPE=0 # Check for options while [ "$#" -gt 0 ]; do @@ -226,8 +237,8 @@ while [ "$#" -gt 0 ]; do if [ -z "${2}" ] || [ -z "${3}" ]; then usage elif ifconfig | grep -owq "${2}:"; then + OPTION_IF=1 RDR_IF="${2}" - OPTION="1" shift 2 else error_exit "${2} is not a valid interface." @@ -238,8 +249,8 @@ while [ "$#" -gt 0 ]; do usage else check_rdr_ip_validity "${2}" + OPTION_SRC=1 RDR_SRC="${2}" - OPTION="1" shift 2 fi ;; @@ -248,14 +259,25 @@ while [ "$#" -gt 0 ]; do usage elif ifconfig | grep -owq "inet ${2}"; then RDR_DST="${2}" - OPTION="1" + OPTION_DST=1 shift 2 else error_exit "${2} is not an IP on this system." fi ;; + -t|--type) + if [ -z "${2}" ] || [ -z "${3}" ]; then + usage + elif [ "${2}" != "ipv4" ] && [ "${2}" != "ipv6" ]; then + usage + else + OPTION_TYPE=1 + RDR_INET="${2}" + shift 2 + fi + ;; list) - if [ "${OPTION}" -eq 1 ];then + if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_TYPE}" -eq 1 ];then error_exit "Command \"${1}\" cannot be used with options." elif [ -n "${2}" ]; then usage @@ -271,7 +293,7 @@ while [ "$#" -gt 0 ]; do shift ;; clear) - if [ "${OPTION}" -eq 1 ];then + if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_TYPE}" -eq 1 ];then error_exit "Command \"${1}\" cannot be used with options." elif [ -n "${2}" ]; then usage @@ -287,7 +309,7 @@ while [ "$#" -gt 0 ]; do shift ;; reset) - if [ "${OPTION}" -eq 1 ];then + if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_TYPE}" -eq 1 ];then error_exit "Command \"${1}\" cannot be used with options." elif [ -n "${2}" ]; then usage @@ -311,10 +333,12 @@ while [ "$#" -gt 0 ]; do tcp|udp) if [ $# -lt 3 ]; then usage + elif [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] && [ "${OPTION_TYPE}" -ne 1 ];then + error_exit "[-t|--type] must be set when using [-s|--source] or [-d|--destination]" elif [ $# -eq 3 ]; then check_jail_validity - persist_rdr_rule $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 - load_rdr_rule $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 + persist_rdr_rule $RDR_INET $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 + load_rdr_rule $RDR_INET $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 shift "$#" else case "$4" in @@ -329,16 +353,16 @@ while [ "$#" -gt 0 ]; do done if [ $2 == "(" ] && [ $last == ")" ] ; then check_jail_validity - persist_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" - load_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" + persist_rdr_log_rule $RDR_INET $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" + load_rdr_log_rule $RDR_INET $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" shift $# else usage fi elif [ $# -eq 1 ]; then check_jail_validity - persist_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" - load_rdr_log_rule $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" + persist_rdr_log_rule $RDR_INET $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" + load_rdr_log_rule $RDR_INET $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" shift 1 else usage @@ -353,12 +377,18 @@ while [ "$#" -gt 0 ]; do *) if [ "${OPTION}" -eq 1 ];then usage - elif [ $# -eq 6 ] && [ "${4}" = "tcp" ] || [ "${4}" = "udp" ]; then + fi + if [ "${1}" = "dual" ] || [ "${1}" = "ipv4" ] || [ "${1}" = "ipv6" ]; then + RDR_INET="${1}" + else + usage + fi + if [ $# -eq 7 ] && [ "${5}" = "tcp" ] || [ "${5}" = "udp" ]; then check_jail_validity persist_rdr_rule "$@" load_rdr_rule "$@" shift $# - elif [ $# -ge 7 ] && [ "${7}" = "log" ]; then + elif [ $# -ge 8 ] && [ "${8}" = "log" ]; then check_jail_validity persist_rdr_log_rule "$@" load_rdr_log_rule "$@" From 2059560dbdb9624c1fcf29bc9b68ce96bcbdcc09 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 14 Dec 2024 16:18:41 -0700 Subject: [PATCH 52/76] list stack when listing ports --- usr/local/share/bastille/list.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/list.sh b/usr/local/share/bastille/list.sh index a10dc532..d9b281f4 100644 --- a/usr/local/share/bastille/list.sh +++ b/usr/local/share/bastille/list.sh @@ -207,7 +207,7 @@ list_ports(){ JAIL_LIST=$(ls "${bastille_jailsdir}" | sed "s/\n//g") for _JAIL in ${JAIL_LIST}; do if [ -f "${bastille_jailsdir}/${_JAIL}/rdr.conf" ]; then - _PORTS="$(cat "${bastille_jailsdir}"/"${_JAIL}"/rdr.conf | awk '{print $1":"$4"/"$2":"$5" -> "$3":"$6}')" + _PORTS="$(cat "${bastille_jailsdir}"/"${_JAIL}"/rdr.conf | awk '{print $1 $2":"$5"/"$3":"$6" -> "$4":"$7}')" info "[${_JAIL}]:" echo "${_PORTS}" fi From 981268cf8b3e66e1799c8b7dfeb2f646efe6d0b0 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 14 Dec 2024 16:20:20 -0700 Subject: [PATCH 53/76] document -t --- docs/chapters/subcommands/rdr.rst | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index cf2488ac..f02ed621 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -20,19 +20,19 @@ specify the interface they run on in rc.conf (or other config files) -i | --interface [interface] | -- Set the interface to create the rdr rule on. Useful if you have multiple interfaces. -s | --source [source ip] | -- Limit rdr to a source IP. Useful to only allow access from a certian IP or subnet. -d | --destination [destination ip] | -- Limit rdr to a destination IP. Useful if you have multiple IPs on one interface. + -t | --type [ipv4|ipv6] | -- Specify IP type. Must be used if -s or -d are used. Defaults to both. + # bastille rdr dev1 tcp 2001 22 [jail1]: - Redirecting IPv4: - tcp/any:2001 -> any:22 on em0 + IPv4 tcp/any:2001 -> any:22 on em0 # bastille rdr dev1 list rdr on em0 inet proto tcp from any to any port = 2001 -> 10.17.89.1 port 22 # bastille rdr dev1 udp 2053 53 [jail1]: - Redirecting: - udp/any:2001 -> any:22 on em0 + IPv4 udp/any:2001 -> any:22 on em0 # bastille rdr dev1 list rdr pass on em0 inet proto tcp from any to any port = 2001 -> 10.17.89.1 port 22 @@ -51,23 +51,19 @@ The `rdr` command includes 3 additional options: # bastille rdr dev1 -i vtnet0 udp 2001 22 [jail1]: - Redirecting IPv4: - tcp/any:8000 -> any:80 on vtnet0 + IPv4 tcp/any:8000 -> any:80 on vtnet0 # bastille rdr dev1 -s 192.168.0.1 tcp 8080 81 [jail1]: - Redirecting IPv4: - tcp/192.168.0.1:8080 -> any:81 on em0 + IPv4 tcp/192.168.0.1:8080 -> any:81 on em0 # bastille rdr dev1 -d 192.168.0.84 tcp 8082 82 [jail1]: - Redirecting IPv4: - tcp/any:8082 -> 192.168.0.84:82 on em0 + IPv4 tcp/any:8082 -> 192.168.0.84:82 on em0 # bastille rdr dev1 -i vtnet0 -d 192.168.0.45 tcp 9000 9000 [jail1]: - Redirecting IPv4: - tcp/any:9000 -> 192.168.0.45:9000 on vtnet0 + IPv4 tcp/any:9000 -> 192.168.0.45:9000 on vtnet0 # bastille rdr dev1 list rdr pass on vtnet0 inet proto udp from any to any port = 2001 -> 10.17.89.1 port 22 From 1f899b73a7071c75070f523c66e76549fb7236b9 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 14 Dec 2024 16:30:08 -0700 Subject: [PATCH 54/76] add space to list command --- usr/local/share/bastille/list.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/list.sh b/usr/local/share/bastille/list.sh index d9b281f4..3f74d29f 100644 --- a/usr/local/share/bastille/list.sh +++ b/usr/local/share/bastille/list.sh @@ -207,7 +207,7 @@ list_ports(){ JAIL_LIST=$(ls "${bastille_jailsdir}" | sed "s/\n//g") for _JAIL in ${JAIL_LIST}; do if [ -f "${bastille_jailsdir}/${_JAIL}/rdr.conf" ]; then - _PORTS="$(cat "${bastille_jailsdir}"/"${_JAIL}"/rdr.conf | awk '{print $1 $2":"$5"/"$3":"$6" -> "$4":"$7}')" + _PORTS="$(cat "${bastille_jailsdir}"/"${_JAIL}"/rdr.conf | awk '{print $1" "$2":"$5"/"$3":"$6" -> "$4":"$7}')" info "[${_JAIL}]:" echo "${_PORTS}" fi From bd2a2e1a4ed27e2fdb8d64cfd7bd0573e1ee56b5 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 14 Dec 2024 16:42:44 -0700 Subject: [PATCH 55/76] Typo --- docs/chapters/subcommands/rdr.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index f02ed621..b3be77f2 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -14,7 +14,7 @@ specify the interface they run on in rc.conf (or other config files) .. code-block:: shell # bastille rdr --help - Usage: bastille rdr TARGET [options(s)] [clear|reset|list|(tcp|udp host_port jail_port [log ['(' logopts ')'] ] )] + Usage: bastille rdr TARGET [option(s)] [clear|reset|list|(tcp|udp host_port jail_port [log ['(' logopts ')'] ] )] Options: -i | --interface [interface] | -- Set the interface to create the rdr rule on. Useful if you have multiple interfaces. From afd7ea7f8f418a56a3cbf0634d4168ba1da3ef91 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 14 Dec 2024 16:43:35 -0700 Subject: [PATCH 56/76] Typo --- usr/local/share/bastille/rdr.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index f51ad914..54cc2649 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -32,7 +32,7 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_notify "Usage: bastille rdr TARGET [options(s)] [clear|reset|list|(tcp|udp)] host_port jail_port [log ['(' logopts ')'] ] )]" + error_notify "Usage: bastille rdr TARGET [option(s)] [clear|reset|list|(tcp|udp)] host_port jail_port [log ['(' logopts ')'] ] )]" cat << EOF Options: From 85fecea04f2c4c645466a6ea870966bb56e9df2d Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 14 Dec 2024 18:42:28 -0700 Subject: [PATCH 57/76] var rename for clarity --- usr/local/share/bastille/rdr.sh | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 54cc2649..dae0f00d 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -48,9 +48,9 @@ EOF # Handle special-case commands first. case "$1" in -help|-h|--help) - usage - ;; + help|-h|--help) + usage + ;; esac if [ $# -lt 2 ]; then @@ -80,10 +80,11 @@ check_jail_validity() { # Check if jail ip4 address (ip4.addr) is valid (non-VNET only) if [ "$(bastille config $TARGET get vnet)" != 'enabled' ]; then JAIL_IP=$(/usr/sbin/jls -j "${TARGET}" ip4.addr 2>/dev/null) - if [ -z "${JAIL_IP}" -o "${JAIL_IP}" = "-" ]; then + if [ -z "${JAIL_IP}" ] || [ "${JAIL_IP}" = "-" ]; then error_exit "Jail IP not found: ${TARGET}" fi fi + # Check if jail ip6 address (ip6.addr) is valid (non-VNET only) if [ "$(bastille config $TARGET get vnet)" != 'enabled' ]; then if [ "$(bastille config $TARGET get ip6)" != 'disable' ] && [ "$(bastille config $TARGET get ip6)" != 'not set' ]; then @@ -97,6 +98,7 @@ check_jail_validity() { fi } +# function: check if IP is valid check_rdr_ip_validity() { local ip="$1" local ip6=$(echo "${ip}" | grep -E '^(([a-fA-F0-9:]+$)|([a-fA-F0-9:]+\/[0-9]{1,3}$)|SLAAC)') @@ -228,7 +230,7 @@ RDR_INET="dual" OPTION_IF=0 OPTION_SRC=0 OPTION_DST=0 -OPTION_TYPE=0 +OPTION_INET_TYPE=0 # Check for options while [ "$#" -gt 0 ]; do @@ -258,8 +260,8 @@ while [ "$#" -gt 0 ]; do if [ -z "${2}" ] || [ -z "${3}" ]; then usage elif ifconfig | grep -owq "inet ${2}"; then + OPTION_DST=1 RDR_DST="${2}" - OPTION_DST=1 shift 2 else error_exit "${2} is not an IP on this system." @@ -271,13 +273,13 @@ while [ "$#" -gt 0 ]; do elif [ "${2}" != "ipv4" ] && [ "${2}" != "ipv6" ]; then usage else - OPTION_TYPE=1 + OPTION_INET_TYPE=1 RDR_INET="${2}" shift 2 fi ;; list) - if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_TYPE}" -eq 1 ];then + if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ];then error_exit "Command \"${1}\" cannot be used with options." elif [ -n "${2}" ]; then usage @@ -293,7 +295,7 @@ while [ "$#" -gt 0 ]; do shift ;; clear) - if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_TYPE}" -eq 1 ];then + if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ];then error_exit "Command \"${1}\" cannot be used with options." elif [ -n "${2}" ]; then usage @@ -309,7 +311,7 @@ while [ "$#" -gt 0 ]; do shift ;; reset) - if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_TYPE}" -eq 1 ];then + if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ];then error_exit "Command \"${1}\" cannot be used with options." elif [ -n "${2}" ]; then usage @@ -333,7 +335,7 @@ while [ "$#" -gt 0 ]; do tcp|udp) if [ $# -lt 3 ]; then usage - elif [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] && [ "${OPTION_TYPE}" -ne 1 ];then + elif [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] && [ "${OPTION_INET_TYPE}" -ne 1 ];then error_exit "[-t|--type] must be set when using [-s|--source] or [-d|--destination]" elif [ $# -eq 3 ]; then check_jail_validity From 71b1f8ce1d1410144afe2175a99d3b10c7566c7a Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 15 Dec 2024 08:55:46 -0700 Subject: [PATCH 58/76] simply print rdr file when listing ports --- usr/local/share/bastille/list.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/list.sh b/usr/local/share/bastille/list.sh index 3f74d29f..21b7db01 100644 --- a/usr/local/share/bastille/list.sh +++ b/usr/local/share/bastille/list.sh @@ -207,7 +207,7 @@ list_ports(){ JAIL_LIST=$(ls "${bastille_jailsdir}" | sed "s/\n//g") for _JAIL in ${JAIL_LIST}; do if [ -f "${bastille_jailsdir}/${_JAIL}/rdr.conf" ]; then - _PORTS="$(cat "${bastille_jailsdir}"/"${_JAIL}"/rdr.conf | awk '{print $1" "$2":"$5"/"$3":"$6" -> "$4":"$7}')" + _PORTS="$(cat "${bastille_jailsdir}"/"${_JAIL}"/rdr.conf)" info "[${_JAIL}]:" echo "${_PORTS}" fi From a717b09d0fdb050e0a21fb0d5b513ea4d430af76 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 15 Dec 2024 08:57:02 -0700 Subject: [PATCH 59/76] print less info --- usr/local/share/bastille/rdr.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index dae0f00d..f1842f85 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -169,7 +169,7 @@ load_rdr_rule() { error_exit "Failed to create IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${JAIL_NAME}]:" - echo "IPv4 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + echo "IPv4 ${proto}/${host_port}:${jail_port} on ${if_name}" fi fi # Create IPv6 rdr rule (if ip6.addr is enabled) @@ -180,7 +180,7 @@ load_rdr_rule() { error_exit "Failed to create IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${JAIL_NAME}]:" - echo "IPv6 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + echo "IPv6 ${proto}/${host_port}:${jail_port} on ${if_name}" fi fi } @@ -205,7 +205,7 @@ load_rdr_log_rule() { error_exit "Failed to create logged IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${JAIL_NAME}]:" - echo "IPv4 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + echo "IPv4 ${proto}/${host_port}:${jail_port} on ${if_name}" fi fi # Create IPv6 rdr rule with log (if ip6.addr is enabled) @@ -216,7 +216,7 @@ load_rdr_log_rule() { error_exit "Failed to create logged IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${JAIL_NAME}]:" - echo "IPv6 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + echo "IPv6 ${proto}/${host_port}:${jail_port} on ${if_name}" fi fi } From 0c80326e3a305f4150a8b990699b50f630495ed9 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 16 Dec 2024 09:34:54 -0700 Subject: [PATCH 60/76] fix quotes --- usr/local/share/bastille/rdr.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index c127c904..68560d66 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -101,7 +101,7 @@ check_jail_validity() { # function: check if IP is valid check_rdr_ip_validity() { local ip="$1" - local ip6=$(echo "${ip}" | grep -E '^(([a-fA-F0-9:]+$)|([a-fA-F0-9:]+\/[0-9]{1,3}$)|SLAAC)') + local ip6="$(echo "${ip}" | grep -E '^(([a-fA-F0-9:]+$)|([a-fA-F0-9:]+\/[0-9]{1,3}$)|SLAAC)')" if [ -n "${ip6}" ]; then info "Valid: (${ip6})." else @@ -198,7 +198,7 @@ load_rdr_log_rule() { shift 7; log=$@ # Create IPv4 rule with log - if [ "${inet} = "ipv4" ] || [ "${inet} = "dual" ]; then + if { [ "${inet}" = "ipv4" ] || [ "${inet}" = "dual" ]; }; then if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f-; then @@ -209,7 +209,7 @@ load_rdr_log_rule() { fi fi # Create IPv6 rdr rule with log (if ip6.addr is enabled) - if [ -n "$JAIL_IP6" ] && [ "${inet} = "ipv6" ] || [ "${inet} = "dual" ]; then + if [ -n "$JAIL_IP6" ] && { [ "${inet}" = "ipv6" ] || [ "${inet}" = "dual" ]; };then if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; printf '%s\nrdr pass %s on $%s inet6 proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ | pfctl -a "rdr/${JAIL_NAME}" -f-; then From fd4c5111b50caae001ca55a8729c95f9e7f41003 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 16 Dec 2024 23:00:20 -0700 Subject: [PATCH 61/76] cleanup --- usr/local/share/bastille/rdr.sh | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index ae7d6b3b..7e46390f 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -225,7 +225,6 @@ load_rdr_log_rule() { RDR_IF="$(grep "^[[:space:]]*${bastille_network_pf_ext_if}[[:space:]]*=" ${bastille_pf_conf} | awk -F'"' '{print $2}')" RDR_SRC="any" RDR_DST="any" -OPTION="0" RDR_INET="dual" OPTION_IF=0 OPTION_SRC=0 @@ -260,7 +259,7 @@ while [ "$#" -gt 0 ]; do if [ -z "${2}" ] || [ -z "${3}" ]; then usage elif ifconfig | grep -owq "inet ${2}"; then - OPTION_DST=1 + OPTION_DST=1 RDR_DST="${2}" shift 2 else @@ -279,9 +278,9 @@ while [ "$#" -gt 0 ]; do fi ;; list) - if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ];then + if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ]; then error_exit "Command \"${1}\" cannot be used with options." - elif [ -n "${2}" ]; then + elif [ -n "${2}" ]; then usage elif [ "${TARGET}" = 'ALL' ]; then for JAIL_NAME in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do @@ -295,7 +294,7 @@ while [ "$#" -gt 0 ]; do shift ;; clear) - if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ];then + if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ]; then error_exit "Command \"${1}\" cannot be used with options." elif [ -n "${2}" ]; then usage @@ -311,7 +310,7 @@ while [ "$#" -gt 0 ]; do shift ;; reset) - if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ];then + if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ]; then error_exit "Command \"${1}\" cannot be used with options." elif [ -n "${2}" ]; then usage @@ -335,7 +334,7 @@ while [ "$#" -gt 0 ]; do tcp|udp) if [ $# -lt 3 ]; then usage - elif [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] && [ "${OPTION_INET_TYPE}" -ne 1 ];then + elif [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] && [ "${OPTION_INET_TYPE}" -ne 1 ]; then error_exit "[-t|--type] must be set when using [-s|--source] or [-d|--destination]" elif [ $# -eq 3 ]; then check_jail_validity From 6f0d318fd3356e468acc6dd74df8713568dcc8dc Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 6 Jan 2025 18:43:22 -0700 Subject: [PATCH 62/76] rdr: Add debug option, code cleanup --- usr/local/share/bastille/rdr.sh | 261 +++++++++++++++----------------- 1 file changed, 122 insertions(+), 139 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 7e46390f..2f4fb6cd 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -32,82 +32,52 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_notify "Usage: bastille rdr TARGET [option(s)] [clear|reset|list|(tcp|udp)] host_port jail_port [log ['(' logopts ')'] ] )]" - + error_notify "Usage: bastille rdr [option(s)] TARGET [clear|reset|list|(tcp|udp)] HOST_PORT JAIL_PORT [log ['(' logopts ')'] ] )]" cat << EOF Options: - -i | --interface [interface] | -- Set the interface to create the rdr rule on. Useful if you have multiple interfaces. - -s | --source [source ip] | -- Limit rdr to a source IP. Useful to only allow access from a certian IP or subnet. - -d | --destination [destination ip] | -- Limit rdr to a destination IP. Useful if you have multiple IPs on one interface. - -t | --type [ipv4|ipv6] | -- Specify IP type. Must be used if -s or -d are used. Defaults to both. + -d | --destination [destination ip] Limit rdr to a destination IP. Useful if you have multiple IPs on one interface. + -i | --interface [interface] Set the interface to create the rdr rule on. Useful if you have multiple interfaces. + -s | --source [source ip] Limit rdr to a source IP. Useful to only allow access from a certian IP or subnet. + -t | --type [ipv4|ipv6] Specify IP type. Must be used if -s or -d are used. Defaults to both. + -x | --debug Enable debug mode. EOF exit 1 } -# Handle special-case commands first. -case "$1" in - help|-h|--help) - usage - ;; -esac - -if [ $# -lt 2 ]; then - usage -fi - -bastille_root_check - -TARGET="${1}" -JAIL_NAME="" -JAIL_IP="" -JAIL_IP6="" -shift - check_jail_validity() { - # Can only redirect to single jail - if [ "${TARGET}" = 'ALL' ]; then - error_exit "Can only redirect to a single jail." - fi - # Check if jail name is valid - JAIL_NAME=$(/usr/sbin/jls -j "${TARGET}" name 2>/dev/null) - if [ -z "${JAIL_NAME}" ]; then - error_exit "Jail not found: ${TARGET}" - fi - - # Check if jail ip4 address (ip4.addr) is valid (non-VNET only) - if [ "$(bastille config $TARGET get vnet)" != 'enabled' ]; then - JAIL_IP=$(/usr/sbin/jls -j "${TARGET}" ip4.addr 2>/dev/null) - if [ -z "${JAIL_IP}" ] || [ "${JAIL_IP}" = "-" ]; then - error_exit "Jail IP not found: ${TARGET}" + if [ "$( bastille config ${TARGET} get vnet )" != 'enabled' ]; then + _ip4_interfaces="$(bastille config ${TARGET} get ip4.addr | sed 's/,/ /g')" + _ip6_interfaces="$(bastille config ${TARGET} get ip6.addr | sed 's/,/ /g')" + # Check if jail ip4.addr is valid (non-VNET only) + if [ "${_ip4_interfaces}" != "not set" ] && [ "${_ip4_interfaces}" != "disable" ]; then + JAIL_IP="$(bastille config ${TARGET} get ip4.addr | awk '{print $1}' | awk -F"|" '{print $2}')" fi - fi - - # Check if jail ip6 address (ip6.addr) is valid (non-VNET only) - if [ "$(bastille config $TARGET get vnet)" != 'enabled' ]; then - if [ "$(bastille config $TARGET get ip6)" != 'disable' ] && [ "$(bastille config $TARGET get ip6)" != 'not set' ]; then - JAIL_IP6=$(/usr/sbin/jls -j "${TARGET}" ip6.addr 2>/dev/null) + # Check if jail ip6.addr is valid (non-VNET only) + if [ "${_ip6_interfaces}" != "not set" ] && [ "${_ip6_interfaces}" != "disable" ]; then + JAIL_IP6="$(bastille config ${TARGET} get ip6.addr | awk '{print $1}' | awk -F"|" '{print $2}')" fi + else + error_exit "VNET jails do not support rdr." fi - + # Check if rdr-anchor is defined in pf.conf if ! (pfctl -sn | grep rdr-anchor | grep 'rdr/\*' >/dev/null); then error_exit "rdr-anchor not found in pf.conf" fi } -# function: check if IP is valid check_rdr_ip_validity() { - local ip4="$1" - local ip6="$(echo "${ip4}" | grep -E '^(([a-fA-F0-9:]+$)|([a-fA-F0-9:]+\/[0-9]{1,3}$)|SLAAC)')" + local ip="${1}" + local ip6="$( echo "${ip}" | grep -E '^(([a-fA-F0-9:]+$)|([a-fA-F0-9:]+\/[0-9]{1,3}$)|SLAAC)' )" if [ -n "${ip6}" ]; then info "Valid: (${ip6})." else local IFS - if echo "${ip4}" | grep -Eq '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))?$'; then - TEST_IP=$(echo "${ip4}" | cut -d / -f1) + if echo "${ip}" | grep -Eq '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))?$'; then + TEST_IP=$(echo "${ip}" | cut -d / -f1) IFS=. set ${TEST_IP} for quad in 1 2 3 4; do @@ -115,14 +85,13 @@ check_rdr_ip_validity() { error_exit "Invalid: (${TEST_IP})" fi done - info "Valid: (${ip4})." + info "Valid: (${ip})." else - error_exit "Invalid: (${ip4})." + error_exit "Invalid: (${ip})." fi fi } -# function: write rule to rdr.conf persist_rdr_rule() { local inet="${1}" local if="${2}" @@ -131,8 +100,8 @@ persist_rdr_rule() { local proto="${5}" local host_port="${6}" local jail_port="${7}" - if ! grep -qs "$inet $if $src $dst $proto $host_port $jail_port" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then - echo "$inet $if $src $dst $proto $host_port $jail_port" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" + if ! grep -qs "$inet $if $src $dst $proto $host_port $jail_port" "${bastille_jailsdir}/${TARGET}/rdr.conf"; then + echo "$inet $if $src $dst $proto $host_port $jail_port" >> "${bastille_jailsdir}/${TARGET}/rdr.conf" fi } @@ -146,12 +115,11 @@ persist_rdr_log_rule() { local jail_port="${7}" shift 7; log=$@; - if ! grep -qs "$inet $if $src $dst $proto $host_port $jail_port $log" "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf"; then - echo "$inet $if $src $dst $proto $host_port $jail_port $log" >> "${bastille_jailsdir}/${JAIL_NAME}/rdr.conf" + if ! grep -qs "$inet $if $src $dst $proto $host_port $jail_port $log" "${bastille_jailsdir}/${TARGET}/rdr.conf"; then + echo "$inet $if $src $dst $proto $host_port $jail_port $log" >> "${bastille_jailsdir}/${TARGET}/rdr.conf" fi } -# function: load rdr rule via pfctl load_rdr_rule() { local inet="${1}" local if_name="${2}" @@ -162,30 +130,31 @@ load_rdr_rule() { local host_port="${6}" local jail_port="${7}" # Create IPv4 rdr rule - if [ "${inet}" = "ipv4" ] || [ "${inet}" = "dual" ]; then - if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn 2>/dev/null; + # shellcheck disable=SC2193 + if { [ "${inet}" = "ipv4" ] || [ "${inet}" = "dual" ]; } then + if ! ( pfctl -a "rdr/${TARGET}" -Psn 2>/dev/null; printf '%s\nrdr pass on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ - | pfctl -a "rdr/${JAIL_NAME}" -f-; then + | pfctl -a "rdr/${TARGET}" -f-; then error_exit "Failed to create IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else - info "[${JAIL_NAME}]:" + info "[${TARGET}]:" echo "IPv4 ${proto}/${host_port}:${jail_port} on ${if_name}" fi fi # Create IPv6 rdr rule (if ip6.addr is enabled) - if [ -n "$JAIL_IP6" ] && [ "${inet}" = "ipv6" ] || [ "${inet}" = "dual" ]; then - if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; + # shellcheck disable=SC2193 + if [ -n "${JAIL_IP6}" ] && { [ "${inet}" = "ipv6" ] || [ "${inet}" = "dual" ]; } then + if ! ( pfctl -a "rdr/${TARGET}" -Psn; printf '%s\nrdr pass on $%s inet6 proto %s from %s to %s port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ - | pfctl -a "rdr/${JAIL_NAME}" -f-; then + | pfctl -a "rdr/${TARGET}" -f-; then error_exit "Failed to create IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else - info "[${JAIL_NAME}]:" - echo "IPv6 ${proto}/${host_port}:${jail_port} on ${if_name}" + info "[${TARGET}]:" + echo "IPv6 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" fi fi } -# function: load rdr rule with log via pfctl load_rdr_log_rule() { local inet="${1}" local if_name="${2}" @@ -198,30 +167,32 @@ load_rdr_log_rule() { shift 7; log=$@ # Create IPv4 rule with log - if { [ "${inet}" = "ipv4" ] || [ "${inet}" = "dual" ]; }; then - if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; + # shellcheck disable=SC2193 + if { [ "${inet}" = "ipv4" ] || [ "${inet}" = "dual" ]; } then + if ! ( pfctl -a "rdr/${TARGET}" -Psn; printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ - | pfctl -a "rdr/${JAIL_NAME}" -f-; then + | pfctl -a "rdr/${TARGET}" -f-; then error_exit "Failed to create logged IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else - info "[${JAIL_NAME}]:" - echo "IPv4 ${proto}/${host_port}:${jail_port} on ${if_name}" + info "[${TARGET}]:" + echo "IPv4 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" fi fi # Create IPv6 rdr rule with log (if ip6.addr is enabled) - if [ -n "$JAIL_IP6" ] && { [ "${inet}" = "ipv6" ] || [ "${inet}" = "dual" ]; };then - if ! ( pfctl -a "rdr/${JAIL_NAME}" -Psn; + # shellcheck disable=SC2193 + if [ -n "${JAIL_IP6}" ] && { [ "${inet}" = "ipv6" ] || [ "${inet}" = "dual" ]; } then + if ! ( pfctl -a "rdr/${TARGET}" -Psn; printf '%s\nrdr pass %s on $%s inet6 proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ - | pfctl -a "rdr/${JAIL_NAME}" -f-; then + | pfctl -a "rdr/${TARGET}" -f-; then error_exit "Failed to create logged IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else - info "[${JAIL_NAME}]:" - echo "IPv6 ${proto}/${host_port}:${jail_port} on ${if_name}" + info "[${TARGET}]:" + echo "IPv6 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" fi fi } -# Set defaults +# Handle options. RDR_IF="$(grep "^[[:space:]]*${bastille_network_pf_ext_if}[[:space:]]*=" ${bastille_pf_conf} | awk -F'"' '{print $2}')" RDR_SRC="any" RDR_DST="any" @@ -230,14 +201,13 @@ OPTION_IF=0 OPTION_SRC=0 OPTION_DST=0 OPTION_INET_TYPE=0 - -# Check for options while [ "$#" -gt 0 ]; do - case "$1" in + case "${1}" in + -h|--help|help) + usage + ;; -i|--interface) - if [ -z "${2}" ] || [ -z "${3}" ]; then - usage - elif ifconfig | grep -owq "${2}:"; then + if ifconfig | grep -owq "${2}:"; then OPTION_IF=1 RDR_IF="${2}" shift 2 @@ -246,19 +216,13 @@ while [ "$#" -gt 0 ]; do fi ;; -s|--source) - if [ -z "${2}" ] || [ -z "${3}" ]; then - usage - else - check_rdr_ip_validity "${2}" - OPTION_SRC=1 - RDR_SRC="${2}" - shift 2 - fi + check_rdr_ip_validity "${2}" + OPTION_SRC=1 + RDR_SRC="${2}" + shift 2 ;; -d|--destination) - if [ -z "${2}" ] || [ -z "${3}" ]; then - usage - elif ifconfig | grep -owq "inet ${2}"; then + if ifconfig | grep -owq "inet ${2}"; then OPTION_DST=1 RDR_DST="${2}" shift 2 @@ -267,92 +231,113 @@ while [ "$#" -gt 0 ]; do fi ;; -t|--type) - if [ -z "${2}" ] || [ -z "${3}" ]; then - usage - elif [ "${2}" != "ipv4" ] && [ "${2}" != "ipv6" ]; then - usage + if [ "${2}" != "ipv4" ] && [ "${2}" != "ipv6" ]; then + error_exit "[-t|--type] must be [ipv4|ipv6]" else OPTION_INET_TYPE=1 RDR_INET="${2}" shift 2 fi ;; + -*) + error_exit "Unknown option: \"${1}\"" + ;; + *) + break + ;; + esac +done + +if [ "$#" -lt 2 ]; then + usage +fi + +TARGET="${1}" +JAIL_IP="" +JAIL_IP6="" +shift + +bastille_root_check +set_target_single "${TARGET}" + +while [ "$#" -gt 0 ]; do + case "${1}" in list) - if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ]; then + if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ];then error_exit "Command \"${1}\" cannot be used with options." - elif [ -n "${2}" ]; then + elif [ -n "${2}" ]; then usage elif [ "${TARGET}" = 'ALL' ]; then - for JAIL_NAME in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do - echo "${JAIL_NAME} redirects:" - pfctl -a "rdr/${JAIL_NAME}" -Psn 2>/dev/null + for _jail in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do + echo "${_jail} redirects:" + pfctl -a "rdr/${_jail}" -Psn 2>/dev/null done else check_jail_validity - pfctl -a "rdr/${JAIL_NAME}" -Psn 2>/dev/null + pfctl -a "rdr/${TARGET}" -Psn 2>/dev/null fi shift ;; clear) - if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ]; then + if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ];then error_exit "Command \"${1}\" cannot be used with options." - elif [ -n "${2}" ]; then + elif [ -n "${2}" ]; then usage elif [ "${TARGET}" = 'ALL' ]; then - for JAIL_NAME in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do - echo "${JAIL_NAME} redirects:" - pfctl -a "rdr/${JAIL_NAME}" -Fn + for _jail in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do + echo "${_jail} redirects:" + pfctl -a "rdr/${_jail}" -Fn done else check_jail_validity - pfctl -a "rdr/${JAIL_NAME}" -Fn + pfctl -a "rdr/${TARGET}" -Fn fi shift ;; reset) - if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ]; then + if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ];then error_exit "Command \"${1}\" cannot be used with options." - elif [ -n "${2}" ]; then + elif [ -n "${2}" ]; then usage elif [ "${TARGET}" = 'ALL' ]; then - for JAIL_NAME in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do - echo "${JAIL_NAME} redirects:" - pfctl -a "rdr/${JAIL_NAME}" -Fn - if rm -f "${bastille_jailsdir}"/"${JAIL_NAME}"/rdr.conf; then - info "[${JAIL_NAME}]: rdr.conf removed" - fi + for _jail in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do + echo "${_jail} redirects:" + pfctl -a "rdr/${_jail}" -Fn + if rm -f "${bastille_jailsdir}"/"${_jail}"/rdr.conf; then + info "[${_jail}]: rdr.conf removed" + fi done else check_jail_validity - pfctl -a "rdr/${JAIL_NAME}" -Fn - if rm -f "${bastille_jailsdir}"/"${JAIL_NAME}"/rdr.conf; then - info "[${JAIL_NAME}]: rdr.conf removed" - fi + pfctl -a "rdr/${TARGET}" -Fn + if rm -f "${bastille_jailsdir}"/"${_jail}"/rdr.conf; then + info "[${TARGET}]: rdr.conf removed" + fi fi shift ;; tcp|udp) - if [ $# -lt 3 ]; then + if [ "$#" -lt 3 ]; then usage - elif [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] && [ "${OPTION_INET_TYPE}" -ne 1 ]; then + elif [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] && [ "${OPTION_INET_TYPE}" -ne 1 ];then error_exit "[-t|--type] must be set when using [-s|--source] or [-d|--destination]" - elif [ $# -eq 3 ]; then + elif [ "$#" -eq 3 ]; then check_jail_validity persist_rdr_rule $RDR_INET $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 load_rdr_rule $RDR_INET $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 shift "$#" else - case "$4" in + case "${4}" in log) proto=$1 host_port=$2 jail_port=$3 shift 3 - if [ $# -gt 3 ]; then + if [ "$#" -gt 3 ]; then for last in "$@"; do true done - if [ "$2" = "(" ] && [ "$last" = ")" ] ; then + if [ "${2}" = "(" ] && [ "${last}" = ")" ] ; then check_jail_validity persist_rdr_log_rule $RDR_INET $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" load_rdr_log_rule $RDR_INET $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" @@ -376,23 +361,21 @@ while [ "$#" -gt 0 ]; do fi ;; *) - if [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ] || [ "${OPTION_IF}" -eq 1 ]; then - usage - elif [ "${1}" = "dual" ] || [ "${1}" = "ipv4" ] || [ "${1}" = "ipv6" ]; then + if [ "${1}" = "dual" ] || [ "${1}" = "ipv4" ] || [ "${1}" = "ipv6" ]; then RDR_INET="${1}" else usage fi - if [ $# -eq 7 ] && [ "${5}" = "tcp" ] || [ "${5}" = "udp" ]; then + if [ "$#" -eq 7 ] && { [ "${5}" = "tcp" ] || [ "${5}" = "udp" ]; } then check_jail_validity persist_rdr_rule "$@" load_rdr_rule "$@" - shift $# - elif [ $# -ge 8 ] && [ "${8}" = "log" ]; then + shift "$#" + elif [ "$#" -ge 8 ] && [ "${8}" = "log" ]; then check_jail_validity persist_rdr_log_rule "$@" load_rdr_log_rule "$@" - shift $# + shift "$#" else usage fi From ada6c2d61c7835b573a24fb84af2849c3a1b0d8b Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 7 Jan 2025 17:03:00 -0700 Subject: [PATCH 63/76] rdr: correctly print default interface IP --- usr/local/share/bastille/rdr.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 2f4fb6cd..225e62a2 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -53,11 +53,11 @@ check_jail_validity() { _ip6_interfaces="$(bastille config ${TARGET} get ip6.addr | sed 's/,/ /g')" # Check if jail ip4.addr is valid (non-VNET only) if [ "${_ip4_interfaces}" != "not set" ] && [ "${_ip4_interfaces}" != "disable" ]; then - JAIL_IP="$(bastille config ${TARGET} get ip4.addr | awk '{print $1}' | awk -F"|" '{print $2}')" + JAIL_IP="$(echo ${_ip4_interfaces} | awk '{print $1}' | awk -F"|" '{print $2}')" fi # Check if jail ip6.addr is valid (non-VNET only) if [ "${_ip6_interfaces}" != "not set" ] && [ "${_ip6_interfaces}" != "disable" ]; then - JAIL_IP6="$(bastille config ${TARGET} get ip6.addr | awk '{print $1}' | awk -F"|" '{print $2}')" + JAIL_IP6="$(echo ${_ip6_interfaces} | awk '{print $1}' | awk -F"|" '{print $2}')" fi else error_exit "VNET jails do not support rdr." From a169beb073ce6ac933b331c4935d1d12bb7ee7b4 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 7 Jan 2025 22:55:36 -0700 Subject: [PATCH 64/76] rdr: do not allow rules to be duplicated between jails --- usr/local/share/bastille/rdr.sh | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 225e62a2..a7b57de2 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -47,7 +47,6 @@ EOF } check_jail_validity() { - if [ "$( bastille config ${TARGET} get vnet )" != 'enabled' ]; then _ip4_interfaces="$(bastille config ${TARGET} get ip4.addr | sed 's/,/ /g')" _ip6_interfaces="$(bastille config ${TARGET} get ip6.addr | sed 's/,/ /g')" @@ -92,6 +91,19 @@ check_rdr_ip_validity() { fi } +validate_rdr_rule() { + local if="${1}" + local src="${2}" + local dst="${3}" + local proto="${4}" + local host_port="${5}" + local jail_port="${6}" + if grep -qs "$if $src $dst $proto $host_port $jail_port" "${bastille_jailsdir}/${TARGET}/rdr.conf"; then + error_notify "Error: Ports already in use on this interface." + error_exit "See 'bastille list ports' or 'bastille rdr TARGET clear'." + fi +} + persist_rdr_rule() { local inet="${1}" local if="${2}" @@ -239,6 +251,10 @@ while [ "$#" -gt 0 ]; do shift 2 fi ;; + -x|--debug) + enable_debug + shift + ;; -*) error_exit "Unknown option: \"${1}\"" ;; @@ -323,6 +339,7 @@ while [ "$#" -gt 0 ]; do error_exit "[-t|--type] must be set when using [-s|--source] or [-d|--destination]" elif [ "$#" -eq 3 ]; then check_jail_validity + validate_rdr_rule $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 persist_rdr_rule $RDR_INET $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 load_rdr_rule $RDR_INET $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 shift "$#" @@ -339,6 +356,7 @@ while [ "$#" -gt 0 ]; do done if [ "${2}" = "(" ] && [ "${last}" = ")" ] ; then check_jail_validity + validate_rdr_rule $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 persist_rdr_log_rule $RDR_INET $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" load_rdr_log_rule $RDR_INET $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" shift $# @@ -347,6 +365,7 @@ while [ "$#" -gt 0 ]; do fi elif [ $# -eq 1 ]; then check_jail_validity + validate_rdr_rule $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 persist_rdr_log_rule $RDR_INET $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" load_rdr_log_rule $RDR_INET $RDR_IF $RDR_SRC $RDR_DST $proto $host_port $jail_port "$@" shift 1 @@ -368,11 +387,13 @@ while [ "$#" -gt 0 ]; do fi if [ "$#" -eq 7 ] && { [ "${5}" = "tcp" ] || [ "${5}" = "udp" ]; } then check_jail_validity + validate_rdr_rule $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 persist_rdr_rule "$@" load_rdr_rule "$@" shift "$#" elif [ "$#" -ge 8 ] && [ "${8}" = "log" ]; then check_jail_validity + validate_rdr_rule $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 persist_rdr_log_rule "$@" load_rdr_log_rule "$@" shift "$#" From b7c861f6f921bca5893006e479e24922dae17323 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 7 Jan 2025 22:58:54 -0700 Subject: [PATCH 65/76] rdr: clear > reset notify on duplicate jail rules --- usr/local/share/bastille/rdr.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index a7b57de2..0c323156 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -100,7 +100,7 @@ validate_rdr_rule() { local jail_port="${6}" if grep -qs "$if $src $dst $proto $host_port $jail_port" "${bastille_jailsdir}/${TARGET}/rdr.conf"; then error_notify "Error: Ports already in use on this interface." - error_exit "See 'bastille list ports' or 'bastille rdr TARGET clear'." + error_exit "See 'bastille list ports' or 'bastille rdr TARGET reset'." fi } From e5f56558287f2f94a7ffa107d29f8ccc737dd6fc Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 7 Jan 2025 23:15:02 -0700 Subject: [PATCH 66/76] rdr: Allow only a single target --- usr/local/share/bastille/rdr.sh | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 0c323156..0361a2fc 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -100,7 +100,7 @@ validate_rdr_rule() { local jail_port="${6}" if grep -qs "$if $src $dst $proto $host_port $jail_port" "${bastille_jailsdir}/${TARGET}/rdr.conf"; then error_notify "Error: Ports already in use on this interface." - error_exit "See 'bastille list ports' or 'bastille rdr TARGET reset'." + error_exit "See 'bastille list ports' or 'bastille rdr TARGET clear'." fi } @@ -283,11 +283,6 @@ while [ "$#" -gt 0 ]; do error_exit "Command \"${1}\" cannot be used with options." elif [ -n "${2}" ]; then usage - elif [ "${TARGET}" = 'ALL' ]; then - for _jail in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do - echo "${_jail} redirects:" - pfctl -a "rdr/${_jail}" -Psn 2>/dev/null - done else check_jail_validity pfctl -a "rdr/${TARGET}" -Psn 2>/dev/null @@ -299,14 +294,10 @@ while [ "$#" -gt 0 ]; do error_exit "Command \"${1}\" cannot be used with options." elif [ -n "${2}" ]; then usage - elif [ "${TARGET}" = 'ALL' ]; then - for _jail in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do - echo "${_jail} redirects:" - pfctl -a "rdr/${_jail}" -Fn - done else check_jail_validity - pfctl -a "rdr/${TARGET}" -Fn + echo "${_jail} redirects:" + pfctl -a "rdr/${_jail}" -Fn fi shift ;; @@ -315,19 +306,12 @@ while [ "$#" -gt 0 ]; do error_exit "Command \"${1}\" cannot be used with options." elif [ -n "${2}" ]; then usage - elif [ "${TARGET}" = 'ALL' ]; then - for _jail in $(ls "${bastille_jailsdir}" | sed "s/\n//g"); do - echo "${_jail} redirects:" - pfctl -a "rdr/${_jail}" -Fn - if rm -f "${bastille_jailsdir}"/"${_jail}"/rdr.conf; then - info "[${_jail}]: rdr.conf removed" - fi - done else check_jail_validity - pfctl -a "rdr/${TARGET}" -Fn - if rm -f "${bastille_jailsdir}"/"${_jail}"/rdr.conf; then - info "[${TARGET}]: rdr.conf removed" + echo "${_jail} redirects:" + pfctl -a "rdr/${_jail}" -Fn + if rm -f "${bastille_jailsdir}/${_jail}/rdr.conf"; then + info "[${_jail}]: rdr.conf removed" fi fi shift From 2da817e0d435475741d45b97e62c720d49058a6d Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 7 Jan 2025 23:16:35 -0700 Subject: [PATCH 67/76] list: use list command for jail list --- usr/local/share/bastille/list.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/usr/local/share/bastille/list.sh b/usr/local/share/bastille/list.sh index 0a6b6b3c..085ba0cb 100644 --- a/usr/local/share/bastille/list.sh +++ b/usr/local/share/bastille/list.sh @@ -224,11 +224,11 @@ list_import(){ list_ports(){ if [ -d "${bastille_jailsdir}" ]; then - JAIL_LIST=$(ls "${bastille_jailsdir}" | sed "s/\n//g") - for _JAIL in ${JAIL_LIST}; do - if [ -f "${bastille_jailsdir}/${_JAIL}/rdr.conf" ]; then - _PORTS="$(cat "${bastille_jailsdir}"/"${_JAIL}"/rdr.conf)" - info "[${_JAIL}]:" + JAIL_LIST="$(bastille list jails)" + for _jail in ${JAIL_LIST}; do + if [ -f "${bastille_jailsdir}/${_jail}/rdr.conf" ]; then + _PORTS="$(cat ${bastille_jailsdir}/${_jail}/rdr.conf)" + info "[${_jail}]:" echo "${_PORTS}" fi done From eee99a3b799a9abcce50091eb43baa86efb6969f Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 8 Jan 2025 10:25:15 -0700 Subject: [PATCH 68/76] rdr: fix _jail > TARGET + alphabetical option order --- usr/local/share/bastille/rdr.sh | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 0361a2fc..2af4bf54 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -47,6 +47,8 @@ EOF } check_jail_validity() { + + # Validate jail network type and set IP4/6 if [ "$( bastille config ${TARGET} get vnet )" != 'enabled' ]; then _ip4_interfaces="$(bastille config ${TARGET} get ip4.addr | sed 's/,/ /g')" _ip6_interfaces="$(bastille config ${TARGET} get ip6.addr | sed 's/,/ /g')" @@ -218,6 +220,15 @@ while [ "$#" -gt 0 ]; do -h|--help|help) usage ;; + -d|--destination) + if ifconfig | grep -owq "inet ${2}"; then + OPTION_DST=1 + RDR_DST="${2}" + shift 2 + else + error_exit "${2} is not an IP on this system." + fi + ;; -i|--interface) if ifconfig | grep -owq "${2}:"; then OPTION_IF=1 @@ -233,15 +244,6 @@ while [ "$#" -gt 0 ]; do RDR_SRC="${2}" shift 2 ;; - -d|--destination) - if ifconfig | grep -owq "inet ${2}"; then - OPTION_DST=1 - RDR_DST="${2}" - shift 2 - else - error_exit "${2} is not an IP on this system." - fi - ;; -t|--type) if [ "${2}" != "ipv4" ] && [ "${2}" != "ipv6" ]; then error_exit "[-t|--type] must be [ipv4|ipv6]" @@ -296,8 +298,8 @@ while [ "$#" -gt 0 ]; do usage else check_jail_validity - echo "${_jail} redirects:" - pfctl -a "rdr/${_jail}" -Fn + echo "${TARGET} redirects:" + pfctl -a "rdr/${TARGET}" -Fn fi shift ;; @@ -308,10 +310,10 @@ while [ "$#" -gt 0 ]; do usage else check_jail_validity - echo "${_jail} redirects:" - pfctl -a "rdr/${_jail}" -Fn + echo "${TARGET} redirects:" + pfctl -a "rdr/${TARGET}" -Fn if rm -f "${bastille_jailsdir}/${_jail}/rdr.conf"; then - info "[${_jail}]: rdr.conf removed" + info "[${TARGET}]: rdr.conf removed" fi fi shift From 685c8f9079d45c524ed3e177e66f155298df69a4 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 8 Jan 2025 10:31:47 -0700 Subject: [PATCH 69/76] doc: rdr with multiple interfaces --- docs/chapters/subcommands/rdr.rst | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index b3be77f2..2a4f9927 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -2,7 +2,7 @@ rdr === -bastille rdr allows you to configure dynamic rdr rules for your containers +`bastille rdr` allows you to configure dynamic rdr rules for your containers without modifying pf.conf (assuming you are using the `bastille0` interface for a private network and have enabled `rdr-anchor 'rdr/*'` in /etc/pf.conf as described in the Networking section). @@ -17,11 +17,11 @@ specify the interface they run on in rc.conf (or other config files) Usage: bastille rdr TARGET [option(s)] [clear|reset|list|(tcp|udp host_port jail_port [log ['(' logopts ')'] ] )] Options: - -i | --interface [interface] | -- Set the interface to create the rdr rule on. Useful if you have multiple interfaces. - -s | --source [source ip] | -- Limit rdr to a source IP. Useful to only allow access from a certian IP or subnet. - -d | --destination [destination ip] | -- Limit rdr to a destination IP. Useful if you have multiple IPs on one interface. - -t | --type [ipv4|ipv6] | -- Specify IP type. Must be used if -s or -d are used. Defaults to both. - + -i | --interface [interface] Set the interface to create the rdr rule on. Useful if you have multiple interfaces. + -s | --source [source ip] Limit rdr to a source IP. Useful to only allow access from a certian IP or subnet. + -d | --destination [destination ip] Limit rdr to a destination IP. Useful if you have multiple IPs on one interface. + -t | --type [ipv4|ipv6] Specify IP type. Must be used if -s or -d are used. Defaults to both. + -x | --debug Enable debug mode. # bastille rdr dev1 tcp 2001 22 [jail1]: @@ -41,11 +41,12 @@ specify the interface they run on in rc.conf (or other config files) # bastille rdr dev1 clear nat cleared -The `rdr` command includes 3 additional options: +The `rdr` command includes 4 additional options: - **-i** | Set a non-default interface on which to create the `rdr` rule. - **-s** | Limit the source IP on the `rdr` rule. - **-d** | Limit the destination IP on the `rdr` rule. +- **-t** | Specify network type. Can be "ipv4" or "ipv6". Default is "dual". .. code-block:: shell @@ -72,3 +73,6 @@ The `rdr` command includes 3 additional options: rdr pass on vtnet0 inet proto tcp from any to 192.168.0.45 port = 9000 -> 10.17.89.1 port 9000 The options can be used together, as seen above. + +If you have multiple interfaces assigned to your jail, `bastille rdr` will +only redirect using the default one. From 780f93ca1668820d4463330b20e6c81c21a066ef Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 16:07:25 -0700 Subject: [PATCH 70/76] rdr: spacing fix and usage message remove additional ] --- usr/local/share/bastille/rdr.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 4dc4b1a5..0320e19f 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -34,7 +34,7 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_notify "Usage: bastille rdr [option(s)] TARGET [clear|reset|list|(tcp|udp)] HOST_PORT JAIL_PORT [log ['(' logopts ')'] ] )]" + error_notify "Usage: bastille rdr [option(s)] TARGET [clear|reset|list|(tcp|udp)] HOST_PORT JAIL_PORT [log ['(' logopts ')'] ]" cat << EOF Options: @@ -49,7 +49,6 @@ EOF } check_jail_validity() { - # Validate jail network type and set IP4/6 if [ "$( bastille config ${TARGET} get vnet )" != 'enabled' ]; then _ip4_interfaces="$(bastille config ${TARGET} get ip4.addr | sed 's/,/ /g')" From ba50618b51ca5f49e9c0b0997d4691f82ade75b4 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 16:09:29 -0700 Subject: [PATCH 71/76] docs: update rdr docs with code block for options --- docs/chapters/subcommands/rdr.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index 2a4f9927..72a9eefa 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -43,10 +43,12 @@ specify the interface they run on in rc.conf (or other config files) The `rdr` command includes 4 additional options: -- **-i** | Set a non-default interface on which to create the `rdr` rule. -- **-s** | Limit the source IP on the `rdr` rule. -- **-d** | Limit the destination IP on the `rdr` rule. -- **-t** | Specify network type. Can be "ipv4" or "ipv6". Default is "dual". +.. code-block:: shell + + -i | --interface [interface] Set the interface to create the rdr rule on. Useful if you have multiple interfaces. + -s | --source [source ip] Limit rdr to a source IP. Useful to only allow access from a certian IP or subnet. + -d | --destination [destination ip] Limit rdr to a destination IP. Useful if you have multiple IPs on one interface. + -t | --type [ipv4|ipv6] Specify IP type. Must be used if -s or -d are used. Defaults to both. .. code-block:: shell From 0696152aa4d2e19ffc16423918a5187706219e81 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 16:13:29 -0700 Subject: [PATCH 72/76] docs: rdr, fix info return block --- docs/chapters/subcommands/rdr.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/chapters/subcommands/rdr.rst b/docs/chapters/subcommands/rdr.rst index 72a9eefa..262f83b8 100644 --- a/docs/chapters/subcommands/rdr.rst +++ b/docs/chapters/subcommands/rdr.rst @@ -25,14 +25,14 @@ specify the interface they run on in rc.conf (or other config files) # bastille rdr dev1 tcp 2001 22 [jail1]: - IPv4 tcp/any:2001 -> any:22 on em0 + IPv4 tcp/2001:22 on em0 # bastille rdr dev1 list rdr on em0 inet proto tcp from any to any port = 2001 -> 10.17.89.1 port 22 # bastille rdr dev1 udp 2053 53 [jail1]: - IPv4 udp/any:2001 -> any:22 on em0 + IPv4 udp/2053:53 on em0 # bastille rdr dev1 list rdr pass on em0 inet proto tcp from any to any port = 2001 -> 10.17.89.1 port 22 @@ -52,21 +52,21 @@ The `rdr` command includes 4 additional options: .. code-block:: shell - # bastille rdr dev1 -i vtnet0 udp 2001 22 + # bastille rdr dev1 -i vtnet0 udp 8000 80 [jail1]: - IPv4 tcp/any:8000 -> any:80 on vtnet0 + IPv4 tcp/8000:80 on vtnet0 # bastille rdr dev1 -s 192.168.0.1 tcp 8080 81 [jail1]: - IPv4 tcp/192.168.0.1:8080 -> any:81 on em0 + IPv4 tcp/8080:81 on em0 # bastille rdr dev1 -d 192.168.0.84 tcp 8082 82 [jail1]: - IPv4 tcp/any:8082 -> 192.168.0.84:82 on em0 + IPv4 tcp/8082:82 on em0 # bastille rdr dev1 -i vtnet0 -d 192.168.0.45 tcp 9000 9000 [jail1]: - IPv4 tcp/any:9000 -> 192.168.0.45:9000 on vtnet0 + IPv4 tcp/9000:9000 on vtnet0 # bastille rdr dev1 list rdr pass on vtnet0 inet proto udp from any to any port = 2001 -> 10.17.89.1 port 22 From cf3bb4e80939a55fda8913e8e77c85efa59114b6 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 16:14:50 -0700 Subject: [PATCH 73/76] rdr: fix echo code on IPv6 redirection --- usr/local/share/bastille/rdr.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 0320e19f..38bb303e 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -165,7 +165,7 @@ load_rdr_rule() { error_exit "Failed to create IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${TARGET}]:" - echo "IPv6 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + echo "IPv6 ${proto}/${host_port}:${jail_port} on ${if_name}" fi fi } @@ -190,7 +190,7 @@ load_rdr_log_rule() { error_exit "Failed to create logged IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${TARGET}]:" - echo "IPv4 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + echo "IPv4 ${proto}/${host_port}:${jail_port} on ${if_name}" fi fi # Create IPv6 rdr rule with log (if ip6.addr is enabled) @@ -202,7 +202,7 @@ load_rdr_log_rule() { error_exit "Failed to create logged IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else info "[${TARGET}]:" - echo "IPv6 ${proto}/${src}:${host_port} -> ${dst}:${jail_port} on ${if_name}" + echo "IPv6 ${proto}/${host_port}:${jail_port} on ${if_name}" fi fi } From 0a837ee5be6c39dc98d6065d53a5b9272ebd9f94 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 12 Jan 2025 10:42:54 -0700 Subject: [PATCH 74/76] rdr: support old style interface --- usr/local/share/bastille/rdr.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 38bb303e..f936b587 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -55,11 +55,19 @@ check_jail_validity() { _ip6_interfaces="$(bastille config ${TARGET} get ip6.addr | sed 's/,/ /g')" # Check if jail ip4.addr is valid (non-VNET only) if [ "${_ip4_interfaces}" != "not set" ] && [ "${_ip4_interfaces}" != "disable" ]; then - JAIL_IP="$(echo ${_ip4_interfaces} | awk '{print $1}' | awk -F"|" '{print $2}')" + if echo "&{_ip4_interfaces}" | grep -q "|"; then + JAIL_IP="$(echo ${_ip4_interfaces} | awk '{print $1}' | awk -F"|" '{print $2}')" + else + JAIL_IP="${_ip4_interfaces}" + fi fi # Check if jail ip6.addr is valid (non-VNET only) if [ "${_ip6_interfaces}" != "not set" ] && [ "${_ip6_interfaces}" != "disable" ]; then - JAIL_IP6="$(echo ${_ip6_interfaces} | awk '{print $1}' | awk -F"|" '{print $2}')" + if echo "&{_ip6_interfaces}" | grep -q "|"; then + JAIL_IP6="$(echo ${_ip6_interfaces} | awk '{print $1}' | awk -F"|" '{print $2}')" + else + JAIL_IP6="${_ip6_interfaces}" + fi fi else error_exit "VNET jails do not support rdr." From 254f1718c071c35a7fc76d88e11a177063764b36 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 12 Jan 2025 11:07:36 -0700 Subject: [PATCH 75/76] rdr: update error_message to say reset instead of clear --- usr/local/share/bastille/rdr.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index f936b587..2de8e259 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -111,7 +111,7 @@ validate_rdr_rule() { local jail_port="${6}" if grep -qs "$if $src $dst $proto $host_port $jail_port" "${bastille_jailsdir}/${TARGET}/rdr.conf"; then error_notify "Error: Ports already in use on this interface." - error_exit "See 'bastille list ports' or 'bastille rdr TARGET clear'." + error_exit "See 'bastille list ports' or 'bastille rdr TARGET reset'." fi } From bee05016f6a372eef2cc635feb30b9899d96cd0e Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 13 Jan 2025 08:17:54 -0700 Subject: [PATCH 76/76] rdr: trim subnet in case it is included behind ip --- usr/local/share/bastille/rdr.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 2de8e259..97897226 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -56,17 +56,17 @@ check_jail_validity() { # Check if jail ip4.addr is valid (non-VNET only) if [ "${_ip4_interfaces}" != "not set" ] && [ "${_ip4_interfaces}" != "disable" ]; then if echo "&{_ip4_interfaces}" | grep -q "|"; then - JAIL_IP="$(echo ${_ip4_interfaces} | awk '{print $1}' | awk -F"|" '{print $2}')" + JAIL_IP="$(echo ${_ip4_interfaces} | awk '{print $1}' | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" else - JAIL_IP="${_ip4_interfaces}" + JAIL_IP="$(echo ${_ip4_interfaces} | sed -E 's#/[0-9]+$##g')" fi fi # Check if jail ip6.addr is valid (non-VNET only) if [ "${_ip6_interfaces}" != "not set" ] && [ "${_ip6_interfaces}" != "disable" ]; then if echo "&{_ip6_interfaces}" | grep -q "|"; then - JAIL_IP6="$(echo ${_ip6_interfaces} | awk '{print $1}' | awk -F"|" '{print $2}')" + JAIL_IP6="$(echo ${_ip6_interfaces} | awk '{print $1}' | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" else - JAIL_IP6="${_ip6_interfaces}" + JAIL_IP6="$(echo ${_ip6_interfaces} | sed -E 's#/[0-9]+$##g')" fi fi else