Merge branch 'BastilleBSD:master' into multiple-interfaces

This commit is contained in:
tschettervictor
2025-02-22 22:20:40 -07:00
committed by GitHub
14 changed files with 620 additions and 167 deletions

View File

@@ -120,6 +120,10 @@ container interfaces as they are started and stopped. These interface names
match the pattern `eXb_bastilleX`. Internally to the containers these
interfaces are presented as `vnet0`.
If you do not specify a subnet mask, you might have issues with jail to jail
networking, especially VLAN to VLAN. We recommend always adding a subnet to
VNET jail IPs when creating them to avoid these issues.
VNET also requires a custom devfs ruleset. Create the file as needed on the
host system:
@@ -305,3 +309,21 @@ At this point you'll likely be disconnected from the host. Reconnect the
ssh session and continue.
This step only needs to be done once in order to prepare the host.
local_unbound
=============
If you are running "local_unbound" on your server, you will probably have issues with DNS resolution.
To resolve this, add the following configuration to local_unbound:
.. code-block:: shell
server:
interface: 0.0.0.0
access-control: 192.168.0.0/16 allow
access-control: 10.17.90.0/24 allow
Also, change the nameserver to the servers IP instead of 127.0.0.1 inside /etc/rc.conf
Adjust the above "access-control" strings to fit your network.

View File

@@ -0,0 +1,46 @@
=========
etcupdate
=========
This command will update the contents of `/etc` inside a jail. It should be run after a jail upgrade
First we need to bootstrap a release for `etcupdate` to use.
.. code-block:: shell
ishmael ~ # bastille etcupdate bootstrap 14.1-RELEASE
bastille_bootstrap_archives: base -> src
/usr/local/bastille/cache/14.1-RELEASE/MANIFES 1046 B 1134 kBps 00s
/usr/local/bastille/cache/14.1-RELEASE/src.txz 205 MB 2711 kBps 01m18s
bastille_bootstrap_archives: src -> base
Building tarball, please wait...
Etcupdate bootstrap complete: 14.1-RELEASE
Next we can use the `update` command to apply the update to the jail.
.. code-block:: shell
ishmael ~ # bastille etcupdate ishmael update 14.1-RELEASE
The output will show you which files were added, updated, changed, deleted, or have conflicts.
To automatically resolve the conflicts, run the `resolve` command.
.. code-block:: shell
ishmael ~ # bastille etcupdate ishmael resolve
To show only the differences between the releases, use the `diff` command.
.. code-block:: shell
ishmael ~ # bastille etcupdate ishmael diff 14.1-RELEASE
.. code-block:: shell
ishmael ~ # bastille etcupdate help
Usage: bastille etcupdate [option(s)] [bootstrap|TARGET] [diff|resolve|update RELEASE]
Options:
-d | --dry-run Show output, but do not apply.
-f | --force Force a re-bootstrap of a RELEASE.
-x | --debug Enable debug mode.

View File

@@ -14,13 +14,67 @@ 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 <host_port> <jail_port>] | [udp <host_port> <jail_port>]
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.
-x | --debug Enable debug mode.
# bastille rdr dev1 tcp 2001 22
[jail1]:
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/2053:53 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
The `rdr` command includes 4 additional options:
.. 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
# bastille rdr dev1 -i vtnet0 udp 8000 80
[jail1]:
IPv4 tcp/8000:80 on vtnet0
# bastille rdr dev1 -s 192.168.0.1 tcp 8080 81
[jail1]:
IPv4 tcp/8080:81 on em0
# bastille rdr dev1 -d 192.168.0.84 tcp 8082 82
[jail1]:
IPv4 tcp/8082:82 on em0
# bastille rdr dev1 -i vtnet0 -d 192.168.0.45 tcp 9000 9000
[jail1]:
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
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.
If you have multiple interfaces assigned to your jail, `bastille rdr` will
only redirect using the default one.

View File

