From 462a019d43487041ac27e28cff954cd6496eae47 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 28 Jan 2025 17:31:51 -0700 Subject: [PATCH 01/19] create: Add ip_hostname/inherit options --- usr/local/share/bastille/create.sh | 251 ++++++++++++++--------------- 1 file changed, 118 insertions(+), 133 deletions(-) diff --git a/usr/local/share/bastille/create.sh b/usr/local/share/bastille/create.sh index bfc62d064..d20910d72 100644 --- a/usr/local/share/bastille/create.sh +++ b/usr/local/share/bastille/create.sh @@ -36,31 +36,24 @@ usage() { # Build an independent usage for the create command # If no option specified, will create a thin container by default - error_notify "Usage: bastille create [option(s)] name release ip [interface]" + error_notify "Usage: bastille create [option(s)] NAME RELEASE IP_ADDRESS [interface]" cat << EOF Options: - -M | --static-mac -- Generate a static MAC address for jail (VNET only). - -E | --empty -- Creates an empty container, intended for custom jail builds (thin/thick/linux or unsupported). - -L | --linux -- This option is intended for testing with Linux jails, this is considered experimental. - -T | --thick -- Creates a thick container, they consume more space as they are self contained and independent. - -V | --vnet -- Enables VNET, VNET containers are attached to a virtual bridge interface for connectivity. - -C | --clone -- Creates a clone container, they are duplicates of the base release, consume low space and preserves changing data. - -B | --bridge -- Enables VNET, VNET containers are attached to a specified, already existing external bridge. + -D | --dual Creates the jails with both IPv4 and IPv6 networking ('inherit' and 'ip_hostname' only). + -M | --static-mac Generate a static MAC address for jail (VNET only). + -E | --empty Creates an empty container, intended for custom jail builds (thin/thick/linux or unsupported). + -L | --linux This option is intended for testing with Linux jails, this is considered experimental. + -T | --thick Creates a thick container, they consume more space as they are self contained and independent. + -V | --vnet Enables VNET, VNET containers are attached to a virtual bridge interface for connectivity. + -C | --clone Creates a clone container, they are duplicates of the base release, consume low space and preserves changing data. + -B | --bridge Enables VNET, VNET containers are attached to a specified, already existing external bridge. EOF exit 1 } -running_jail() { - if [ -n "$(/usr/sbin/jls name | awk "/^${NAME}$/")" ]; then - error_exit "A running jail matches name." - elif [ -d "${bastille_jailsdir}/${NAME}" ]; then - error_exit "Jail: ${NAME} already created." - fi -} - validate_name() { local NAME_VERIFY=${NAME} local NAME_SANITY="$(echo "${NAME_VERIFY}" | tr -c -d 'a-zA-Z0-9-_')" @@ -74,54 +67,90 @@ validate_name() { } validate_ip() { - ipx_addr="ip4.addr" - ip="$1" - 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})." + _ip="${1}" + _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})." ipx_addr="ip6.addr" - IP6_MODE="new" else - if [ "${ip}" = "DHCP" ]; then - info "Valid: (${ip})." + if [ "${_ip}" = "inherit" ] || [ "${_ip}" = "ip_hostname" ]; then + info "Valid: (${_ip})." 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) + 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 - echo "Invalid: (${TEST_IP})" - exit 1 + error_continue "Invalid: (${TEST_IP})" fi done if ifconfig | grep -qwF "${TEST_IP}"; then warn "Warning: IP address already in use (${TEST_IP})." else - info "Valid: (${ip})." + ipx_addr="ip4.addr" + info "Valid: (${_ip})." fi else - error_exit "Invalid: (${ip})." + error_continue "Invalid: (${_ip})." fi fi fi - if echo "${ip}" | grep -qvE '(SLAAC|DHCP|0[.]0[.]0[.]0)'; then - if [ "${ipx_addr}" = "ip4.addr" ]; then - IP4_ADDR="${ip}" - IP4_DEFINITION="${ipx_addr} = ${ip};" + # Set interface value + if [ ! -f "${bastille_jail_conf}" ]; then + if [ -z "${bastille_network_loopback}" ] && [ -n "${bastille_network_shared}" ]; then + local bastille_jail_conf_interface=${bastille_network_shared} + fi + if [ -n "${bastille_network_loopback}" ] && [ -z "${bastille_network_shared}" ]; then + local bastille_jail_conf_interface=${bastille_network_loopback} + fi + if [ -n "${INTERFACE}" ]; then + local bastille_jail_conf_interface=${INTERFACE} + fi + fi + # Determine IP/Interface mode + if [ "${_ip}" = "inherit" ]; then + if [ -n "${DUAL_STACK}" ]; then + IP4_DEFINITION="ip4 = ${_ip};" + IP6_DEFINITION="ip6 = ${_ip};" + IP6_MODE="new" else - IP6_ADDR="${ip}" - IP6_DEFINITION="${ipx_addr} = ${ip};" + IP4_DEFINITION="ip4 = ${_ip};" + IP6_DEFINITION="" + IP6_MODE="disable" + fi + elif [ "${_ip}" = "ip_hostname" ]; then + if [ -n "${DUAL_STACK}" ]; then + IP_HOSTNAME="${_ip}" + IP4_DEFINITION="${IP_HOSTNAME};" + IP6_DEFINITION="${IP_HOSTNAME};" + IP6_MODE="new" + else + IP_HOSTNAME="${_ip}" + IP4_DEFINITION="${IP_HOSTNAME};" + IP6_DEFINITION="" + IP6_MODE="disable" + fi + elif echo "${_ip}" | grep -qvE '(SLAAC|DHCP|0[.]0[.]0[.]0)'; then + if [ "${ipx_addr}" = "ip4.addr" ]; then + IP4_ADDR="${_ip}" + IP4_DEFINITION="${ipx_addr} = ${bastille_jail_conf_interface}|${_ip};" + elif [ "${ipx_addr}" = "ip6.addr" ]; then + IP6_ADDR="${_ip}" + IP6_DEFINITION="${ipx_addr} = ${bastille_jail_conf_interface}|${_ip};" + IP6_MODE="new" fi fi } + validate_ips() { IP6_MODE="disable" IP4_DEFINITION="" IP6_DEFINITION="" IP4_ADDR="" IP6_ADDR="" + IP_HOSTNAME="" for ip in ${IP}; do validate_ip "${ip}" done @@ -170,15 +199,10 @@ EOF } generate_jail_conf() { - if [ "$(sysctl -n security.jail.jailed)" -eq 1 ]; then - devfs_ruleset_value=0 - else - devfs_ruleset_value=4 - fi cat << EOF > "${bastille_jail_conf}" ${NAME} { + devfs_ruleset = 4; enforce_statfs = 2; - devfs_ruleset = ${devfs_ruleset_value}; exec.clean; exec.consolelog = ${bastille_jail_log}; exec.start = '/bin/sh /etc/rc'; @@ -190,7 +214,6 @@ ${NAME} { securelevel = 2; osrelease = ${RELEASE}; - interface = ${bastille_jail_conf_interface}; ${IP4_DEFINITION} ${IP6_DEFINITION} ip6 = ${IP6_MODE}; @@ -199,17 +222,12 @@ EOF } generate_linux_jail_conf() { - if [ "$(sysctl -n security.jail.jailed)" -eq 1 ]; then - devfs_ruleset_value=0 - else - devfs_ruleset_value=4 - fi cat << EOF > "${bastille_jail_conf}" ${NAME} { host.hostname = ${NAME}; mount.fstab = ${bastille_jail_fstab}; path = ${bastille_jail_path}; - devfs_ruleset = ${devfs_ruleset_value}; + devfs_ruleset = 4; enforce_statfs = 1; exec.start = '/bin/true'; @@ -219,24 +237,19 @@ ${NAME} { allow.mount; allow.mount.devfs; - interface = ${bastille_jail_conf_interface}; - ${ipx_addr} = ${IP}; + ${IP4_DEFINITION} + ${IP6_DEFINITION} ip6 = ${IP6_MODE}; } EOF } generate_vnet_jail_conf() { - if [ "$(sysctl -n security.jail.jailed)" -eq 1 ]; then - devfs_ruleset_value=0 - else - devfs_ruleset_value=13 - fi - NETBLOCK=$(generate_vnet_jail_netblock "$NAME" "${VNET_JAIL_BRIDGE}" "${bastille_jail_conf_interface}" "${STATIC_MAC}") + NETBLOCK=$(generate_vnet_jail_netblock "${NAME}" "${VNET_JAIL_BRIDGE}" "${bastille_jail_conf_interface}" "${STATIC_MAC}") cat << EOF > "${bastille_jail_conf}" ${NAME} { + devfs_ruleset = 13; enforce_statfs = 2; - devfs_ruleset = ${devfs_ruleset_value}; exec.clean; exec.consolelog = ${bastille_jail_log}; exec.start = '/bin/sh /etc/rc'; @@ -258,8 +271,7 @@ post_create_jail() { # Using relative paths here. # MAKE SURE WE'RE IN THE RIGHT PLACE. - cd "${bastille_jail_path}" || error_exit "Failed to change directory." - echo + cd "${bastille_jail_path}" || error_exit "Could not cd to ${bastille_jail_path}" if [ ! -f "${bastille_jail_conf}" ]; then if [ -z "${bastille_network_loopback}" ] && [ -n "${bastille_network_shared}" ]; then @@ -382,7 +394,7 @@ create_jail() { if [ -z "${THICK_JAIL}" ] && [ -z "${CLONE_JAIL}" ]; then LINK_LIST="bin boot lib libexec rescue sbin usr/bin usr/include usr/lib usr/lib32 usr/libdata usr/libexec usr/sbin usr/share usr/src" - info "Creating a thinjail...\n" + info "Creating a thinjail..." for _link in ${LINK_LIST}; do ln -sf /.bastille/${_link} ${_link} done @@ -416,11 +428,11 @@ create_jail() { info "Creating a clonejail...\n" ## clone the release base to the new basejail SNAP_NAME="bastille-clone-$(date +%Y-%m-%d-%H%M%S)" - # shellcheck disable=SC2140 + # shellcheck disable=SC2140 zfs snapshot "${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${RELEASE}"@"${SNAP_NAME}" - - # shellcheck disable=SC2140 - zfs clone -p "${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${RELEASE}"@"${SNAP_NAME}" \ + + # shellcheck disable=SC2140 + zfs clone -p "${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${RELEASE}"@"${SNAP_NAME}" \ "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root" # Check and apply required settings. @@ -434,20 +446,20 @@ create_jail() { ## take a temp snapshot of the base release SNAP_NAME="bastille-$(date +%Y-%m-%d-%H%M%S)" - # shellcheck disable=SC2140 + # shellcheck disable=SC2140 zfs snapshot "${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${RELEASE}"@"${SNAP_NAME}" ## replicate the release base to the new thickjail and set the default mountpoint - # shellcheck disable=SC2140 + # shellcheck disable=SC2140 zfs send -R "${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${RELEASE}"@"${SNAP_NAME}" | \ zfs receive "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root" zfs set ${ZFS_OPTIONS} mountpoint=none "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root" zfs inherit mountpoint "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root" ## cleanup temp snapshots initially - # shellcheck disable=SC2140 + # shellcheck disable=SC2140 zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${RELEASE}"@"${SNAP_NAME}" - # shellcheck disable=SC2140 + # shellcheck disable=SC2140 zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root"@"${SNAP_NAME}" fi @@ -526,6 +538,12 @@ create_jail() { fi fi + # Exit if jail was not started, which means something is wrong. + if ! check_target_is_running "${NAME}"; then + bastille destroy "${NAME}" + error_exit "[${NAME}]: Failed to create jail..." + fi + if [ -n "${VNET_JAIL}" ]; then if [ -n "${bastille_template_vnet}" ]; then ## rename interface to generic vnet0 @@ -591,7 +609,7 @@ create_jail() { jexec -l "${NAME}" /bin/bash -c "DEBIAN_FRONTEND=noninteractive rm /var/cache/apt/archives/rsyslog*.deb" jexec -l "${NAME}" /bin/bash -c "DEBIAN_FRONTEND=noninteractive dpkg --force-depends --force-confdef --force-confold -i /var/cache/apt/archives/*.deb" jexec -l "${NAME}" /bin/bash -c "DEBIAN_FRONTEND=noninteractive dpkg --force-depends --force-confdef --force-confold -i /var/cache/apt/archives/*.deb" - jexec -l "${NAME}" /bin/bash -c "chmod 777 /tmp" + jexec -l "${NAME}" /bin/bash -c "chmod 1777 /tmp" jexec -l "${NAME}" /bin/bash -c "apt update" else # Thin jail. @@ -611,33 +629,32 @@ create_jail() { fi } -# Handle special-case commands first. -case "$1" in -help|-h|--help) - usage - ;; -esac - bastille_root_check -if echo "$3" | grep '@'; then +if echo "${3}" | grep '@'; then # shellcheck disable=SC2034 BASTILLE_JAIL_IP=$(echo "$3" | awk -F@ '{print $2}') # shellcheck disable=SC2034 BASTILLE_JAIL_INTERFACES=$( echo "$3" | awk -F@ '{print $1}') fi -## reset this options +# Handle options. EMPTY_JAIL="" THICK_JAIL="" CLONE_JAIL="" VNET_JAIL="" LINUX_JAIL="" STATIC_MAC="" - -# Handle and parse options +DUAL_STACK="" while [ $# -gt 0 ]; do case "${1}" in + -h|--help|help) + usage + ;; + -D|--dual) + DUAL_STACK="1" + shift + ;; -M|--static-mac) STATIC_MAC="1" shift @@ -667,61 +684,30 @@ while [ $# -gt 0 ]; do CLONE_JAIL="1" shift ;; - -CV|-VC|--clone-vnet) - CLONE_JAIL="1" - VNET_JAIL="1" - shift - ;; - -CB|-BC|--clone-bridge) - CLONE_JAIL="1" - VNET_JAIL="1" - VNET_JAIL_BRIDGE="1" - shift - ;; - -TV|-VT|--thick-vnet) - THICK_JAIL="1" - VNET_JAIL="1" - shift - ;; - -TB|-BT|--thick-bridge) - THICK_JAIL="1" - VNET_JAIL="1" - VNET_JAIL_BRIDGE="1" - shift - ;; - -EB|-BE|--empty-bridge) - EMPTY_JAIL="1" - VNET_JAIL="1" - VNET_JAIL_BRIDGE="1" - shift - ;; - -EV|-VE|--empty-vnet) - EMPTY_JAIL="1" - VNET_JAIL="1" - shift - ;; - -LV|-VL|--linux-vnet) - LINUX_JAIL="1" - VNET_JAIL="1" - shift - ;; - -LB|-BL|--linux-bridge) - LINUX_JAIL="1" - VNET_JAIL="1" - VNET_JAIL_BRIDGE="1" + -*) + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + B) VNET_JAIL=1 VNET_JAIL_BRIDGE=1 ;; + C) CLONE_JAIL=1 ;; + D) DUAL_STACK=1 ;; + E) EMPTY_JAIL=1 ;; + L) LINUX_JAIL=1 ;; + M) STATIC_MAC=1 ;; + T) THICK_JAIL=1 ;; + V) VNET_JAIL=1 ;; + x) enable_debug ;; + *) error_exit "Unknown Option: \"${1}\"" ;; + esac + done shift ;; - --*|-*) - error_notify "Unknown Option." - usage - ;; *) break ;; esac done -## validate for combined options +# Validate options if [ -n "${EMPTY_JAIL}" ]; then if [ -n "${CLONE_JAIL}" ] || [ -n "${THICK_JAIL}" ] || [ -n "${VNET_JAIL}" ] || [ -n "${LINUX_JAIL}" ]; then error_exit "Error: Empty jail option can't be used with other options." @@ -900,11 +886,6 @@ else info "Creating empty jail: ${NAME}." fi -## check if a running jail matches name or already exist -if [ -n "${NAME}" ]; then - running_jail -fi - # May not exist on deployments created before Bastille 0.7.20200714, so creating it. -- cwells if [ ! -e "${bastille_templatesdir}/default" ]; then ln -s "${bastille_sharedir}/templates/default" "${bastille_templatesdir}/default" @@ -934,4 +915,8 @@ if [ -z ${bastille_template_vnet+x} ]; then bastille_template_vnet='default/vnet' fi +if check_target_exists "${NAME}"; then + error_exit "Error: Existing jail found: ${NAME}" +fi create_jail "${NAME}" "${RELEASE}" "${IP}" "${INTERFACE}" + From 7958718140715d1d75a965004320dba009ef5645 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 28 Jan 2025 17:38:52 -0700 Subject: [PATCH 02/19] create: Restore ruleset var --- usr/local/share/bastille/create.sh | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/create.sh b/usr/local/share/bastille/create.sh index d20910d72..1931600f0 100644 --- a/usr/local/share/bastille/create.sh +++ b/usr/local/share/bastille/create.sh @@ -199,10 +199,15 @@ EOF } generate_jail_conf() { + if [ "$(sysctl -n security.jail.jailed)" -eq 1 ]; then + devfs_ruleset_value=0 + else + devfs_ruleset_value=4 + fi cat << EOF > "${bastille_jail_conf}" ${NAME} { - devfs_ruleset = 4; enforce_statfs = 2; + devfs_ruleset = ${devfs_ruleset_value}; exec.clean; exec.consolelog = ${bastille_jail_log}; exec.start = '/bin/sh /etc/rc'; @@ -245,11 +250,16 @@ EOF } generate_vnet_jail_conf() { + if [ "$(sysctl -n security.jail.jailed)" -eq 1 ]; then + devfs_ruleset_value=0 + else + devfs_ruleset_value=13 + fi NETBLOCK=$(generate_vnet_jail_netblock "${NAME}" "${VNET_JAIL_BRIDGE}" "${bastille_jail_conf_interface}" "${STATIC_MAC}") cat << EOF > "${bastille_jail_conf}" ${NAME} { - devfs_ruleset = 13; enforce_statfs = 2; + devfs_ruleset = ${devfs_ruleset_value}; exec.clean; exec.consolelog = ${bastille_jail_log}; exec.start = '/bin/sh /etc/rc'; @@ -609,7 +619,7 @@ create_jail() { jexec -l "${NAME}" /bin/bash -c "DEBIAN_FRONTEND=noninteractive rm /var/cache/apt/archives/rsyslog*.deb" jexec -l "${NAME}" /bin/bash -c "DEBIAN_FRONTEND=noninteractive dpkg --force-depends --force-confdef --force-confold -i /var/cache/apt/archives/*.deb" jexec -l "${NAME}" /bin/bash -c "DEBIAN_FRONTEND=noninteractive dpkg --force-depends --force-confdef --force-confold -i /var/cache/apt/archives/*.deb" - jexec -l "${NAME}" /bin/bash -c "chmod 1777 /tmp" + jexec -l "${NAME}" /bin/bash -c "chmod 777 /tmp" jexec -l "${NAME}" /bin/bash -c "apt update" else # Thin jail. From eb1ebff5d29a1579d029ddd5d4ad0d72913aee39 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 28 Jan 2025 17:53:13 -0700 Subject: [PATCH 03/19] stop: Allow multiple IPs in jails --- usr/local/share/bastille/stop.sh | 116 ++++++++++++++++++++++--------- 1 file changed, 84 insertions(+), 32 deletions(-) diff --git a/usr/local/share/bastille/stop.sh b/usr/local/share/bastille/stop.sh index efec51e11..18000adfb 100644 --- a/usr/local/share/bastille/stop.sh +++ b/usr/local/share/bastille/stop.sh @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: BSD-3-Clause # -# Copyright (c) 2018-2025, Christer Edwards +# Copyright (c) 2018-2024, Christer Edwards # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -34,52 +34,104 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_exit "Usage: bastille stop TARGET" + error_notify "Usage: bastille stop [option(s)] TARGET" + cat << EOF + Options: + + -v | --verbose Print every action on jail stop. + -x | --debug Enable debug mode. + +EOF + exit 1 } -# Handle special-case commands first. -case "$1" in -help|-h|--help) - usage - ;; -esac +# Handle options. +OPTION="" +while [ "$#" -gt 0 ]; do + case "${1}" in + -h|--help|help) + usage + ;; + -v|--verbose) + OPTION="-v" + shift + ;; + -x|--debug) + enable_debug + shift + ;; + -*) + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + v) OPTION="-v" ;; + x) enable_debug ;; + *) error_exit "Unknown Option: \"${1}\"" ;; + esac + done + shift + ;; + *) + break + ;; + esac +done -if [ $# -ne 0 ]; then +if [ "$#" -ne 1 ]; then usage fi +TARGET="${1}" + bastille_root_check +set_target "${TARGET}" for _jail in ${JAILS}; do - ## test if running - if [ "$(/usr/sbin/jls name | awk "/^${_jail}$/")" ]; then - ## Capture ip4.addr address while still running - _ip4="$(bastille config ${_jail} get ip4.addr)" - # Check if pfctl is present - if [ "${_ip4}" != "not set" ]; then - if [ "$(bastille rdr ${_jail} list)" ]; then - bastille rdr ${_jail} clear + info "[${_jail}]:" + check_target_is_running "${_jail}" || error_continue "Jail is already stopped." + + # Remove RDR rules + if [ "$(bastille config ${_jail} get vnet)" != "enabled" ]; then + _ip4="$(bastille config ${_jail} get ip4.addr | sed 's/,/ /g')" + _ip6="$(bastille config ${_jail} get ip6.addr | sed 's/,/ /g')" + if [ "${_ip4}" != "not set" ] || [ "${_ip6}" != "not set" ]; then + if which -s pfctl; then + if [ "$(bastille rdr ${_jail} list)" ]; then + bastille rdr "${_jail}" clear + fi fi fi + fi - ## remove rctl limits - if [ -s "${bastille_jailsdir}/${_jail}/rctl.conf" ]; then - while read _limits; do - rctl -r "${_limits}" - done < "${bastille_jailsdir}/${_jail}/rctl.conf" - fi + # Remove rctl limits + if [ -s "${bastille_jailsdir}/${_jail}/rctl.conf" ]; then + while read _limits; do + rctl -r "${_limits}" + done < "${bastille_jailsdir}/${_jail}/rctl.conf" + fi - ## stop container - info "[${_jail}]:" - jail -f "${bastille_jailsdir}/${_jail}/jail.conf" -r "${_jail}" + # Stop jail + jail ${OPTION} -f "${bastille_jailsdir}/${_jail}/jail.conf" -r "${_jail}" - ## remove (captured above) ip4.addr from firewall table - if [ -n "${bastille_network_loopback}" ] && [ "${_ip4}" != "not set" ]; then - if grep -qw "interface.*=.*${bastille_network_loopback}" "${bastille_jailsdir}/${_jail}/jail.conf"; then - pfctl -q -t "${bastille_network_pf_table}" -T delete "${_ip4}" + # Remove (captured above) IPs from firewall table + if [ "${_ip4}" != "not set" ]; then + for _ip in ${_ip4}; do + if echo "${_ip}" | grep -q "|"; then + _ip="$(echo ${_ip} | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" + else + _ip="$(echo ${_ip} | sed -E 's#/[0-9]+$##g')" fi - fi + pfctl -q -t "${bastille_network_pf_table}" -T delete "${_ip}" + done + fi + if [ "${_ip6}" != "not set" ]; then + for _ip in ${_ip6}; do + if echo "${_ip}" | grep -q "|"; then + _ip="$(echo ${_ip} | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" + else + _ip="$(echo ${_ip} | sed -E 's#/[0-9]+$##g')" + fi + pfctl -q -t "${bastille_network_pf_table}" -T delete "${_ip}" + done fi - echo done From b3d9e3e0ddb70739559e6dfcb004da2f7b2fa52d Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 28 Jan 2025 17:55:19 -0700 Subject: [PATCH 04/19] start: Allow multiple interface and IPs --- usr/local/share/bastille/start.sh | 160 +++++++++++++++++++----------- 1 file changed, 101 insertions(+), 59 deletions(-) diff --git a/usr/local/share/bastille/start.sh b/usr/local/share/bastille/start.sh index 375d49c22..0a1ac0462 100644 --- a/usr/local/share/bastille/start.sh +++ b/usr/local/share/bastille/start.sh @@ -34,80 +34,122 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_exit "Usage: bastille start TARGET" + error_notify "Usage: bastille start [option(s)] TARGET" + cat << EOF + Options: + + -v | --verbose Print every action on jail start. + -x | --debug Enable debug mode. + +EOF + exit 1 } -# Handle special-case commands first. -case "$1" in -help|-h|--help) - usage - ;; -esac +# Handle options. +OPTION="" +while [ "$#" -gt 0 ]; do + case "${1}" in + -h|--help|help) + usage + ;; + -v|--verbose) + OPTION="-v" + shift + ;; + -x|--debug) + enable_debug + shift + ;; + -*) + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + v) OPTION="-v" ;; + x) enable_debug ;; + *) error_exit "Unknown Option: \"${1}\"" ;; + esac + done + shift + ;; + *) + break + ;; + esac +done -if [ $# -gt 1 ] || [ $# -lt 1 ]; then +if [ "$#" -ne 1 ]; then usage fi -bastille_root_check - TARGET="${1}" -shift -if [ "${TARGET}" = 'ALL' ]; then - JAILS=$(bastille list jails) -fi -if [ "${TARGET}" != 'ALL' ]; then - JAILS=$(bastille list jails | awk "/^${TARGET}$/") - ## check if exist - if [ ! -d "${bastille_jailsdir}/${TARGET}" ]; then - error_exit "[${TARGET}]: Not found." - fi -fi +bastille_root_check +set_target "${TARGET}" for _jail in ${JAILS}; do - ## test if running - if [ "$(/usr/sbin/jls name | awk "/^${_jail}$/")" ]; then - error_notify "[${_jail}]: Already started." - ## test if not running - elif [ ! "$(/usr/sbin/jls name | awk "/^${_jail}$/")" ]; then - # Verify that the configured interface exists. -- cwells - if [ "$(bastille config $_jail get vnet)" != 'enabled' ]; then - _interface=$(bastille config $_jail get interface) - if ! ifconfig | grep "^${_interface}:" >/dev/null; then - error_notify "Error: ${_interface} interface does not exist." - continue - fi - fi + info "[${_jail}]:" + check_target_is_stopped "${_jail}" || error_continue "Jail is already running." - ## warn if matching configured (but not online) ip4.addr, ignore if there's no ip4.addr entry - _ip4=$(bastille config "${_jail}" get ip4.addr) - if [ "${_ip4}" != "not set" ]; then - if ifconfig | grep -wF "${_ip4}" >/dev/null; then - error_notify "Error: IP address (${_ip4}) already in use." - continue - fi - ## add ip4.addr to firewall table - pfctl -q -t "${bastille_network_pf_table}" -T add "${_ip4}" + # Validate interfaces and add IPs to firewall table + if [ "$(bastille config ${_jail} get vnet)" != 'enabled' ]; then + _ip4_interfaces="$(bastille config ${_jail} get ip4.addr | sed 's/,/ /g')" + _ip6_interfaces="$(bastille config ${_jail} get ip6.addr | sed 's/,/ /g')" + # IP4 + if [ "${_ip4_interfaces}" != "not set" ]; then + for _interface in ${_ip4_interfaces}; do + if echo "${_interface}" | grep -q "|"; then + _if="$(echo ${_interface} 2>/dev/null | awk -F"|" '{print $1}')" + _ip="$(echo ${_interface} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" + else + _if="$(bastille config ${_jail} get interface)" + _ip="$(echo ${_interface} | sed -E 's#/[0-9]+$##g')" + fi + if ifconfig | grep "^${_if}:" >/dev/null; then + if ifconfig | grep -qwF "${_ip}"; then + warn "Warning: IP address (${_ip}) already in use, continuing..." + pfctl -q -t "${bastille_network_pf_table}" -T add "${_ip}" + fi + else + error_continue "Error: ${_if} interface does not exist." + fi + done + fi + # IP6 + if [ "${_ip6_interfaces}" != "not set" ]; then + for _interface in ${_ip6_interfaces}; do + if echo "${_interface}" | grep -q "|"; then + _if="$(echo ${_interface} | awk -F"|" '{print $1}')" + _ip="$(echo ${_interface} | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" + else + _if="$(bastille config ${_jail} get interface)" + _ip="$(echo ${_interface} | sed -E 's#/[0-9]+$##g')" + fi + if ifconfig | grep "^${_if}:" >/dev/null; then + if ifconfig | grep -qwF "${_ip}"; then + warn "Warning: IP address (${_ip}) already in use, continuing..." + pfctl -q -t "${bastille_network_pf_table}" -T add "${_ip}" + fi + else + error_continue "Error: ${_if} interface does not exist." + fi + done fi + fi - ## start the container - info "[${_jail}]:" - jail -f "${bastille_jailsdir}/${_jail}/jail.conf" -c "${_jail}" + # Start jail + jail ${OPTION} -f "${bastille_jailsdir}/${_jail}/jail.conf" -c "${_jail}" - ## add rctl limits - if [ -s "${bastille_jailsdir}/${_jail}/rctl.conf" ]; then - while read _limits; do - rctl -a "${_limits}" - done < "${bastille_jailsdir}/${_jail}/rctl.conf" - fi + # Add rctl limits + if [ -s "${bastille_jailsdir}/${_jail}/rctl.conf" ]; then + while read _limits; do + rctl -a "${_limits}" + done < "${bastille_jailsdir}/${_jail}/rctl.conf" + fi - ## add rdr rules - if [ -s "${bastille_jailsdir}/${_jail}/rdr.conf" ]; then - while read _rules; do - bastille rdr "${_jail}" ${_rules} - done < "${bastille_jailsdir}/${_jail}/rdr.conf" - fi + # Add rdr rules + if [ -s "${bastille_jailsdir}/${_jail}/rdr.conf" ]; then + while read _rules; do + bastille rdr ${_jail} ${_rules} + done < "${bastille_jailsdir}/${_jail}/rdr.conf" fi - echo done From d0d46c1f701b746fcda95b32e29a99306409cd80 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 31 Jan 2025 09:26:49 -0700 Subject: [PATCH 05/19] stop: Fix copyright year --- usr/local/share/bastille/stop.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/stop.sh b/usr/local/share/bastille/stop.sh index 18000adfb..faafe4cc1 100644 --- a/usr/local/share/bastille/stop.sh +++ b/usr/local/share/bastille/stop.sh @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: BSD-3-Clause # -# Copyright (c) 2018-2024, Christer Edwards +# Copyright (c) 2018-2025, Christer Edwards # All rights reserved. # # Redistribution and use in source and binary forms, with or without From 73d510aae4cf457ed36d5a9a52c80d44c08530ee Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 3 Feb 2025 11:46:08 -0700 Subject: [PATCH 06/19] Bastille: Stop to no action commands --- usr/local/bin/bastille | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index d8439beb7..fcf440297 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -166,10 +166,10 @@ help|-h|--help) usage ;; -bootstrap|clone|console|create|cp|destroy|etcupdate|export|htop|import|jcp|list|mount|rcp|rdr|rename|restart|setup|start|top|umount|update|upgrade|verify) +bootstrap|clone|console|create|cp|destroy|etcupdate|export|htop|import|jcp|list|mount|rcp|rdr|rename|restart|setup|start|stop|top|umount|update|upgrade|verify) # Nothing "extra" to do for these commands. -- cwells ;; -config|cmd|convert|edit|limits|pkg|service|stop|sysrc|tags|template|zfs) +config|cmd|convert|edit|limits|pkg|service|sysrc|tags|template|zfs) # Parse the target and ensure it exists. -- cwells if [ $# -eq 0 ]; then # No target was given, so show the command's help. -- cwells PARAMS='help' From a1e58f41312226aa8f0196361ddf45d9b4e90525 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 16 Feb 2025 19:35:27 -0700 Subject: [PATCH 07/19] start: Fix IP not being added to firewal --- usr/local/share/bastille/start.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/start.sh b/usr/local/share/bastille/start.sh index 0a1ac0462..715e83070 100644 --- a/usr/local/share/bastille/start.sh +++ b/usr/local/share/bastille/start.sh @@ -107,8 +107,8 @@ for _jail in ${JAILS}; do if ifconfig | grep "^${_if}:" >/dev/null; then if ifconfig | grep -qwF "${_ip}"; then warn "Warning: IP address (${_ip}) already in use, continuing..." - pfctl -q -t "${bastille_network_pf_table}" -T add "${_ip}" fi + pfctl -q -t "${bastille_network_pf_table}" -T add "${_ip}" else error_continue "Error: ${_if} interface does not exist." fi @@ -127,8 +127,8 @@ for _jail in ${JAILS}; do if ifconfig | grep "^${_if}:" >/dev/null; then if ifconfig | grep -qwF "${_ip}"; then warn "Warning: IP address (${_ip}) already in use, continuing..." - pfctl -q -t "${bastille_network_pf_table}" -T add "${_ip}" fi + pfctl -q -t "${bastille_network_pf_table}" -T add "${_ip}" else error_continue "Error: ${_if} interface does not exist." fi From 1245b0e30e33a872e2cadf5c1ed714bf40f1a1e3 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 20 Feb 2025 09:47:36 -0700 Subject: [PATCH 08/19] start: Do not add IP to firewall table if it is in the same subnet --- usr/local/share/bastille/start.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/start.sh b/usr/local/share/bastille/start.sh index 715e83070..8a0960d13 100644 --- a/usr/local/share/bastille/start.sh +++ b/usr/local/share/bastille/start.sh @@ -108,7 +108,10 @@ for _jail in ${JAILS}; do if ifconfig | grep -qwF "${_ip}"; then warn "Warning: IP address (${_ip}) already in use, continuing..." fi - pfctl -q -t "${bastille_network_pf_table}" -T add "${_ip}" + ## add ip to firewall table if it is not reachable through local interface (assumes NAT/rdr is needed) + if route -n get ${_ip} | grep "gateway" >/dev/null; then + pfctl -q -t "${bastille_network_pf_table}" -T add "${_ip}" + fi else error_continue "Error: ${_if} interface does not exist." fi @@ -128,7 +131,10 @@ for _jail in ${JAILS}; do if ifconfig | grep -qwF "${_ip}"; then warn "Warning: IP address (${_ip}) already in use, continuing..." fi - pfctl -q -t "${bastille_network_pf_table}" -T add "${_ip}" + ## add ip to firewall table if it is not reachable through local interface (assumes NAT/rdr is needed) + if route -n get ${_ip} | grep "gateway" >/dev/null; then + pfctl -q -t "${bastille_network_pf_table}" -T add "${_ip}" + fi else error_continue "Error: ${_if} interface does not exist." fi From 6193fa307a5df502b3884516c58dca19f5011465 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 22 Feb 2025 22:49:33 -0700 Subject: [PATCH 09/19] template: Use new style of interface|ip pair --- usr/local/share/bastille/template.sh | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index 9e4f42b28..da9ee3980 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -231,15 +231,25 @@ for _jail in ${JAILS}; do ## jail-specific variables. bastille_jail_path=$(/usr/sbin/jls -j "${_jail}" path) - if [ "$(bastille config $TARGET get vnet)" != 'enabled' ]; then - _jail_ip=$(/usr/sbin/jls -j "${_jail}" ip4.addr 2>/dev/null) - _jail_ip6=$(/usr/sbin/jls -j "${_jail}" ip6.addr 2>/dev/null) - if [ -z "${_jail_ip}" ] || [ "${_jail_ip}" = "-" ]; then - error_notify "Jail IP not found: ${_jail}" - _jail_ip='' # In case it was -. -- cwells - fi + if [ "$(bastille config ${_jail} get vnet)" != 'enabled' ]; then + _jail_ip="$(bastille config ${_jail} get ip4.addr | sed 's/,/ /g')" + _jail_ip6="$(bastille config ${_jail} get ip6.addr | sed 's/,/ /g')" fi - + if [ "${_jail_ip}" = "not set" ] || [ "${_jail_ip}" = "disabled" ]; then + error_notify "Jail IP4 not found: ${_jail}" + _jail_ip='' # In case it was -. -- cwells + fi + if [ "${_jail_ip6}" = "not set" ] || [ "${_jail_ip6}" = "disabled" ]; then + error_notify "Jail IP6 not found: ${_jail}" + _jail_ip6='' # In case it was -. -- cwells + fi + if echo "${_jail_ip}" | grep -q "|"; then + _jail_ip="$(echo ${_jail_ip} 2>/dev/null | awk -F"|" '{print $2}')" + fi + if echo "${_jail_ip6}" | grep -q "|"; then + _jail_ip6="$(echo ${_jail_ip6} 2>/dev/null | awk -F"|" '{print $2}')" + fi + ## TARGET if [ -s "${bastille_template}/TARGET" ]; then if grep -qw "${_jail}" "${bastille_template}/TARGET"; then From 8f6599fd491dbfb8999252aaf88c51aa728893e5 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 22 Feb 2025 22:51:23 -0700 Subject: [PATCH 10/19] template: Trim trailing slash from jail ip --- usr/local/share/bastille/template.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index da9ee3980..c960c15d6 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -244,10 +244,10 @@ for _jail in ${JAILS}; do _jail_ip6='' # In case it was -. -- cwells fi if echo "${_jail_ip}" | grep -q "|"; then - _jail_ip="$(echo ${_jail_ip} 2>/dev/null | awk -F"|" '{print $2}')" + _jail_ip="$(echo ${_jail_ip} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" fi if echo "${_jail_ip6}" | grep -q "|"; then - _jail_ip6="$(echo ${_jail_ip6} 2>/dev/null | awk -F"|" '{print $2}')" + _jail_ip6="$(echo ${_jail_ip6} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" fi ## TARGET From 4b092e513a0f0b2c02383c2ec0a85c512998b572 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 22 Feb 2025 22:52:55 -0700 Subject: [PATCH 11/19] template: jail_ip > jail_ip4 --- usr/local/share/bastille/template.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index c960c15d6..7f8a185c2 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -232,22 +232,22 @@ for _jail in ${JAILS}; do ## jail-specific variables. bastille_jail_path=$(/usr/sbin/jls -j "${_jail}" path) if [ "$(bastille config ${_jail} get vnet)" != 'enabled' ]; then - _jail_ip="$(bastille config ${_jail} get ip4.addr | sed 's/,/ /g')" - _jail_ip6="$(bastille config ${_jail} get ip6.addr | sed 's/,/ /g')" + _jail_ip4="$(bastille config ${_jail} get ip4.addr | sed 's/,/ /g')" + _jail_ip46="$(bastille config ${_jail} get ip6.addr | sed 's/,/ /g')" fi - if [ "${_jail_ip}" = "not set" ] || [ "${_jail_ip}" = "disabled" ]; then + if [ "${_jail_ip4}" = "not set" ] || [ "${_jail_ip4}" = "disabled" ]; then error_notify "Jail IP4 not found: ${_jail}" - _jail_ip='' # In case it was -. -- cwells + _jail_ip4='' # In case it was -. -- cwells fi - if [ "${_jail_ip6}" = "not set" ] || [ "${_jail_ip6}" = "disabled" ]; then + if [ "${_jail_ip46}" = "not set" ] || [ "${_jail_ip46}" = "disabled" ]; then error_notify "Jail IP6 not found: ${_jail}" - _jail_ip6='' # In case it was -. -- cwells + _jail_ip46='' # In case it was -. -- cwells fi - if echo "${_jail_ip}" | grep -q "|"; then - _jail_ip="$(echo ${_jail_ip} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" + if echo "${_jail_ip4}" | grep -q "|"; then + _jail_ip4="$(echo ${_jail_ip4} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" fi - if echo "${_jail_ip6}" | grep -q "|"; then - _jail_ip6="$(echo ${_jail_ip6} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" + if echo "${_jail_ip46}" | grep -q "|"; then + _jail_ip46="$(echo ${_jail_ip46} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" fi ## TARGET @@ -266,7 +266,7 @@ for _jail in ${JAILS}; do # Build a list of sed commands like this: -e 's/${username}/root/g' -e 's/${domain}/example.com/g' # Values provided by default (without being defined by the user) are listed here. -- cwells - ARG_REPLACEMENTS="-e 's/\${JAIL_IP}/${_jail_ip}/g' -e 's/\${JAIL_IP6}/${_jail_ip6}/g' -e 's/\${JAIL_NAME}/${_jail}/g'" + ARG_REPLACEMENTS="-e 's/\${jail_ip4}/${_jail_ip4}/g' -e 's/\${jail_ip46}/${_jail_ip46}/g' -e 's/\${JAIL_NAME}/${_jail}/g'" # This is parsed outside the HOOKS loop so an ARG file can be used with a Bastillefile. -- cwells if [ -s "${bastille_template}/ARG" ]; then while read _line; do From 2ed27f572e8912594b5a87bc797a8c9a88ed1676 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 22 Feb 2025 22:54:46 -0700 Subject: [PATCH 12/19] template: Fix booboo --- usr/local/share/bastille/template.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index 7f8a185c2..626fc9ccc 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -233,21 +233,21 @@ for _jail in ${JAILS}; do bastille_jail_path=$(/usr/sbin/jls -j "${_jail}" path) if [ "$(bastille config ${_jail} get vnet)" != 'enabled' ]; then _jail_ip4="$(bastille config ${_jail} get ip4.addr | sed 's/,/ /g')" - _jail_ip46="$(bastille config ${_jail} get ip6.addr | sed 's/,/ /g')" + _jail_ip6="$(bastille config ${_jail} get ip6.addr | sed 's/,/ /g')" fi if [ "${_jail_ip4}" = "not set" ] || [ "${_jail_ip4}" = "disabled" ]; then error_notify "Jail IP4 not found: ${_jail}" _jail_ip4='' # In case it was -. -- cwells fi - if [ "${_jail_ip46}" = "not set" ] || [ "${_jail_ip46}" = "disabled" ]; then + if [ "${_jail_ip6}" = "not set" ] || [ "${_jail_ip6}" = "disabled" ]; then error_notify "Jail IP6 not found: ${_jail}" - _jail_ip46='' # In case it was -. -- cwells + _jail_ip6='' # In case it was -. -- cwells fi if echo "${_jail_ip4}" | grep -q "|"; then _jail_ip4="$(echo ${_jail_ip4} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" fi - if echo "${_jail_ip46}" | grep -q "|"; then - _jail_ip46="$(echo ${_jail_ip46} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" + if echo "${_jail_ip6}" | grep -q "|"; then + _jail_ip6="$(echo ${_jail_ip6} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" fi ## TARGET @@ -266,7 +266,7 @@ for _jail in ${JAILS}; do # Build a list of sed commands like this: -e 's/${username}/root/g' -e 's/${domain}/example.com/g' # Values provided by default (without being defined by the user) are listed here. -- cwells - ARG_REPLACEMENTS="-e 's/\${jail_ip4}/${_jail_ip4}/g' -e 's/\${jail_ip46}/${_jail_ip46}/g' -e 's/\${JAIL_NAME}/${_jail}/g'" + ARG_REPLACEMENTS="-e 's/\${jail_ip4}/${_jail_ip4}/g' -e 's/\${jail_ip6}/${_jail_ip6}/g' -e 's/\${JAIL_NAME}/${_jail}/g'" # This is parsed outside the HOOKS loop so an ARG file can be used with a Bastillefile. -- cwells if [ -s "${bastille_template}/ARG" ]; then while read _line; do From f0063b41f71a7aedc301f0265c823f68b276fc0c Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 22 Feb 2025 23:15:49 -0700 Subject: [PATCH 13/19] template: FIx booboo --- usr/local/share/bastille/template.sh | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index 626fc9ccc..18fa593fd 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -236,18 +236,18 @@ for _jail in ${JAILS}; do _jail_ip6="$(bastille config ${_jail} get ip6.addr | sed 's/,/ /g')" fi if [ "${_jail_ip4}" = "not set" ] || [ "${_jail_ip4}" = "disabled" ]; then - error_notify "Jail IP4 not found: ${_jail}" - _jail_ip4='' # In case it was -. -- cwells - fi - if [ "${_jail_ip6}" = "not set" ] || [ "${_jail_ip6}" = "disabled" ]; then - error_notify "Jail IP6 not found: ${_jail}" - _jail_ip6='' # In case it was -. -- cwells - fi - if echo "${_jail_ip4}" | grep -q "|"; then - _jail_ip4="$(echo ${_jail_ip4} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" - fi - if echo "${_jail_ip6}" | grep -q "|"; then - _jail_ip6="$(echo ${_jail_ip6} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" + if [ "${_jail_ip6}" = "not set" ] || [ "${_jail_ip6}" = "disabled" ]; then + error_notify "Jail IP not found: ${_jail}" + _jail_ip4='' # In case it was -. -- cwells + _jail_ip6='' # In case it was -. -- cwells + else + if echo "${_jail_ip4}" | grep -q "|"; then + _jail_ip4="$(echo ${_jail_ip4} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" + fi + if echo "${_jail_ip6}" | grep -q "|"; then + _jail_ip6="$(echo ${_jail_ip6} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" + fi + fi fi ## TARGET From f06788ee7bccfe6bfe1e896b29307412fd245524 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 22 Feb 2025 23:24:17 -0700 Subject: [PATCH 14/19] Update template.sh --- usr/local/share/bastille/template.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index 18fa593fd..726a10beb 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -240,13 +240,13 @@ for _jail in ${JAILS}; do error_notify "Jail IP not found: ${_jail}" _jail_ip4='' # In case it was -. -- cwells _jail_ip6='' # In case it was -. -- cwells - else - if echo "${_jail_ip4}" | grep -q "|"; then - _jail_ip4="$(echo ${_jail_ip4} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" - fi - if echo "${_jail_ip6}" | grep -q "|"; then - _jail_ip6="$(echo ${_jail_ip6} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" - fi + fi + else + if echo "${_jail_ip4}" | grep -q "|"; then + _jail_ip4="$(echo ${_jail_ip4} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" + fi + if echo "${_jail_ip6}" | grep -q "|"; then + _jail_ip6="$(echo ${_jail_ip6} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" fi fi From 1ef0de52a04ad8ef754e64112b4ae5815bfe58bf Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 22 Feb 2025 23:35:49 -0700 Subject: [PATCH 15/19] template: One more fix for IP --- usr/local/share/bastille/template.sh | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index 726a10beb..f320f58ca 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -235,19 +235,17 @@ for _jail in ${JAILS}; do _jail_ip4="$(bastille config ${_jail} get ip4.addr | sed 's/,/ /g')" _jail_ip6="$(bastille config ${_jail} get ip6.addr | sed 's/,/ /g')" fi - if [ "${_jail_ip4}" = "not set" ] || [ "${_jail_ip4}" = "disabled" ]; then - if [ "${_jail_ip6}" = "not set" ] || [ "${_jail_ip6}" = "disabled" ]; then - error_notify "Jail IP not found: ${_jail}" - _jail_ip4='' # In case it was -. -- cwells - _jail_ip6='' # In case it was -. -- cwells - fi - else - if echo "${_jail_ip4}" | grep -q "|"; then - _jail_ip4="$(echo ${_jail_ip4} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" - fi - if echo "${_jail_ip6}" | grep -q "|"; then - _jail_ip6="$(echo ${_jail_ip6} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" - fi + if { [ "${_jail_ip4}" = "not set" ] || [ "${_jail_ip4}" = "disabled" ]; } && \ + { [ "${_jail_ip6}" = "not set" ] || [ "${_jail_ip6}" = "disabled" ]; } then + error_notify "Jail IP not found: ${_jail}" + _jail_ip4='' # In case it was -. -- cwells + _jail_ip6='' # In case it was -. -- cwells + fi + if echo "${_jail_ip4}" | grep -q "|"; then + _jail_ip4="$(echo ${_jail_ip4} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" + fi + if echo "${_jail_ip6}" | grep -q "|"; then + _jail_ip6="$(echo ${_jail_ip6} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" fi ## TARGET From c2421ad98181abd7157c165b66f9e6aa302fe186 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 22 Feb 2025 23:43:16 -0700 Subject: [PATCH 16/19] template: Code cleanup for getting IP --- usr/local/share/bastille/template.sh | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index f320f58ca..10a6c255e 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -229,24 +229,29 @@ for _jail in ${JAILS}; do info "[${_jail}]:" info "Applying template: ${TEMPLATE}..." - ## jail-specific variables. + ## get jail ip4 and ip6 values bastille_jail_path=$(/usr/sbin/jls -j "${_jail}" path) if [ "$(bastille config ${_jail} get vnet)" != 'enabled' ]; then _jail_ip4="$(bastille config ${_jail} get ip4.addr | sed 's/,/ /g')" _jail_ip6="$(bastille config ${_jail} get ip6.addr | sed 's/,/ /g')" fi - if { [ "${_jail_ip4}" = "not set" ] || [ "${_jail_ip4}" = "disabled" ]; } && \ - { [ "${_jail_ip6}" = "not set" ] || [ "${_jail_ip6}" = "disabled" ]; } then - error_notify "Jail IP not found: ${_jail}" + ## remove value if ip4 was not set or disabled, otherwise get value + if [ "${_jail_ip4}" = "not set" ] || [ "${_jail_ip4}" = "disabled" ]; then _jail_ip4='' # In case it was -. -- cwells - _jail_ip6='' # In case it was -. -- cwells - fi - if echo "${_jail_ip4}" | grep -q "|"; then + elif echo "${_jail_ip4}" | grep -q "|"; then _jail_ip4="$(echo ${_jail_ip4} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" fi + ## remove value if ip6 was not set or disabled, otherwise get value + if [ "${_jail_ip6}" = "not set" ] || [ "${_jail_ip6}" = "disabled" ]; then + _jail_ip6='' # In case it was -. -- cwells if echo "${_jail_ip6}" | grep -q "|"; then _jail_ip6="$(echo ${_jail_ip6} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" fi + # print error when both ip4 and ip6 are not set + if { [ "${_jail_ip4}" = "not set" ] || [ "${_jail_ip4}" = "disabled" ]; } && \ + { [ "${_jail_ip6}" = "not set" ] || [ "${_jail_ip6}" = "disabled" ]; } then + error_notify "Jail IP not found: ${_jail}" + fi ## TARGET if [ -s "${bastille_template}/TARGET" ]; then From efa279bf7193170f061a7c3a1b5fe21e71950417 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 22 Feb 2025 23:45:24 -0700 Subject: [PATCH 17/19] template: Support old style IP/interface pair --- usr/local/share/bastille/template.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index 10a6c255e..10d8866fc 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -239,13 +239,17 @@ for _jail in ${JAILS}; do if [ "${_jail_ip4}" = "not set" ] || [ "${_jail_ip4}" = "disabled" ]; then _jail_ip4='' # In case it was -. -- cwells elif echo "${_jail_ip4}" | grep -q "|"; then - _jail_ip4="$(echo ${_jail_ip4} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" + _jail_ip4="$(echo ${_jail_ip4} | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" + else + _jail_ip4="$(echo ${_jail_ip4} | sed -E 's#/[0-9]+$##g')" fi ## remove value if ip6 was not set or disabled, otherwise get value if [ "${_jail_ip6}" = "not set" ] || [ "${_jail_ip6}" = "disabled" ]; then _jail_ip6='' # In case it was -. -- cwells if echo "${_jail_ip6}" | grep -q "|"; then - _jail_ip6="$(echo ${_jail_ip6} 2>/dev/null | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" + _jail_ip6="$(echo ${_jail_ip6} | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" + else + _jail_ip6="$(echo ${_jail_ip6} | sed -E 's#/[0-9]+$##g')" fi # print error when both ip4 and ip6 are not set if { [ "${_jail_ip4}" = "not set" ] || [ "${_jail_ip4}" = "disabled" ]; } && \ From d799fa37b68f537a5ce47a13d649190e10ecc7e8 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 22 Feb 2025 23:47:07 -0700 Subject: [PATCH 18/19] template: Fix shellcheck --- usr/local/share/bastille/template.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index 10d8866fc..7802f8368 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -246,7 +246,7 @@ for _jail in ${JAILS}; do ## remove value if ip6 was not set or disabled, otherwise get value if [ "${_jail_ip6}" = "not set" ] || [ "${_jail_ip6}" = "disabled" ]; then _jail_ip6='' # In case it was -. -- cwells - if echo "${_jail_ip6}" | grep -q "|"; then + elif echo "${_jail_ip6}" | grep -q "|"; then _jail_ip6="$(echo ${_jail_ip6} | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')" else _jail_ip6="$(echo ${_jail_ip6} | sed -E 's#/[0-9]+$##g')" From 87e9affe46540cc9aacc185585a409817590fb18 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 23 Feb 2025 09:24:15 -0700 Subject: [PATCH 19/19] template: Print only the first IP for the jail --- usr/local/share/bastille/template.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index 7802f8368..030b79c01 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -232,8 +232,8 @@ for _jail in ${JAILS}; do ## get jail ip4 and ip6 values bastille_jail_path=$(/usr/sbin/jls -j "${_jail}" path) if [ "$(bastille config ${_jail} get vnet)" != 'enabled' ]; then - _jail_ip4="$(bastille config ${_jail} get ip4.addr | sed 's/,/ /g')" - _jail_ip6="$(bastille config ${_jail} get ip6.addr | sed 's/,/ /g')" + _jail_ip4="$(bastille config ${_jail} get ip4.addr | sed 's/,/ /g' | awk '{print $1}')" + _jail_ip6="$(bastille config ${_jail} get ip6.addr | sed 's/,/ /g' | awk '{print $1}')" fi ## remove value if ip4 was not set or disabled, otherwise get value if [ "${_jail_ip4}" = "not set" ] || [ "${_jail_ip4}" = "disabled" ]; then