@@ -2,8 +2,8 @@
update
======
The `update` command targets a release instead of a container. Because every container is
based on a release, when the release is updated all the containers are automatically
The `update` command targets a release or a thick jail. Because thin jails are
based on a release, when the release is updated all the thin jails are automatically
updated as well.
If no updates are available, a message will be shown:
@@ -20,8 +20,7 @@ If no updates are available, a message will be shown:
No updates needed to update system to 11.4-RELEASE-p4.
No updates are available to install.
The older the release, however, the more updates will be available:
The older the release or jail, however, the more updates will be available:
.. code-block:: shell
@@ -38,4 +37,7 @@ The older the release, however, the more updates will be available:
The following files will be added as part of updating to 13.2-RELEASE-p4:
...[snip]...
To be safe, you may want to restart any containers that have been updated live.
To be safe, you may want to restart any jails that have been updated live.
If the jail is a thin jail, an error will be shown. If it is a thick jail, it will be updated just like
the release shown above.

View File

@@ -0,0 +1,16 @@
=======
upgrade
=======
The `upgrade` command targets a thick or thin jail. Thin jails will be updated by changing the
release mount point that it is based on. Thick jails will be upgraded normally.
.. code-block:: shell
ishmael ~ # bastille upgrade help
Usage: bastille upgrade [option(s)] TARGET [NEWRELEASE|install]
Options:
-a | --auto Auto mode. Start/stop jail(s) if required.
-f | --force Force upgrade a jail.
-x | --debug Enable debug mode.

View File

@@ -6,8 +6,8 @@ Looking for ready made CI/CD validated `Bastille Templates`_?
Bastille supports a templating system allowing you to apply files, pkgs and
execute commands inside the containers automatically.
Currently supported template hooks are: `CMD`, `CP`, `INCLUDE`, `LIMITS`, `MOUNT`,
`PKG`, `RDR`, `SERVICE`, `SYSRC`.
Currently supported template hooks are: `ARG`, `CMD`, `CONFIG`, `CP`, `INCLUDE`,
`LIMITS`, `MOUNT`, `OVERLAY`, `PKG`, `RDR`, `RENDER`, `RESTART`, `SERVICE`, `SYSRC`.
Templates are created in `${bastille_prefix}/templates` and can leverage any of
the template hooks.
@@ -23,27 +23,75 @@ template hook commands.
Template Automation Hooks
-------------------------
+---------+-------------------+-----------------------------------------+
| HOOK | format | example |
+=========+===================+=========================================+
| CMD | /bin/sh command | /usr/bin/chsh -s /usr/local/bin/zsh |
+---------+-------------------+-----------------------------------------+
| CP | path(s) | etc root usr (one per line) |
+---------+-------------------+-----------------------------------------+
| INCLUDE | template path/URL | http?://TEMPLATE_URL or project/path |
+---------+-------------------+-----------------------------------------+
| LIMITS | resource value | memoryuse 1G |
+---------+-------------------+-----------------------------------------+
| MOUNT | fstab syntax | /host/path container/path nullfs ro 0 0 |
+---------+-------------------+-----------------------------------------+
| PKG | port/pkg name(s) | vim-console zsh git-lite tree htop |
+---------+-------------------+-----------------------------------------+
| RDR | tcp port port | tcp 2200 22 (hostport jailport) |
+---------+-------------------+-----------------------------------------+
| SERVICE | service command | 'nginx start' OR 'postfix reload' |
+---------+-------------------+-----------------------------------------+
| SYSRC | sysrc command(s) | nginx_enable=YES |
+---------+-------------------+-----------------------------------------+
+-------------+---------------------+-----------------------------------------+
| HOOK | format | example |
+=============+=====================+=========================================+
| ARG | ARG=VALUE | MINECRAFT_MEMX="1024M" |
+-------------+---------------------+-----------------------------------------+
| CMD | /bin/sh command | /usr/bin/chsh -s /usr/local/bin/zsh |
+-------------+---------------------+-----------------------------------------+
| CONFIG | set property value | set allow.mlock 1 |
+-------------+---------------------+-----------------------------------------+
| CP/OVERLAY | path(s) | etc root usr (one per line) |
+-------------+---------------------+-----------------------------------------+
| INCLUDE | template path/URL | http?://TEMPLATE_URL or project/path |
+-------------+---------------------+-----------------------------------------+
| LIMITS | resource value | memoryuse 1G |
+-------------+---------------------+-----------------------------------------+
| MOUNT | fstab syntax | /host/path container/path nullfs ro 0 0 |
+-------------+---------------------+-----------------------------------------+
| OVERLAY | path(s) | etc root usr (one per line) |
+-------------+---------------------+-----------------------------------------+
| PKG | port/pkg name(s) | vim-console zsh git-lite tree htop |
+-------------+---------------------+-----------------------------------------+
| RDR | tcp port port | tcp 2200 22 (hostport jailport) |
+-------------+---------------------+-----------------------------------------+
| RENDER | /path/file.txt | /usr/local/etc/gitea/conf/app.ini |
+-------------+---------------------+-----------------------------------------+
| RESTART | | (restart jail) |
+-------------+---------------------+-----------------------------------------+
| SERVICE | service command | 'nginx start' OR 'postfix reload' |
+-------------+---------------------+-----------------------------------------+
| SYSRC | sysrc command(s) | nginx_enable=YES |
+-------------+---------------------+-----------------------------------------+
Template Hook Descriptions
--------------------------
ARG - set an ARG value to be used in the template
ARGS will default to the value set inside the template, but can be changed by including `--arg ARG=VALUE` when
running the template. Multiple ARGS can also be specified as seen below. If no ARG value is given, the template
will show a warning, but will still continue.
.. code-block:: shell
ishmael ~ # bastille template azkaban sample/template --arg ARG=VALUE --arg ARG1=VALUE
CMD - run the specified command
CONFIG - set the specified property and value
CP/OVERLAY - copy specified files from template directory to specified path inside jail
INCLUDE - specify a template to include. Make sure the template is bootstrapped, or you are using the template url
LIMITS - set the specified resource value for the jail
MOUNT - mount specified files/directories inside the jail
PKG - install specified packages inside jail
RDR - redirect specified ports to the jail
RENDER - replace ARG values inside specified files inside the jail. If a directory is specified, ARGS will be replaced in all files underneath
RESTART - restart the jail
SERVICE - run `service` command inside the jail with specified arguments
SYSRC - run `sysrc` inside the jail with specified arguments
Special Hook Cases
------------------
@@ -54,6 +102,9 @@ ie; (`\\"`)
ARG will always treat an ampersand "\&" literally, without the need to escape it.
Escaping it will cause errors.
Template Examples
-----------------
Place these uppercase template hook commands into a `Bastillefile` in any order
and automate container setup as needed.

View File

@@ -5,31 +5,88 @@ This document outlines upgrading jails hosted using Bastille.
Bastille can "bootstrap" multiple versions of FreeBSD to be used by jails. All jails do not NEED to be the same version (even if they often are), the only requirement here is that the "bootstrapped" versions are less than or equal to the host version of FreeBSD.
To keep releases updated, use `bastille update RELEASE`
To keep thick jails updated, use `bastille update TARGET`
======================
Minor Release Upgrades
======================
To upgrade Bastille jails for a minor release (ie; 13.1→13.2) you can do the following:
1. ensure the new release version is bootstrapped and updated to the latest patch release: `bastille bootstrap 13.2-RELEASE update`
2. stop the jail(s) that need to be updated.
3. use `bastille edit TARGET fstab` to manually update the jail mounts from 13.1 to 13.2 release path.
4. start the jail(s) that were edited
5. upgrade complete!
Thick Jails
===========
1. ensure the new release version is bootstrapped and updated to the latest patch release: `bastille bootstrap 13.2-RELEASE`
2. update the release: `bastille update 13.2-RELEASE`
3. use `bastille upgrade TARGET 13.2-RELEASE` to upgrade the jail to 13.2-RELEASE
4. use `bastille upgrade TARGET 13.2-RELEASE update` to apply the updates
5. reboot the jail `bastille restart TARGET`
6. use `bastille upgrade TARGET 13.2-RELEASE update` to finish applying the upgrade
7. upgrade complete!
Thin Jails
==========
1. ensure the new release version is bootstrapped and updated to the latest patch release: `bastille bootstrap 13.2-RELEASE`
2. update the release: `bastille update 13.2-RELEASE`
3. stop the jail(s) that need to be updated.
4. use `bastille upgrade TARGET 13.2-RELEASE` to automatically change the mount points to 13.2-RELEASE
5. use `bastille etcupdate bootstrap 13.2-RELEASE` to bootstrap src for 13.2-RELEASE
6. use `bastille etcupdate TARGET update 13.2-RELEASE` to update the contents of /etc for 13.2-RELEASE
7. use `bastille etcupdate TARGET reslove` to resolve any conflicts
8. start the jail(s)
8. upgrade complete!
======================
Major Release Upgrades
======================
To upgrade Bastille jails for a major release (ie; 12.4→13.2) you can do the following:
1. ensure the new version is bootstrapped and update to the latest patch release: `bastille bootstrap 13.2-RELEASE update`
2. stop the jail(s) that need to be updated.
3. use `bastille edit TARGET fstab` to manually update the jail mounts from 12.4 to 13.2 release path.
4. start the jail(s) that were edited
5. Force the reinstallation or upgrade of all installed packages (ABI change): `pkg upgrade -f` within each jail (or `bastille pkg ALL upgrade -f`)
6. restart the affected jail(s)
7. upgrade complete!
Thick Jails
===========
1. ensure the new release version is bootstrapped and updated to the latest patch release: `bastille bootstrap 13.2-RELEASE`
2. update the release: `bastille update 13.2-RELEASE`
3. use `bastille upgrade TARGET 13.2-RELEASE` to upgrade the jail to 13.2-RELEASE
4. use `bastille upgrade TARGET 13.2-RELEASE update` to apply the updates
5. reboot the jail `bastille restart TARGET`
6. use `bastille upgrade TARGET 13.2-RELEASE update` to finish applying the upgrade
7. force the reinstallation or upgrade of all installed packages (ABI change): `pkg upgrade -f` within each jail (or `bastille pkg ALL upgrade -f`)
8. upgrade complete!
Thin Jails
==========
1. ensure the new release version is bootstrapped and updated to the latest patch release: `bastille bootstrap 13.2-RELEASE`
2. update the release: `bastille update 13.2-RELEASE`
3. stop the jail(s) that need to be updated.
4. use `bastille upgrade TARGET 13.2-RELEASE` to automatically change the mount points to 13.2-RELEASE
5. use `bastille etcupdate bootstrap 13.2-RELEASE` to bootstrap src for 13.2-RELEASE
6. use `bastille etcupdate TARGET update 13.2-RELEASE` to update the contents of /etc for 13.2-RELEASE
7. use `bastille etcupdate TARGET reslove` to resolve any conflicts
8. start the jail(s)
9. force the reinstallation or upgrade of all installed packages (ABI change): `pkg upgrade -f` within each jail (or `bastille pkg ALL upgrade -f`)
10. upgrade complete!
Revert Upgrade / Downgrade Process
----------------------------------
The downgrade process (not usually needed) is similar to the upgrade process only in reverse.
If you did a minor upgrade changing the release path from 13.1 to 13.2, stop the jail and revert that change. Downgrade complete.
Thick Jails
===========
If you did a major upgrade changing the release path from 12.4 to 13.2, stop the jail and revert that change. The pkg reinstallation will also need to be repeated after the jail restarts on the previous release.
Thick jails should not be downgraded and is not supported in general on FreeBSD.
Thin Jails
==========
Not recommended, but you can run `bastille upgrade TARGET 13.1-RELEASE` to downgrade a thin jail.
Make sure to run `bastille etcupdate TARGET update 13.1-RELEASE` to keep the contents of /etc updated with each release.
The pkg reinstallation will also need to be repeated after the jail restarts on the previous release.
Old Releases
----------------------------------
@@ -40,4 +97,4 @@ After upgrading all jails from one release to the next you may find that you now
`bastille destroy X.Y-RELEASE` to fully delete the release.
`bastille destroy force X.Y-RELEASE` to delete the cache directory as well.
`bastille destroy [-f|--force] X.Y-RELEASE` to delete the cache directory as well.

View File

@@ -32,6 +32,7 @@ rcvar=${name}_enable
: ${bastille_conf:="/usr/local/etc/bastille/bastille.conf"}
: ${bastille_list:="ALL"}
: ${bastille_rcorder:="NO"}
: ${bastille_startup_delay:=0}
command=/usr/local/bin/${name}
start_cmd="bastille_start"
@@ -58,6 +59,7 @@ bastille_start()
fi
for _jail in ${bastille_ordered_list}; do
sleep ${bastille_startup_delay}
echo "Starting Bastille Container: ${_jail}"
${command} start ${_jail}
done

View File

@@ -571,9 +571,10 @@ create_jail() {
fi
# Join together IPv4 and IPv6 parts of ifconfig
_ifconfig="${_ifconfig_inet} ${_ifconfig_inet6}"
bastille template "${NAME}" ${bastille_template_vnet} --arg BASE_TEMPLATE="${bastille_template_base}" --arg HOST_RESOLV_CONF="${bastille_resolv_conf}" --arg EPAIR="${uniq_epair}" --arg GATEWAY="${_gateway}" --arg GATEWAY6="${_gateway6}" --arg IFCONFIG="${_ifconfig}"
bastille template "${NAME}" ${bastille_template_vnet} --arg EPAIR="${uniq_epair}" --arg GATEWAY="${_gateway}" --arg GATEWAY6="${_gateway6}" --arg IFCONFIG="${_ifconfig}"
fi
elif [ -n "${THICK_JAIL}" ]; then
fi
if [ -n "${THICK_JAIL}" ]; then
if [ -n "${bastille_template_thick}" ]; then
bastille template "${NAME}" ${bastille_template_thick} --arg BASE_TEMPLATE="${bastille_template_base}" --arg HOST_RESOLV_CONF="${bastille_resolv_conf}"
fi

View File

@@ -46,7 +46,7 @@ EOF
bootstrap_etc_release() {
local _release="${1}"
local _current="$(sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives | awk -F': ' '{print $2}')"
if ! ls -A "${bastille_releasesdir}/${_release}/usr/src" 2>/dev/null; then
if [ -z "$(ls -A "${bastille_releasesdir}/${_release}/usr/src")" ]; then
sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives=src
if ! bastille bootstrap "${_release}" > /dev/null; then
sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${_current}"

View File

@@ -34,7 +34,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 ] || [ "${1}" = "-h" ] || [ "${1}" = "--help" ]; then
@@ -208,7 +208,7 @@ list_template(){
list_jail(){
if [ -d "${bastille_jailsdir}" ]; then
JAIL_LIST=$(ls "${bastille_jailsdir}" | sed "s/\n//g")
JAIL_LIST=$(ls --color=never "${bastille_jailsdir}" | sed "s/\n//g")
for _JAIL in ${JAIL_LIST}; do
if [ -f "${bastille_jailsdir}/${_JAIL}/jail.conf" ]; then
echo "${_JAIL}"
@@ -230,12 +230,28 @@ list_import(){
ls "${bastille_backupsdir}" | grep -v ".sha256$"
}
list_ports(){
if [ -d "${bastille_jailsdir}" ]; then
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
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 "${2}"
;;

View File

@@ -34,172 +34,341 @@
. /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 [option(s)] TARGET [clear|reset|list|(tcp|udp)] HOST_PORT JAIL_PORT [log ['(' logopts ')'] ]"
cat << EOF
Options:
-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=""
EXT_IF=""
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}"
# 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')"
# 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}' | sed -E 's#/[0-9]+$##g')"
else
JAIL_IP="$(echo ${_ip4_interfaces} | sed -E 's#/[0-9]+$##g')"
fi
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
if echo "&{_ip6_interfaces}" | grep -q "|"; then
JAIL_IP6="$(echo ${_ip6_interfaces} | awk '{print $1}' | awk -F"|" '{print $2}' | sed -E 's#/[0-9]+$##g')"
else
JAIL_IP6="$(echo ${_ip6_interfaces} | sed -E 's#/[0-9]+$##g')"
fi
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
}
# Check if ext_if is defined in pf.conf
if [ -n "${bastille_pf_conf}" ]; then
EXT_IF=$(grep "^[[:space:]]*${bastille_network_pf_ext_if}[[:space:]]*=" ${bastille_pf_conf})
if [ -z "${EXT_IF}" ]; then
error_exit "bastille_network_pf_ext_if (${bastille_network_pf_ext_if}) not defined in pf.conf"
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
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 reset'."
fi
}
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"
fi
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}/${TARGET}/rdr.conf"; then
echo "$inet $if $src $dst $proto $host_port $jail_port" >> "${bastille_jailsdir}/${TARGET}/rdr.conf"
fi
}
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"
fi
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 "$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() {
( pfctl -a "rdr/${JAIL_NAME}" -Psn 2>/dev/null;
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" ) \
| pfctl -a "rdr/${JAIL_NAME}" -f-
if [ -n "$JAIL_IP6" ]; then
( pfctl -a "rdr/${JAIL_NAME}" -Psn 2>/dev/null;
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 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
# 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/${TARGET}" -f-; then
error_exit "Failed to create IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\""
else
info "[${TARGET}]:"
echo "IPv4 ${proto}/${host_port}:${jail_port} on ${if_name}"
fi
fi
# Create IPv6 rdr rule (if ip6.addr is enabled)
# 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/${TARGET}" -f-; then
error_exit "Failed to create IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\""
else
info "[${TARGET}]:"
echo "IPv6 ${proto}/${host_port}:${jail_port} on ${if_name}"
fi
fi
}
# function: load rdr rule with log via pfctl
load_rdr_log_rule() {
proto=$1;host_port=$2;jail_port=$3;
shift 3;
log=$@
( pfctl -a "rdr/${JAIL_NAME}" -Psn 2>/dev/null;
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" ) \
| pfctl -a "rdr/${JAIL_NAME}" -f-
if [ -n "$JAIL_IP6" ]; then
( pfctl -a "rdr/${JAIL_NAME}" -Psn 2>/dev/null;
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 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
# 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/${TARGET}" -f-; then
error_exit "Failed to create logged IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\""
else
info "[${TARGET}]:"
echo "IPv4 ${proto}/${host_port}:${jail_port} on ${if_name}"
fi
fi
# Create IPv6 rdr rule with log (if ip6.addr is enabled)
# 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/${TARGET}" -f-; then
error_exit "Failed to create logged IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\""
else
info "[${TARGET}]:"
echo "IPv6 ${proto}/${host_port}:${jail_port} on ${if_name}"
fi
fi
}
while [ $# -gt 0 ]; do
case "$1" in
# 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"
RDR_INET="dual"
OPTION_IF=0
OPTION_SRC=0
OPTION_DST=0
OPTION_INET_TYPE=0
while [ "$#" -gt 0 ]; do
case "${1}" in
-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
RDR_IF="${2}"
shift 2
else
error_exit "${2} is not a valid interface."
fi
;;
-s|--source)
check_rdr_ip_validity "${2}"
OPTION_SRC=1
RDR_SRC="${2}"
shift 2
;;
-t|--type)
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
;;
-x|--debug)
enable_debug
shift
;;
-*)
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 [ "${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
done
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
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 [ "${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
done
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
else
check_jail_validity
pfctl -a "rdr/${JAIL_NAME}" -Fn
echo "${TARGET} redirects:"
pfctl -a "rdr/${TARGET}" -Fn
fi
shift
;;
tcp|udp)
if [ $# -lt 3 ]; then
reset)
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
elif [ $# -eq 3 ]; then
check_jail_validity
persist_rdr_rule $1 $2 $3
load_rdr_rule $1 $2 $3
shift 3
else
case "$4" in
check_jail_validity
echo "${TARGET} redirects:"
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
usage
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
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
# Temp block to remove old format after new format is loaded the first time
while read rules; do
if [ "$(echo ${rules} | wc -w)" -lt 6 ]; then
sed -i '' "/^${rules}$/d" "${bastille_jailsdir}/${TARGET}/rdr.conf"
fi
done < "${bastille_jailsdir}/${TARGET}/rdr.conf"
shift "$#"
else
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 "$proto" "$host_port" "$jail_port" "$@"
load_rdr_log_rule "$proto" "$host_port" "$jail_port" "$@"
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 $#
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 "$@"
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
else
usage
@@ -212,7 +381,26 @@ while [ $# -gt 0 ]; do
fi
;;
*)
usage
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
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 "$#"
else
usage
fi
;;
esac
done

View File

@@ -1,6 +1,9 @@
ARG HOST_RESOLV_CONF=/etc/resolv.conf
CMD touch /etc/rc.conf
CMD touch /etc/periodic.conf
CMD sysrc -f /etc/periodic.conf daily_status_world_kernel="NO"
SYSRC syslogd_flags="-ss"
SYSRC sendmail_enable="NO"
SYSRC sendmail_submit_enable="NO"

View File

@@ -1,8 +1,3 @@
ARG BASE_TEMPLATE=default/base
ARG HOST_RESOLV_CONF=/etc/resolv.conf
INCLUDE ${BASE_TEMPLATE} --arg HOST_RESOLV_CONF="${HOST_RESOLV_CONF}"
ARG EPAIR
ARG GATEWAY
ARG GATEWAY6