2018-11-07 10:36:54 -07:00
#!/bin/sh
2020-04-14 11:52:29 +02:00
#
2025-01-11 14:07:41 -05:00
# SPDX-License-Identifier: BSD-3-Clause
#
# Copyright (c) 2018-2025, Christer Edwards <christer.edwards@gmail.com>
2018-11-07 10:36:54 -07:00
# All rights reserved.
2020-04-14 11:52:29 +02:00
#
2018-11-07 10:36:54 -07:00
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
2020-04-14 11:52:29 +02:00
#
2018-11-07 10:36:54 -07:00
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
2020-04-14 11:52:29 +02:00
#
2018-11-07 10:36:54 -07:00
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
2020-04-14 11:52:29 +02:00
#
2018-11-07 10:36:54 -07:00
# * Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
2020-04-14 11:52:29 +02:00
#
2018-11-07 10:36:54 -07:00
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2020-08-30 10:57:14 -04:00
. /usr/local/share/bastille/common.sh
2018-11-07 10:36:54 -07:00
usage( ) {
2021-07-12 14:54:00 -04:00
# Build an independent usage for the create command
# If no option specified, will create a thin container by default
2025-05-18 17:16:17 -06:00
error_notify "Usage: bastille create [option(s)] NAME RELEASE IP [INTERFACE]"
2021-07-12 14:54:00 -04:00
cat << EOF
2025-05-01 12:38:14 -06:00
2021-07-12 14:54:00 -04:00
Options:
2025-02-28 12:59:48 -07:00
2025-05-18 17:16:17 -06:00
-B | --bridge Enable VNET, and attach to a specified, already existing external bridge.
-C | --clone Create a clone jail.
-D | --dual Create jail with both IPv4 and IPv6 networking ( 'inherit' and 'ip_hostname' only) .
-E | --empty Create an empty container, intended for custom jail builds ( thin/thick/linux or unsupported) .
2025-05-20 09:00:48 -06:00
-g | --gateway IP Specify a default router/gateway for the jail.
2025-05-18 17:16:17 -06:00
-L | --linux Create a Linux jail ( experimental) .
-M | --static-mac Generate a static MAC address for jail ( VNET only) .
2025-05-21 09:18:20 -06:00
-n | --nameserver IP,IP Specify nameserver( s) for the jail. Comma separated.
2025-05-18 17:16:17 -06:00
--no-validate Do not validate the release when creating the jail.
--no-boot Create jail with boot = off.
-p | --priority VALUE Set priority value for jail.
-T | --thick Creates a thick container, they consume more space as they are self contained and independent.
-V | --vnet Enable VNET, and attach to an existing, physical interface.
-v | --vlan VLANID Creates the jail with specified VLAN ID ( VNET only) .
-x | --debug Enable debug mode.
2025-05-20 09:00:48 -06:00
-Z | --zfs-opts zfs,options Comma separated list of ZFS options to create the jail with. This overrides the defaults.
2021-07-12 14:54:00 -04:00
EOF
exit 1
2020-05-09 15:31:15 -04:00
}
validate_name( ) {
2025-05-01 12:38:14 -06:00
2020-05-09 15:31:15 -04:00
local NAME_VERIFY = ${ NAME }
2024-12-08 21:05:45 -05:00
local NAME_SANITY = " $( echo " ${ NAME_VERIFY } " | tr -c -d 'a-zA-Z0-9-_' ) "
2025-06-02 18:08:21 -06:00
# Make sure NAME has only allowed characters
2021-01-10 18:55:02 -04:00
if [ -n " $( echo " ${ NAME_SANITY } " | awk " /^[-_].* $/ " ) " ] ; then
2025-05-01 17:39:50 -06:00
error_exit "[ERROR]: Jail names may not begin with (-|_) characters!"
2021-01-10 18:55:02 -04:00
elif [ " ${ NAME_VERIFY } " != " ${ NAME_SANITY } " ] ; then
2025-05-01 17:39:50 -06:00
error_exit "[ERROR]: Jail names may not contain special characters!"
2025-01-20 19:25:02 -07:00
elif echo " ${ NAME_VERIFY } " | grep -qE '^[0-9]+$' ; then
2025-05-01 17:39:50 -06:00
error_exit "[ERROR]: Jail names may not contain only digits."
2019-12-29 23:04:19 -04:00
fi
2018-11-07 10:36:54 -07:00
}
validate_ip( ) {
2025-05-01 12:38:14 -06:00
2025-06-02 18:08:21 -06:00
local _ip = " ${ 1 } "
2025-06-02 18:20:08 -06:00
local _ip6 = " $( echo ${ _ip } | grep -E '^(([a-fA-F0-9:]+$)|([a-fA-F0-9:]+\/[0-9]{1,3}$)|SLAAC)' ) "
2025-05-01 12:38:14 -06:00
2025-01-28 17:31:51 -07:00
if [ -n " ${ _ip6 } " ] ; then
2025-05-01 12:38:14 -06:00
info " \nValid: ( ${ _ip6 } ). "
2025-06-02 19:35:55 -06:00
# This is only used in this function to set IPX_DEFINITION
2025-06-02 18:08:21 -06:00
local ipx_addr = "ip6.addr"
2018-11-07 10:36:54 -07:00
else
2025-06-02 18:08:21 -06:00
if [ " ${ _ip } " = "inherit" ] || [ " ${ _ip } " = "ip_hostname" ] ; then
2025-06-02 19:35:55 -06:00
if [ -n " ${ VNET_JAIL } " ] ; then
2025-06-02 18:08:21 -06:00
error_exit " [ERROR]: Unsupported IP option for standard jail: ( ${ _ip } ). "
2025-06-02 19:35:55 -06:00
else
2025-06-02 18:08:21 -06:00
info " \nValid: ( ${ _ip } ). "
2025-06-02 19:35:55 -06:00
fi
2025-06-02 18:08:21 -06:00
elif [ " ${ _ip } " = "DHCP" ] || [ " ${ _ip } " = "SYNCDHCP" ] || [ " ${ _ip } " = "0.0.0.0" ] ; then
2025-06-02 19:35:55 -06:00
if [ -z " ${ VNET_JAIL } " ] ; then
2025-06-02 18:08:21 -06:00
error_exit " [ERROR]: Unsupported IP option for VNET jail: ( ${ _ip } ). "
2025-06-02 19:35:55 -06:00
else
2025-06-02 18:08:21 -06:00
info " \nValid: ( ${ _ip } ). "
2025-06-02 19:35:55 -06:00
fi
2021-08-07 19:57:53 +02:00
else
local IFS
2025-01-28 17:31:51 -07:00
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)
2021-08-07 19:57:53 +02:00
IFS = .
set ${ TEST_IP }
for quad in 1 2 3 4; do
if eval [ \$ $quad -gt 255 ] ; then
2025-01-28 17:31:51 -07:00
error_continue " Invalid: ( ${ TEST_IP } ) "
2021-08-07 19:57:53 +02:00
fi
done
2025-04-14 20:46:43 -06:00
ipx_addr = "ip4.addr"
2025-05-01 12:38:14 -06:00
info " \nValid: ( ${ _ip } ). "
2020-02-16 13:22:32 -04:00
else
2025-01-28 17:31:51 -07:00
error_continue " Invalid: ( ${ _ip } ). "
2020-02-16 13:22:32 -04:00
fi
2021-08-07 19:57:53 +02:00
fi
fi
2025-05-01 12:38:14 -06:00
# Warn if IP is in use
if ifconfig | grep -qwF " ${ TEST_IP } " ; then
warn " [WARNING]: IP address in use ( ${ TEST_IP } ). "
fi
2025-01-28 17:31:51 -07:00
# 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
2025-05-01 12:38:14 -06:00
2025-01-28 17:31:51 -07:00
# Determine IP/Interface mode
if [ " ${ _ip } " = "inherit" ] ; then
if [ -n " ${ DUAL_STACK } " ] ; then
IP4_DEFINITION = " ip4 = ${ _ip } ; "
IP6_DEFINITION = " ip6 = ${ _ip } ; "
IP6_MODE = "new"
2020-02-16 13:22:32 -04:00
else
2025-01-28 17:31:51 -07:00
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
2025-06-02 18:08:21 -06:00
elif [ " ${ _ip } " = "DHCP" ] || [ " ${ _ip } " = "SLAAC" ] || [ " ${ _ip } " = "0.0.0.0" ] ; then
if [ -n " ${ VNET_JAIL } " ] ; then
if [ " ${ ipx_addr } " = "ip4.addr" ] ; then
IP4_ADDR = " ${ _ip } "
elif [ " ${ ipx_addr } " = "ip6.addr" ] ; then
IP6_ADDR = " ${ _ip } "
fi
else
error_exit " [ERROR]: Unsupported IP option for standard jail: ( ${ _ip } ). "
fi
else
2025-01-28 17:31:51 -07:00
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"
2020-02-16 13:22:32 -04:00
fi
2018-11-07 10:36:54 -07:00
fi
}
2025-01-28 17:31:51 -07:00
2021-08-07 19:57:53 +02:00
validate_ips( ) {
2025-05-01 12:38:14 -06:00
2021-08-07 19:57:53 +02:00
IP6_MODE = "disable"
IP4_DEFINITION = ""
IP6_DEFINITION = ""
IP4_ADDR = ""
IP6_ADDR = ""
2025-01-28 17:31:51 -07:00
IP_HOSTNAME = ""
2025-05-01 12:38:14 -06:00
2021-08-07 19:57:53 +02:00
for ip in ${ IP } ; do
validate_ip " ${ ip } "
done
}
2018-11-07 10:36:54 -07:00
2019-10-24 17:02:50 -04:00
validate_netif( ) {
2025-05-01 12:38:14 -06:00
2024-12-08 21:05:45 -05:00
local LIST_INTERFACES = " $( ifconfig -l) "
2025-05-01 12:38:14 -06:00
2025-05-22 10:12:21 -06:00
if ! echo " ${ LIST_INTERFACES } VNET " | grep -qwo " ${ INTERFACE } " ; then
2025-05-01 17:39:50 -06:00
error_exit " [ERROR]: Invalid: ( ${ INTERFACE } ). "
2025-05-22 10:12:21 -06:00
elif [ -n " ${ VNET_JAIL } " ] && [ -z " ${ VNET_JAIL_BRIDGE } " ] ; then
for _bridge in $( ifconfig -g bridge | grep -vw " ${ INTERFACE } bridge " ) ; do
if ifconfig ${ _bridge } | grep "member" | grep -owq " ${ INTERFACE } " ; then
error_exit " [ERROR]: Interface ( ${ INTERFACE } ) is already a member of bridge: ${ _bridge } "
fi
done
else
info " \nValid: ( ${ INTERFACE } ). "
2019-10-24 17:02:50 -04:00
fi
2025-05-21 12:41:35 -06:00
# Don't allow dots in INTERFACE if -V
2025-05-21 18:39:04 -06:00
if [ -n " ${ VNET_JAIL } " ] && [ -z " ${ VNET_JAIL_BRIDGE } " ] ; then
2025-05-21 12:41:35 -06:00
if echo " ${ INTERFACE } " | grep -q "\." ; then
2025-05-21 18:40:37 -06:00
error_exit "[ERROR]: [-V|--vnet] does not support dots (.) in interface names."
2025-05-21 12:41:35 -06:00
fi
fi
2019-10-24 17:02:50 -04:00
}
2020-02-02 02:42:22 -04:00
validate_release( ) {
2025-05-01 12:38:14 -06:00
2021-07-15 16:30:36 -04:00
## ensure the user set the Linux(experimental) option explicitly
if [ -n " ${ UBUNTU } " ] ; then
if [ -z " ${ LINUX_JAIL } " ] ; then
usage
fi
fi
2020-02-02 02:42:22 -04:00
## check release name match, else show usage
if [ -n " ${ NAME_VERIFY } " ] ; then
RELEASE = " ${ NAME_VERIFY } "
else
usage
fi
}
2020-04-18 18:02:11 -04:00
generate_minimal_conf( ) {
2025-05-01 12:38:14 -06:00
2020-04-18 18:02:11 -04:00
cat << EOF > " ${ bastille_jail_conf } "
${ NAME } {
host.hostname = ${ NAME } ;
mount.fstab = ${ bastille_jail_fstab } ;
path = ${ bastille_jail_path } ;
}
EOF
touch " ${ bastille_jail_fstab } "
}
2020-02-16 15:20:31 -07:00
generate_jail_conf( ) {
2025-05-01 12:38:14 -06:00
2025-01-28 17:38:52 -07:00
if [ " $( sysctl -n security.jail.jailed) " -eq 1 ] ; then
devfs_ruleset_value = 0
else
devfs_ruleset_value = 4
fi
2020-02-20 18:06:31 -04:00
cat << EOF > " ${ bastille_jail_conf } "
2020-02-16 15:20:31 -07:00
${ NAME } {
enforce_statfs = 2;
2025-01-28 17:38:52 -07:00
devfs_ruleset = ${ devfs_ruleset_value } ;
2020-02-16 15:20:31 -07:00
exec.clean;
exec.consolelog = ${ bastille_jail_log } ;
exec.start = '/bin/sh /etc/rc' ;
exec.stop = '/bin/sh /etc/rc.shutdown' ;
host.hostname = ${ NAME } ;
mount.devfs;
mount.fstab = ${ bastille_jail_fstab } ;
path = ${ bastille_jail_path } ;
securelevel = 2;
2023-11-19 14:37:31 -07:00
osrelease = ${ RELEASE } ;
2020-02-16 15:20:31 -07:00
2021-08-07 19:57:53 +02:00
${ IP4_DEFINITION }
${ IP6_DEFINITION }
2020-02-16 15:22:32 -07:00
ip6 = ${ IP6_MODE } ;
2020-02-16 15:20:31 -07:00
}
EOF
}
2021-07-12 14:45:37 -04:00
generate_linux_jail_conf( ) {
2025-05-01 12:38:14 -06:00
2021-07-12 14:45:37 -04:00
cat << EOF > " ${ bastille_jail_conf } "
${ NAME } {
host.hostname = ${ NAME } ;
mount.fstab = ${ bastille_jail_fstab } ;
path = ${ bastille_jail_path } ;
2025-01-28 17:31:51 -07:00
devfs_ruleset = 4;
2022-03-04 08:16:33 -08:00
enforce_statfs = 1;
2021-07-12 14:54:00 -04:00
2021-07-12 14:45:37 -04:00
exec.start = '/bin/true' ;
exec.stop = '/bin/true' ;
persist;
2021-07-12 14:54:00 -04:00
2021-07-12 14:45:37 -04:00
allow.mount;
allow.mount.devfs;
2021-07-12 14:54:00 -04:00
2025-01-28 17:31:51 -07:00
${ IP4_DEFINITION }
${ IP6_DEFINITION }
2021-07-12 14:45:37 -04:00
ip6 = ${ IP6_MODE } ;
}
EOF
}
2020-02-16 15:20:31 -07:00
generate_vnet_jail_conf( ) {
2025-05-01 12:38:14 -06:00
2025-01-28 17:38:52 -07:00
if [ " $( sysctl -n security.jail.jailed) " -eq 1 ] ; then
devfs_ruleset_value = 0
else
devfs_ruleset_value = 13
fi
2025-05-01 12:38:14 -06:00
2025-03-03 12:28:23 -07:00
NETBLOCK = $( generate_vnet_jail_netblock " ${ NAME } " " ${ VNET_JAIL_BRIDGE } " " ${ bastille_jail_conf_interface } " " ${ STATIC_MAC } " )
2025-05-01 12:38:14 -06:00
2020-02-20 18:06:31 -04:00
cat << EOF > " ${ bastille_jail_conf } "
2020-02-16 15:20:31 -07:00
${ NAME } {
enforce_statfs = 2;
2025-01-28 17:38:52 -07:00
devfs_ruleset = ${ devfs_ruleset_value } ;
2020-02-16 15:20:31 -07:00
exec.clean;
exec.consolelog = ${ bastille_jail_log } ;
exec.start = '/bin/sh /etc/rc' ;
exec.stop = '/bin/sh /etc/rc.shutdown' ;
host.hostname = ${ NAME } ;
mount.devfs;
mount.fstab = ${ bastille_jail_fstab } ;
path = ${ bastille_jail_path } ;
securelevel = 2;
2023-11-19 14:37:31 -07:00
osrelease = ${ RELEASE } ;
2020-02-16 15:20:31 -07:00
2022-01-09 19:22:16 -08:00
${ NETBLOCK }
2020-02-16 15:20:31 -07:00
}
EOF
}
2022-01-15 11:32:28 -04:00
post_create_jail( ) {
2025-05-01 12:38:14 -06:00
2022-01-15 11:32:28 -04:00
# Common config checks and settings.
# Using relative paths here.
# MAKE SURE WE'RE IN THE RIGHT PLACE.
2025-01-28 17:31:51 -07:00
cd " ${ bastille_jail_path } " || error_exit " Could not cd to ${ bastille_jail_path } "
2022-01-15 11:32:28 -04:00
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
if [ ! -f " ${ bastille_jail_fstab } " ] ; then
if [ -z " ${ THICK_JAIL } " ] && [ -z " ${ CLONE_JAIL } " ] ; then
echo -e " ${ bastille_releasesdir } / ${ RELEASE } ${ bastille_jail_base } nullfs ro 0 0 " > " ${ bastille_jail_fstab } "
else
touch " ${ bastille_jail_fstab } "
fi
fi
# Generate the jail configuration file.
if [ -n " ${ VNET_JAIL } " ] ; then
generate_vnet_jail_conf
else
generate_jail_conf
fi
}
2018-11-07 10:36:54 -07:00
create_jail( ) {
2025-05-01 12:38:14 -06:00
2018-11-07 10:36:54 -07:00
bastille_jail_base = " ${ bastille_jailsdir } / ${ NAME } /root/.bastille " ## dir
bastille_jail_template = " ${ bastille_jailsdir } / ${ NAME } /root/.template " ## dir
bastille_jail_path = " ${ bastille_jailsdir } / ${ NAME } /root " ## dir
bastille_jail_fstab = " ${ bastille_jailsdir } / ${ NAME } /fstab " ## file
bastille_jail_conf = " ${ bastille_jailsdir } / ${ NAME } /jail.conf " ## file
bastille_jail_log = " ${ bastille_logsdir } / ${ NAME } _console.log " ## file
2024-12-08 21:05:45 -05:00
# shellcheck disable=SC2034
2019-05-22 21:50:29 -06:00
bastille_jail_rc_conf = " ${ bastille_jailsdir } / ${ NAME } /root/etc/rc.conf " ## file
2024-12-08 21:05:45 -05:00
# shellcheck disable=SC2034
2018-11-07 10:36:54 -07:00
bastille_jail_resolv_conf = " ${ bastille_jailsdir } / ${ NAME } /root/etc/resolv.conf " ## file
2019-06-22 09:28:42 -06:00
if [ ! -d " ${ bastille_jailsdir } / ${ NAME } " ] ; then
2023-11-25 15:09:11 -07:00
if checkyesno bastille_zfs_enable; then
2020-02-20 18:06:31 -04:00
if [ -n " ${ bastille_zfs_zpool } " ] ; then
2020-02-15 07:57:33 -04:00
## create required zfs datasets, mountpoint inherited from system
2022-01-15 11:32:28 -04:00
if [ -z " ${ CLONE_JAIL } " ] ; then
zfs create ${ bastille_zfs_options } " ${ bastille_zfs_zpool } / ${ bastille_zfs_prefix } /jails/ ${ NAME } "
fi
if [ -z " ${ THICK_JAIL } " ] && [ -z " ${ CLONE_JAIL } " ] ; then
2020-02-20 18:06:31 -04:00
zfs create ${ bastille_zfs_options } " ${ bastille_zfs_zpool } / ${ bastille_zfs_prefix } /jails/ ${ NAME } /root "
2019-11-18 03:51:06 -04:00
fi
2019-06-22 09:28:42 -06:00
fi
else
2020-04-18 18:02:11 -04:00
mkdir -p " ${ bastille_jailsdir } / ${ NAME } /root "
2019-06-22 09:28:42 -06:00
fi
2025-05-04 15:23:52 -06:00
# Check if the jail directory has been mounted under UFS (not supported)
2025-04-22 10:30:46 -06:00
elif [ ! -d " ${ bastille_jailsdir } / ${ NAME } /root " ] && ! checkyesno bastille_zfs_enable; then
if mount | grep " ${ bastille_jailsdir } / ${ NAME } " | grep -oq "ufs" ; then
2025-05-04 15:23:52 -06:00
error_exit "[ERROR]: Using UFS mounts for the jail directory is not supported."
2025-04-22 10:30:46 -06:00
fi
2019-06-22 09:28:42 -06:00
fi
2022-01-15 11:32:28 -04:00
2025-04-22 10:30:46 -06:00
2021-07-12 14:45:37 -04:00
## PoC for Linux jails @hackacad
if [ -n " ${ LINUX_JAIL } " ] ; then
2022-01-15 11:32:28 -04:00
info "\nCreating a linuxjail. This may take a while...\n"
2021-07-12 14:45:37 -04:00
if [ ! -d " ${ bastille_jail_base } " ] ; then
mkdir -p " ${ bastille_jail_base } "
fi
mkdir -p " ${ bastille_jail_path } /dev "
mkdir -p " ${ bastille_jail_path } /proc "
mkdir -p " ${ bastille_jail_path } /sys "
mkdir -p " ${ bastille_jail_path } /home "
2021-07-12 14:54:00 -04:00
mkdir -p " ${ bastille_jail_path } /tmp "
2021-07-12 14:45:37 -04:00
touch " ${ bastille_jail_path } /dev/shm "
touch " ${ bastille_jail_path } /dev/fd "
cp -RPf ${ bastille_releasesdir } /${ RELEASE } /* ${ bastille_jail_path } /
2021-07-15 21:26:35 +10:00
echo " ${ NAME } " > ${ bastille_jail_path } /etc/hostname
2019-06-22 09:28:42 -06:00
2021-07-12 14:45:37 -04:00
if [ ! -d " ${ bastille_jail_template } " ] ; then
mkdir -p " ${ bastille_jail_template } "
fi
if [ ! -f " ${ bastille_jail_fstab } " ] ; then
touch " ${ bastille_jail_fstab } "
fi
2021-07-15 20:52:16 +10:00
echo -e " devfs ${ bastille_jail_path } /dev devfs rw 0 0 " >> " ${ bastille_jail_fstab } "
echo -e " tmpfs ${ bastille_jail_path } /dev/shm tmpfs rw,size=1g,mode=1777 0 0 " >> " ${ bastille_jail_fstab } "
echo -e " fdescfs ${ bastille_jail_path } /dev/fd fdescfs rw,linrdlnk 0 0 " >> " ${ bastille_jail_fstab } "
echo -e " linprocfs ${ bastille_jail_path } /proc linprocfs rw 0 0 " >> " ${ bastille_jail_fstab } "
echo -e " linsysfs ${ bastille_jail_path } /sys linsysfs rw 0 0 " >> " ${ bastille_jail_fstab } "
echo -e " /tmp ${ bastille_jail_path } /tmp nullfs rw 0 0 " >> " ${ bastille_jail_fstab } "
2021-07-12 14:54:00 -04:00
## removed temporarely / only for X11 jails? @hackacad
2021-07-15 20:52:16 +10:00
#echo -e "/home ${bastille_jail_path}/home nullfs rw 0 0" >> "${bastille_jail_fstab}"
2021-07-12 14:45:37 -04:00
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
fi
if [ -z " ${ EMPTY_JAIL } " ] && [ -z " ${ LINUX_JAIL } " ] ; then
2022-01-15 11:32:28 -04:00
if [ -z " ${ THICK_JAIL } " ] && [ -z " ${ CLONE_JAIL } " ] ; then
if [ ! -d " ${ bastille_jail_base } " ] ; then
mkdir -p " ${ bastille_jail_base } "
fi
if [ ! -d " ${ bastille_jail_template } " ] ; then
mkdir -p " ${ bastille_jail_template } "
fi
2019-11-17 18:15:19 -04:00
fi
2018-11-07 10:36:54 -07:00
2020-04-18 18:02:11 -04:00
if [ ! -d " ${ bastille_jail_path } /usr/local " ] ; then
mkdir -p " ${ bastille_jail_path } /usr/local "
2020-02-16 15:20:31 -07:00
fi
2018-11-07 10:36:54 -07:00
2022-01-15 11:32:28 -04:00
# Check and apply required settings.
post_create_jail
2018-11-07 10:36:54 -07:00
2022-01-15 11:32:28 -04:00
if [ -z " ${ THICK_JAIL } " ] && [ -z " ${ CLONE_JAIL } " ] ; then
2021-07-07 05:05:38 -04:00
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"
2025-04-30 11:21:41 -06:00
info "\nCreating a thinjail..."
2020-05-07 22:50:43 -04:00
for _link in ${ LINK_LIST } ; do
2020-04-18 18:02:11 -04:00
ln -sf /.bastille/${ _link } ${ _link }
done
2022-01-15 11:32:28 -04:00
2021-07-07 05:05:38 -04:00
# Properly link shared ports on thin jails in read-write.
2021-01-08 22:37:18 -04:00
if [ -d " ${ bastille_releasesdir } / ${ RELEASE } /usr/ports " ] ; then
if [ ! -d " ${ bastille_jail_path } /usr/ports " ] ; then
2021-07-07 05:05:38 -04:00
mkdir ${ bastille_jail_path } /usr/ports
2021-01-08 22:37:18 -04:00
fi
2021-07-07 05:05:38 -04:00
echo -e " ${ bastille_releasesdir } / ${ RELEASE } /usr/ports ${ bastille_jail_path } /usr/ports nullfs rw 0 0 " >> " ${ bastille_jail_fstab } "
2021-01-08 22:37:18 -04:00
fi
2020-04-18 18:02:11 -04:00
fi
2019-11-18 03:51:06 -04:00
2022-01-15 11:32:28 -04:00
if [ -z " ${ THICK_JAIL } " ] && [ -z " ${ CLONE_JAIL } " ] ; then
2020-04-18 18:02:11 -04:00
## rw
## copy only required files for thin jails
FILE_LIST = ".cshrc .profile COPYRIGHT dev etc media mnt net proc root tmp var usr/obj usr/tests"
for files in ${ FILE_LIST } ; do
if [ -f " ${ bastille_releasesdir } / ${ RELEASE } / ${ files } " ] || [ -d " ${ bastille_releasesdir } / ${ RELEASE } / ${ files } " ] ; then
2021-07-14 13:57:09 -04:00
if ! cp -a " ${ bastille_releasesdir } / ${ RELEASE } / ${ files } " " ${ bastille_jail_path } / ${ files } " ; then
2020-04-18 18:02:11 -04:00
## notify and clean stale files/directories
2025-03-12 13:33:23 -06:00
bastille destroy -af " ${ NAME } "
2025-05-01 17:39:50 -06:00
error_exit "[ERROR]: Failed to copy release files. Please retry create!"
2020-04-18 18:02:11 -04:00
fi
fi
done
else
2023-11-25 15:09:11 -07:00
if checkyesno bastille_zfs_enable; then
2020-04-18 18:02:11 -04:00
if [ -n " ${ bastille_zfs_zpool } " ] ; then
2022-01-15 11:32:28 -04:00
if [ -n " ${ CLONE_JAIL } " ] ; then
2025-04-30 11:21:41 -06:00
info "\nCreating a clonejail...\n"
2022-01-15 11:32:28 -04:00
## clone the release base to the new basejail
SNAP_NAME = " bastille-clone- $( date +%Y-%m-%d-%H%M%S) "
2025-04-22 09:08:42 -06:00
# shellcheck disable=SC2140
2024-12-15 11:02:28 -05:00
zfs snapshot " ${ bastille_zfs_zpool } / ${ bastille_zfs_prefix } /releases/ ${ RELEASE } " @" ${ SNAP_NAME } "
2025-04-22 09:08:42 -06:00
# shellcheck disable=SC2140
zfs clone -p " ${ bastille_zfs_zpool } / ${ bastille_zfs_prefix } /releases/ ${ RELEASE } " @" ${ SNAP_NAME } " \
2022-01-15 11:32:28 -04:00
" ${ bastille_zfs_zpool } / ${ bastille_zfs_prefix } /jails/ ${ NAME } /root "
# Check and apply required settings.
post_create_jail
elif [ -n " ${ THICK_JAIL } " ] ; then
2025-05-01 17:39:50 -06:00
info "\nCreating a thickjail. This may take a while..."
## perform release base replication
2022-01-15 11:32:28 -04:00
## sane bastille zfs options
ZFS_OPTIONS = $( echo ${ bastille_zfs_options } | sed 's/-o//g' )
2025-04-26 14:58:26 -06:00
## send without -R if encryption is enabled
2025-02-25 15:40:41 -07:00
if [ " $( zfs get -H -o value encryption " ${ bastille_zfs_zpool } / ${ bastille_zfs_prefix } " ) " = "off" ] ; then
2025-04-26 14:58:26 -06:00
OPT_SEND = "-R"
2025-02-25 15:37:44 -07:00
else
2025-04-26 14:58:26 -06:00
OPT_SEND = ""
2025-02-25 15:37:44 -07:00
fi
2022-01-15 11:32:28 -04:00
## take a temp snapshot of the base release
SNAP_NAME = " bastille- $( date +%Y-%m-%d-%H%M%S) "
2025-04-22 09:08:42 -06:00
# shellcheck disable=SC2140
2024-12-15 11:02:28 -05:00
zfs snapshot " ${ bastille_zfs_zpool } / ${ bastille_zfs_prefix } /releases/ ${ RELEASE } " @" ${ SNAP_NAME } "
2022-01-15 11:32:28 -04:00
## replicate the release base to the new thickjail and set the default mountpoint
2025-04-22 09:08:42 -06:00
# shellcheck disable=SC2140
2025-02-25 15:37:44 -07:00
zfs send ${ OPT_SEND } " ${ bastille_zfs_zpool } / ${ bastille_zfs_prefix } /releases/ ${ RELEASE } " @" ${ SNAP_NAME } " | \
2022-01-15 11:32:28 -04:00
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
2025-04-22 09:08:42 -06:00
# shellcheck disable=SC2140
2024-12-15 11:02:28 -05:00
zfs destroy " ${ bastille_zfs_zpool } / ${ bastille_zfs_prefix } /releases/ ${ RELEASE } " @" ${ SNAP_NAME } "
2025-04-22 09:08:42 -06:00
# shellcheck disable=SC2140
2024-12-15 11:02:28 -05:00
zfs destroy " ${ bastille_zfs_zpool } / ${ bastille_zfs_prefix } /jails/ ${ NAME } /root " @" ${ SNAP_NAME } "
2022-01-15 11:32:28 -04:00
fi
2020-04-18 18:02:11 -04:00
if [ " $? " -ne 0 ] ; then
## notify and clean stale files/directories
2025-03-12 13:33:23 -06:00
bastille destroy -af " ${ NAME } "
2025-05-01 17:39:50 -06:00
error_exit "[ERROR]: Failed release base replication. Please retry create!"
2020-04-18 18:02:11 -04:00
fi
fi
else
## copy all files for thick jails
cp -a " ${ bastille_releasesdir } / ${ RELEASE } / " " ${ bastille_jail_path } "
2020-02-20 18:06:31 -04:00
if [ " $? " -ne 0 ] ; then
2019-11-18 03:51:06 -04:00
## notify and clean stale files/directories
2025-05-17 10:18:52 -06:00
bastille destroy -afy " ${ NAME } "
2025-05-01 12:38:14 -06:00
error_exit "[ERROR]: Failed to copy release files. Please retry create!"
2019-11-18 03:51:06 -04:00
fi
fi
2019-11-17 18:15:19 -04:00
fi
2021-07-12 14:54:00 -04:00
2021-07-12 14:45:37 -04:00
if [ -z " ${ LINUX_JAIL } " ] ; then
## create home directory if missing
if [ ! -d " ${ bastille_jail_path } /usr/home " ] ; then
mkdir -p " ${ bastille_jail_path } /usr/home "
fi
## link home properly
if [ ! -L "home" ] ; then
ln -s usr/home home
fi
2021-07-12 14:54:00 -04:00
2021-12-12 12:10:39 -05:00
## TZ: configurable (default: empty to use host's time zone)
if [ -z " ${ bastille_tzdata } " ] ; then
2021-12-12 12:38:05 -05:00
# Note that if host has no time zone, FreeBSD assumes UTC anyway
if [ -e /etc/localtime ] ; then
# uses cp as a way to prevent issues with symlinks if the host happens to use that for tz configuration
cp /etc/localtime etc/localtime
fi
2021-12-12 12:10:39 -05:00
else
ln -s " /usr/share/zoneinfo/ ${ bastille_tzdata } " etc/localtime
fi
2021-07-12 14:54:00 -04:00
2021-07-12 14:45:37 -04:00
# Post-creation jail misc configuration
# Create a dummy fstab file
touch "etc/fstab"
# Disables adjkerntz, avoids spurious error messages
sed -i '' 's|[0-9],[0-9]\{2\}.*[0-9]-[0-9].*root.*kerntz -a|#& # Disabled by bastille|' "etc/crontab"
fi
2021-07-12 14:54:00 -04:00
2020-11-26 12:44:40 -05:00
## VNET specific
if [ -n " ${ VNET_JAIL } " ] ; then
2025-04-25 14:33:38 -06:00
## VNET requires jib or jng script
if [ " ${ bastille_network_vnet_type } " = "if_bridge" ] ; then
if [ ! " $( command -v jib) " ] ; then
if [ -f /usr/share/examples/jails/jib ] && [ ! -f /usr/local/bin/jib ] ; then
install -m 0544 /usr/share/examples/jails/jib /usr/local/bin/jib
fi
fi
elif [ " ${ bastille_network_vnet_type } " = "netgraph" ] ; then
2025-04-25 20:33:09 -06:00
if [ ! " $( command -v jng) " ] ; then
2025-04-25 14:33:38 -06:00
if [ -f /usr/share/examples/jails/jng ] && [ ! -f /usr/local/bin/jng ] ; then
install -m 0544 /usr/share/examples/jails/jng /usr/local/bin/jng
fi
2025-04-26 11:04:09 -06:00
fi
2020-02-18 17:04:06 -04:00
fi
2020-02-16 15:20:31 -07:00
fi
2021-07-12 14:45:37 -04:00
elif [ -n " ${ LINUX_JAIL } " ] ; then
2021-07-12 14:54:00 -04:00
## Generate configuration for Linux jail
2021-07-12 14:45:37 -04:00
generate_linux_jail_conf
2021-07-12 14:54:00 -04:00
elif [ -n " ${ EMPTY_JAIL } " ] ; then
2020-04-18 18:02:11 -04:00
## Generate minimal configuration for empty jail
generate_minimal_conf
fi
2020-07-24 15:37:50 -04:00
# Set strict permissions on the jail by default
chmod 0700 " ${ bastille_jailsdir } / ${ NAME } "
2020-11-26 12:44:40 -05:00
2025-05-02 08:37:51 -06:00
# Apply boot, depends and priority settings before starting jail
2025-05-02 10:27:00 -06:00
sysrc -f " ${ bastille_jailsdir } / ${ NAME } /settings.conf " boot = ${ BOOT } >/dev/null
2025-05-02 08:37:51 -06:00
sysrc -f " ${ bastille_jailsdir } / ${ NAME } /settings.conf " depend = "" >/dev/null
2025-05-02 10:27:00 -06:00
sysrc -f " ${ bastille_jailsdir } / ${ NAME } /settings.conf " priority = " ${ PRIORITY } " >/dev/null
2025-03-19 10:48:26 -06:00
2020-11-26 12:44:40 -05:00
# Jail must be started before applying the default template. -- cwells
2021-01-08 02:05:30 -04:00
if [ -z " ${ EMPTY_JAIL } " ] ; then
bastille start " ${ NAME } "
2021-01-08 20:26:31 -04:00
elif [ -n " ${ EMPTY_JAIL } " ] ; then
# Don't start empty jails unless a template defined.
if [ -n " ${ bastille_template_empty } " ] ; then
bastille start " ${ NAME } "
fi
2021-01-08 02:05:30 -04:00
fi
2021-07-12 14:54:00 -04:00
2025-02-28 11:49:29 -07:00
# Exit if jail was not started, except for empty jails
if [ -z " ${ EMPTY_JAIL } " ] ; then
if ! check_target_is_running " ${ NAME } " ; then
2025-05-17 10:18:52 -06:00
bastille destroy -afy " ${ NAME } "
2025-05-01 17:39:50 -06:00
error_exit " [ERROR]: Failed to create jail: ${ NAME } "
2025-02-28 11:49:29 -07:00
fi
2025-01-28 17:31:51 -07:00
fi
2020-11-26 12:44:40 -05:00
if [ -n " ${ VNET_JAIL } " ] ; then
2021-01-08 22:37:18 -04:00
if [ -n " ${ bastille_template_vnet } " ] ; then
2025-06-02 18:08:21 -06:00
2020-11-26 12:44:40 -05:00
## rename interface to generic vnet0
2023-10-30 20:39:58 +01:00
uniq_epair = $( grep vnet.interface " ${ bastille_jailsdir } / ${ NAME } /jail.conf " | awk '{print $3}' | sed 's/;//; s/-/_/g' )
2020-11-26 12:44:40 -05:00
_gateway = ''
2021-07-26 11:13:04 +02:00
_gateway6 = ''
2021-08-07 19:57:53 +02:00
_ifconfig_inet = ''
_ifconfig_inet6 = ''
2025-05-01 17:39:50 -06:00
2025-06-02 18:08:21 -06:00
# Determine default gateway option
if echo " ${ IP } " | grep -qE '(0[.]0[.]0[.]0|DHCP|SYNCDHCP)' ; then
2021-08-07 19:57:53 +02:00
# Enable DHCP if requested
_ifconfig_inet = SYNCDHCP
else
# Else apply the default gateway
2025-05-20 09:00:48 -06:00
if [ -n " ${ OPT_GATEWAY } " ] ; then
_gateway = " ${ OPT_GATEWAY } "
elif [ -n " ${ bastille_network_gateway } " ] ; then
2020-11-26 12:44:40 -05:00
_gateway = " ${ bastille_network_gateway } "
else
2025-04-24 10:12:56 -06:00
_gateway = " $( netstat -4rn | awk '/default/ {print $2}' ) "
2021-08-07 19:57:53 +02:00
fi
fi
2025-06-02 18:08:21 -06:00
2021-08-07 19:57:53 +02:00
# Add IPv4 address (this is empty if DHCP is used)
if [ -n " ${ IP4_ADDR } " ] ; then
2025-06-02 18:08:21 -06:00
_ifconfig_inet = " ${ _ifconfig_inet } inet ${ IP4_ADDR } "
2021-08-07 19:57:53 +02:00
fi
2025-06-02 18:08:21 -06:00
2021-08-07 19:57:53 +02:00
# Enable IPv6 if used
2025-06-02 18:08:21 -06:00
if [ -n " ${ IP6_ADDR } " ] ; then
2021-08-07 19:57:53 +02:00
_ifconfig_inet6 = 'inet6 -ifdisabled'
if echo " ${ IP } " | grep -qE 'SLAAC' ; then
# Enable SLAAC if requested
_ifconfig_inet6 = " ${ _ifconfig_inet6 } accept_rtadv "
else
# Else apply the default gateway
if [ -n " ${ bastille_network_gateway6 } " ] ; then
_gateway6 = " ${ bastille_network_gateway6 } "
2021-07-12 14:54:00 -04:00
else
2021-08-07 19:57:53 +02:00
_gateway6 = " $( netstat -6rn | awk '/default/ {print $2}' ) "
2021-07-12 14:54:00 -04:00
fi
2020-11-26 12:44:40 -05:00
fi
fi
2025-06-02 18:08:21 -06:00
2021-08-07 19:57:53 +02:00
# Add IPv6 address (this is empty if SLAAC is used)
if [ -n " ${ IP6_ADDR } " ] ; then
2025-06-02 18:08:21 -06:00
_ifconfig_inet6 = " ${ _ifconfig_inet6 } ${ IP6_ADDR } "
2021-08-07 19:57:53 +02:00
fi
2025-06-02 18:08:21 -06:00
# We need to pass IP4 and IP6 separately
_ifconfig = " ${ _ifconfig_inet } "
_ifconfig6 = " ${ _ifconfig_inet6 } "
bastille template " ${ NAME } " ${ bastille_template_vnet } --arg EPAIR = " ${ uniq_epair } " --arg GATEWAY = " ${ _gateway } " --arg GATEWAY6 = " ${ _gateway6 } " --arg IFCONFIG = " ${ _ifconfig } " --arg IFCONFIG6 = " ${ _ifconfig6 } "
2025-03-03 12:28:23 -07:00
# Add VLAN ID if it was given
if [ -n " ${ VLAN_ID } " ] ; then
2025-03-03 12:33:57 -07:00
bastille template " ${ NAME } " ${ bastille_template_vlan } --arg VLANID = " ${ VLAN_ID } " --arg IFCONFIG = " ${ _ifconfig } "
2025-03-03 12:28:23 -07:00
fi
2020-11-26 12:44:40 -05:00
fi
2025-02-13 11:59:32 -07:00
fi
if [ -n " ${ THICK_JAIL } " ] ; then
2021-01-08 20:26:31 -04:00
if [ -n " ${ bastille_template_thick } " ] ; then
2020-11-26 12:44:40 -05:00
bastille template " ${ NAME } " ${ bastille_template_thick } --arg BASE_TEMPLATE = " ${ bastille_template_base } " --arg HOST_RESOLV_CONF = " ${ bastille_resolv_conf } "
fi
2022-01-15 11:32:28 -04:00
elif [ -n " ${ CLONE_JAIL } " ] ; then
if [ -n " ${ bastille_template_clone } " ] ; then
bastille template " ${ NAME } " ${ bastille_template_clone } --arg BASE_TEMPLATE = " ${ bastille_template_base } " --arg HOST_RESOLV_CONF = " ${ bastille_resolv_conf } "
fi
2020-11-26 12:44:40 -05:00
elif [ -n " ${ EMPTY_JAIL } " ] ; then
2021-01-08 20:26:31 -04:00
if [ -n " ${ bastille_template_empty } " ] ; then
bastille template " ${ NAME } " ${ bastille_template_empty } --arg BASE_TEMPLATE = " ${ bastille_template_base } " --arg HOST_RESOLV_CONF = " ${ bastille_resolv_conf } "
2020-11-26 12:44:40 -05:00
fi
2021-07-12 14:45:37 -04:00
## Using templating function to fetch necessary packges @hackacad
elif [ -n " ${ LINUX_JAIL } " ] ; then
2025-05-01 17:39:50 -06:00
info "\nFetching packages..."
2021-07-12 14:45:37 -04:00
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"
2025-01-28 17:38:52 -07:00
jexec -l " ${ NAME } " /bin/bash -c "chmod 777 /tmp"
2021-07-12 14:45:37 -04:00
jexec -l " ${ NAME } " /bin/bash -c "apt update"
2021-07-12 14:54:00 -04:00
else
# Thin jail.
2021-01-08 20:26:31 -04:00
if [ -n " ${ bastille_template_thin } " ] ; then
2020-11-26 12:44:40 -05:00
bastille template " ${ NAME } " ${ bastille_template_thin } --arg BASE_TEMPLATE = " ${ bastille_template_base } " --arg HOST_RESOLV_CONF = " ${ bastille_resolv_conf } "
fi
fi
2025-05-20 11:38:57 -06:00
# Apply nameserver (if set)
if [ -n " ${ OPT_NAMESERVER } " ] ; then
2025-05-21 12:13:11 -06:00
sed -i '' "/^nameserver.*/d" " ${ bastille_jail_resolv_conf } "
2025-05-21 18:00:44 -06:00
for _ns in $( echo ${ OPT_NAMESERVER } | sed 's/,/ /g' ) ; do
echo " nameserver ${ _ns } " >> " ${ bastille_jail_resolv_conf } "
done
2025-05-20 11:38:57 -06:00
fi
2020-11-26 12:44:40 -05:00
# Apply values changed by the template. -- cwells
2021-07-12 14:45:37 -04:00
if [ -z " ${ EMPTY_JAIL } " ] && [ -z " ${ LINUX_JAIL } " ] ; then
2021-01-08 02:05:30 -04:00
bastille restart " ${ NAME } "
2021-01-08 20:26:31 -04:00
elif [ -n " ${ EMPTY_JAIL } " ] ; then
# Don't restart empty jails unless a template defined.
if [ -n " ${ bastille_template_empty } " ] ; then
bastille restart " ${ NAME } "
fi
2021-01-08 02:05:30 -04:00
fi
2018-11-07 10:36:54 -07:00
}
2023-03-16 20:58:11 +01:00
bastille_root_check
2025-01-28 17:31:51 -07:00
if echo " ${ 3 } " | grep '@' ; then
2024-12-08 21:05:45 -05:00
# shellcheck disable=SC2034
2020-02-20 18:06:31 -04:00
BASTILLE_JAIL_IP = $( echo " $3 " | awk -F@ '{print $2}' )
2024-12-08 21:05:45 -05:00
# shellcheck disable=SC2034
2020-02-20 18:06:31 -04:00
BASTILLE_JAIL_INTERFACES = $( echo " $3 " | awk -F@ '{print $1}' )
2019-07-15 07:44:45 -06:00
fi
2025-01-28 17:31:51 -07:00
# Handle options.
2025-03-15 21:35:03 -06:00
BOOT = "on"
2020-04-18 18:02:11 -04:00
EMPTY_JAIL = ""
2020-02-18 17:04:06 -04:00
THICK_JAIL = ""
2022-01-15 11:32:28 -04:00
CLONE_JAIL = ""
2020-02-18 17:04:06 -04:00
VNET_JAIL = ""
2025-03-03 12:13:48 -07:00
VLAN_ID = ""
2021-07-12 14:45:37 -04:00
LINUX_JAIL = ""
2025-01-13 13:19:26 -07:00
STATIC_MAC = ""
2025-01-28 17:31:51 -07:00
DUAL_STACK = ""
2023-12-08 11:21:31 +01:00
VALIDATE_RELEASE = "1"
2025-03-12 16:00:56 -06:00
PRIORITY = "99"
2025-05-20 09:00:48 -06:00
OPT_GATEWAY = ""
2025-05-20 11:38:57 -06:00
OPT_NAMESERVER = ""
2021-07-07 05:22:35 -04:00
while [ $# -gt 0 ] ; do
2020-02-18 17:04:06 -04:00
case " ${ 1 } " in
2025-01-28 17:31:51 -07:00
-h| --help| help )
usage
; ;
2025-02-28 12:59:48 -07:00
-B| --bridge)
VNET_JAIL = "1"
VNET_JAIL_BRIDGE = "1"
2025-01-28 17:31:51 -07:00
shift
; ;
2025-02-28 12:59:48 -07:00
-C| --clone)
CLONE_JAIL = "1"
shift
; ;
-D| --dual)
DUAL_STACK = "1"
2025-01-13 13:19:26 -07:00
shift
; ;
2023-11-24 16:28:31 -07:00
-E| --empty)
2021-07-07 05:21:28 -04:00
EMPTY_JAIL = "1"
2021-07-07 05:22:35 -04:00
shift
2020-04-18 18:02:11 -04:00
; ;
2025-05-20 11:38:57 -06:00
-g| --gateway| --defaultrouter)
2025-05-20 09:00:48 -06:00
OPT_GATEWAY = " ${ 2 } "
# Validate gateway
if [ -n " ${ OPT_GATEWAY } " ] ; then
if ! validate_ip " ${ OPT_GATEWAY } " >/dev/null 2>/dev/null; then
error_exit " [ERROR]: Not a valid gateway: ${ OPT_GATEWAY } "
fi
fi
shift 2
; ;
2023-11-24 16:28:31 -07:00
-L| --linux)
2021-07-12 14:52:25 -04:00
LINUX_JAIL = "1"
2021-07-12 14:54:00 -04:00
shift
2021-07-12 14:45:37 -04:00
; ;
2025-02-28 12:59:48 -07:00
-M| --static-mac)
STATIC_MAC = "1"
shift
; ;
2025-05-20 11:38:57 -06:00
-n| --nameserver)
OPT_NAMESERVER = " ${ 2 } "
# Validate nameserver
if [ -n " ${ OPT_NAMESERVER } " ] ; then
2025-05-21 09:07:25 -06:00
for _nameserver in $( echo ${ OPT_NAMESERVER } | sed 's/,/ /g' ) ; do
if ! validate_ip " ${ _nameserver } " >/dev/null 2>/dev/null; then
error_exit " [ERROR]: Invalid nameserver(s): ${ OPT_NAMESERVER } "
fi
done
2025-05-20 11:38:57 -06:00
fi
shift 2
; ;
2025-03-12 16:00:56 -06:00
-p| --priority)
if echo " ${ 2 } " | grep -Eoq " ^[0-9]+ $" ; then
PRIORITY = " ${ 2 } "
shift 2
else
error_exit " Not a valid priority value: \" ${ 2 } \" "
fi
; ;
2025-03-15 21:35:03 -06:00
--no-boot)
BOOT = "off"
shift
; ;
2025-02-28 12:59:48 -07:00
--no-validate| no-validate)
VALIDATE_RELEASE = ""
shift
; ;
2023-11-24 16:28:31 -07:00
-T| --thick)
2021-07-07 05:21:28 -04:00
THICK_JAIL = "1"
2021-07-07 05:22:35 -04:00
shift
2020-02-19 19:53:25 -04:00
; ;
2023-11-24 16:28:31 -07:00
-V| --vnet)
2021-07-07 05:21:28 -04:00
VNET_JAIL = "1"
2021-07-07 05:22:35 -04:00
shift
2020-02-19 19:53:25 -04:00
; ;
2025-03-03 12:13:48 -07:00
-v| --vlan)
2025-05-20 11:38:57 -06:00
if echo " ${ 2 } " | grep -Eq '^[0-9]+$' ; then
2025-03-03 12:38:13 -07:00
VLAN_ID = " ${ 2 } "
2025-05-20 11:38:57 -06:00
else
2025-03-03 12:28:23 -07:00
error_exit " Not a valid VLAN ID: ${ 2 } "
2025-05-20 11:38:57 -06:00
fi
2025-03-03 12:13:48 -07:00
shift 2
; ;
2025-02-28 12:59:48 -07:00
-x| --debug)
enable_debug
2021-12-02 15:06:47 +01:00
shift
; ;
2025-02-28 12:59:48 -07:00
-Z| --zfs-opts)
bastille_zfs_options = " ${ 2 } "
shift 2
2023-12-08 11:21:31 +01:00
; ;
2025-01-28 17:31:51 -07:00
-*)
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 ; ;
2025-05-01 17:39:50 -06:00
*) error_exit " [ERROR]: Unknown Option: \" ${ 1 } \" " ; ;
2025-01-28 17:31:51 -07:00
esac
done
2023-11-24 16:28:31 -07:00
shift
; ;
*)
2021-07-07 05:22:35 -04:00
break
; ;
2020-02-18 17:04:06 -04:00
esac
2021-07-07 05:22:35 -04:00
done
2025-01-28 17:31:51 -07:00
# Validate options
2021-07-12 14:54:00 -04:00
if [ -n " ${ EMPTY_JAIL } " ] ; then
2022-01-15 11:32:28 -04:00
if [ -n " ${ CLONE_JAIL } " ] || [ -n " ${ THICK_JAIL } " ] || [ -n " ${ VNET_JAIL } " ] || [ -n " ${ LINUX_JAIL } " ] ; then
2025-05-01 12:38:14 -06:00
error_exit "[ERROR]: Empty jail option can't be used with other options."
2021-07-07 05:22:35 -04:00
fi
2021-07-12 14:54:00 -04:00
elif [ -n " ${ LINUX_JAIL } " ] ; then
2022-01-15 11:32:28 -04:00
if [ -n " ${ EMPTY_JAIL } " ] || [ -n " ${ VNET_JAIL } " ] || [ -n " ${ THICK_JAIL } " ] || [ -n " ${ CLONE_JAIL } " ] ; then
2025-05-01 17:39:50 -06:00
error_exit "[ERROR]: Linux jail option can't be used with other options."
2021-07-12 14:54:00 -04:00
fi
2022-01-15 11:32:28 -04:00
elif [ -n " ${ CLONE_JAIL } " ] && [ -n " ${ THICK_JAIL } " ] ; then
2025-05-01 12:38:14 -06:00
error_exit "[ERROR]: Clonejail and Thickjail can't be used together."
2025-03-03 12:13:48 -07:00
elif [ -z " ${ VNET_JAIL } " ] && [ -z " ${ VNET_JAIL_BRIDGE } " ] && [ -n " ${ VLAN_ID } " ] ; then
2025-05-01 12:38:14 -06:00
error_exit "[ERROR]: VLANs can only be used with VNET and bridged VNET jails."
2020-02-18 17:04:06 -04:00
fi
2018-11-07 10:36:54 -07:00
2020-02-19 19:53:25 -04:00
NAME = " $1 "
RELEASE = " $2 "
IP = " $3 "
INTERFACE = " $4 "
2025-05-01 12:38:14 -06:00
info " \nAttempting to create jail: ${ NAME } "
2020-04-18 18:02:11 -04:00
if [ -n " ${ EMPTY_JAIL } " ] ; then
if [ $# -ne 1 ] ; then
usage
fi
else
if [ $# -gt 4 ] || [ $# -lt 3 ] ; then
usage
fi
2020-02-19 19:53:25 -04:00
fi
2025-05-01 12:38:14 -06:00
# Validate jail name
2020-05-09 15:31:15 -04:00
if [ -n " ${ NAME } " ] ; then
validate_name
2019-11-19 13:10:24 -04:00
fi
2025-04-14 15:38:06 -06:00
# Validate interface type
if [ -n " ${ VNET_JAIL } " ] && [ -n " ${ VNET_JAIL_BRIDGE } " ] ; then
if ! ifconfig -g bridge | grep -owq " ${ INTERFACE } " ; then
2025-05-01 12:38:14 -06:00
error_exit " [ERROR]: Interface is not a bridge: ${ INTERFACE } "
2025-04-14 15:38:06 -06:00
fi
elif [ -n " ${ VNET_JAIL } " ] && [ -z " ${ VNET_JAIL_BRIDGE } " ] ; then
if ifconfig -g bridge | grep -owq " ${ INTERFACE } " ; then
2025-05-01 12:38:14 -06:00
error_exit " [ERROR]: Interface is a bridge: ${ INTERFACE } "
2025-04-14 15:38:06 -06:00
fi
fi
2025-04-25 14:33:38 -06:00
# Do not allow netgraph with -B|--bridge yet...
2025-04-25 20:33:09 -06:00
if [ " ${ bastille_network_vnet_type } " = "netgraph" ] && [ -n " ${ VNET_JAIL_BRIDGE } " ] ; then
2025-04-25 14:33:38 -06:00
error_exit "[ERROR]: Netgraph does not support the [-B|--bridge] option."
fi
2023-12-08 11:21:31 +01:00
if [ -n " ${ LINUX_JAIL } " ] && [ -n " ${ VALIDATE_RELEASE } " ] ; then
2021-07-12 14:45:37 -04:00
case " ${ RELEASE } " in
bionic| ubuntu_bionic| ubuntu| ubuntu-bionic)
## check for FreeBSD releases name
NAME_VERIFY = ubuntu_bionic
; ;
focal| ubuntu_focal| ubuntu-focal)
## check for FreeBSD releases name
NAME_VERIFY = ubuntu_focal
; ;
2023-07-10 12:04:40 +02:00
jammy| ubuntu_jammy| ubuntu-jammy)
2021-07-23 12:07:21 -05:00
## check for FreeBSD releases name
2023-07-10 12:04:40 +02:00
NAME_VERIFY = ubuntu_jammy
2021-07-23 12:07:21 -05:00
; ;
2021-07-30 07:40:01 -05:00
debian_buster| buster| debian-buster)
## check for FreeBSD releases name
NAME_VERIFY = buster
; ;
2021-12-22 18:35:49 -07:00
debian_bullseye| bullseye| debian-bullseye)
## check for FreeBSD releases name
NAME_VERIFY = bullseye
; ;
2023-07-10 12:04:40 +02:00
debian_bookworm| bookworm| debian-bookworm)
## check for FreeBSD releases name
NAME_VERIFY = bookworm
; ;
2021-07-12 14:45:37 -04:00
*)
2025-05-01 12:38:14 -06:00
error_notify "[ERROR]: Unknown linux release."
2021-07-12 14:45:37 -04:00
usage
; ;
esac
fi
2020-04-18 18:02:11 -04:00
if [ -z " ${ EMPTY_JAIL } " ] ; then
2023-12-08 11:21:31 +01:00
if [ -n " ${ VALIDATE_RELEASE } " ] ; then
## verify release
case " ${ RELEASE } " in
2025-05-31 12:23:36 -04:00
[ 2-4] .[ 0-9] *)
2023-12-08 11:21:31 +01:00
## check for MidnightBSD releases name
NAME_VERIFY = $( echo " ${ RELEASE } " )
validate_release
; ;
*-CURRENT| *-CURRENT-I386| *-CURRENT-i386| *-current)
## check for FreeBSD releases name
NAME_VERIFY = $( echo " ${ RELEASE } " | grep -iwE '^([1-9]{2,2})\.[0-9](-CURRENT|-CURRENT-i386)$' | tr '[:lower:]' '[:upper:]' | sed 's/I/i/g' )
validate_release
; ;
*-RELEASE| *-RELEASE-I386| *-RELEASE-i386| *-release| *-RC[ 1-9] | *-rc[ 1-9] | *-BETA[ 1-9] )
## check for FreeBSD releases name
NAME_VERIFY = $( echo " ${ RELEASE } " | grep -iwE '^([1-9]{2,2})\.[0-9](-RELEASE|-RELEASE-i386|-RC[1-9]|-BETA[1-9])$' | tr '[:lower:]' '[:upper:]' | sed 's/I/i/g' )
validate_release
; ;
*-stable-LAST| *-STABLE-last| *-stable-last| *-STABLE-LAST)
## check for HardenedBSD releases name(previous infrastructure)
NAME_VERIFY = $( echo " ${ RELEASE } " | grep -iwE '^([1-9]{2,2})(-stable-last)$' | sed 's/STABLE/stable/g' | sed 's/last/LAST/g' )
validate_release
; ;
*-stable-build-[ 0-9] *| *-STABLE-BUILD-[ 0-9] *)
## check for HardenedBSD(specific stable build releases)
NAME_VERIFY = $( echo " ${ RELEASE } " | grep -iwE '([0-9]{1,2})(-stable-build)-([0-9]{1,3})$' | sed 's/BUILD/build/g' | sed 's/STABLE/stable/g' )
validate_release
; ;
*-stable-build-latest| *-stable-BUILD-LATEST| *-STABLE-BUILD-LATEST)
## check for HardenedBSD(latest stable build release)
NAME_VERIFY = $( echo " ${ RELEASE } " | grep -iwE '([0-9]{1,2})(-stable-build-latest)$' | sed 's/STABLE/stable/g' | sed 's/build/BUILD/g' | sed 's/latest/LATEST/g' )
validate_release
; ;
current-build-[ 0-9] *| CURRENT-BUILD-[ 0-9] *)
## check for HardenedBSD(specific current build releases)
NAME_VERIFY = $( echo " ${ RELEASE } " | grep -iwE '(current-build)-([0-9]{1,3})' | sed 's/BUILD/build/g' | sed 's/CURRENT/current/g' )
validate_release
; ;
current-build-latest| current-BUILD-LATEST| CURRENT-BUILD-LATEST)
## check for HardenedBSD(latest current build release)
NAME_VERIFY = $( echo " ${ RELEASE } " | grep -iwE '(current-build-latest)' | sed 's/CURRENT/current/g' | sed 's/build/BUILD/g' | sed 's/latest/LATEST/g' )
validate_release
; ;
ubuntu_bionic| bionic| ubuntu-bionic)
UBUNTU = "1"
NAME_VERIFY = Ubuntu_1804
validate_release
; ;
ubuntu_focal| focal| ubuntu-focal)
UBUNTU = "1"
NAME_VERIFY = Ubuntu_2004
validate_release
; ;
ubuntu_jammy| jammy| ubuntu-jammy)
UBUNTU = "1"
NAME_VERIFY = Ubuntu_2204
validate_release
; ;
debian_buster| buster| debian-buster)
NAME_VERIFY = Debian10
validate_release
; ;
debian_bullseye| bullseye| debian-bullseye)
NAME_VERIFY = Debian11
validate_release
; ;
debian_bookworm| bookworm| debian-bookworm)
NAME_VERIFY = Debian12
validate_release
; ;
*)
error_notify "Unknown Release."
usage
; ;
esac
fi
2018-11-07 10:36:54 -07:00
2025-05-01 12:38:14 -06:00
# Check for name/root/.bastille
2020-04-18 18:02:11 -04:00
if [ -d " ${ bastille_jailsdir } / ${ NAME } /root/.bastille " ] ; then
2025-05-01 12:38:14 -06:00
error_exit " [ERROR]: ${ NAME } already exists. ${ NAME } /root/.bastille exists. "
2020-04-18 18:02:11 -04:00
fi
2018-11-07 10:36:54 -07:00
2025-05-01 12:38:14 -06:00
# Check for required release
2020-04-18 18:02:11 -04:00
if [ ! -d " ${ bastille_releasesdir } / ${ RELEASE } " ] ; then
2025-05-01 12:38:14 -06:00
error_notify "[ERROR]: Release must be bootstrapped first."
error_exit "See 'bastille bootstrap'."
2020-04-18 18:02:11 -04:00
fi
2019-06-22 09:28:42 -06:00
2025-05-01 12:38:14 -06:00
# Validate IP address
2020-04-18 18:02:11 -04:00
if [ -n " ${ IP } " ] ; then
2021-08-07 19:57:53 +02:00
validate_ips
2020-04-18 18:02:11 -04:00
else
usage
fi
2018-11-07 10:36:54 -07:00
2025-05-01 12:38:14 -06:00
# Validate interface
2020-11-26 12:44:40 -05:00
if [ -n " ${ INTERFACE } " ] ; then
2020-04-18 18:02:11 -04:00
validate_netif
2025-04-26 15:01:56 -06:00
validate_netconf
2021-01-12 23:15:39 -04:00
elif [ -n " ${ VNET_JAIL } " ] ; then
if [ -z " ${ INTERFACE } " ] ; then
if [ -z " ${ bastille_network_shared } " ] ; then
# User must specify interface on vnet jails.
2025-05-01 12:38:14 -06:00
error_exit "[ERROR]: Network interface not defined."
2021-01-12 23:15:39 -04:00
else
2025-04-26 15:01:56 -06:00
validate_netconf
2021-01-12 23:15:39 -04:00
fi
2021-01-08 20:26:31 -04:00
fi
2020-04-18 18:02:11 -04:00
else
2025-04-26 15:01:56 -06:00
validate_netconf
2020-04-18 18:02:11 -04:00
fi
2019-10-24 17:02:50 -04:00
else
2025-04-30 11:21:41 -06:00
info " \nCreating empty jail: ${ NAME } . "
2019-10-24 17:02:50 -04:00
fi
2020-11-26 12:44:40 -05:00
# 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 "
fi
# These variables were added after Bastille 0.7.20200714, so they may not exist in the user's config.
# We're checking for existence of the variables rather than empty since empty is a valid value. -- cwells
if [ -z ${ bastille_template_base +x } ] ; then
bastille_template_base = 'default/base'
fi
if [ -z ${ bastille_template_empty +x } ] ; then
bastille_template_empty = 'default/empty'
fi
2021-07-12 14:45:37 -04:00
if [ -z ${ bastille_template_linux +x } ] ; then
2021-07-12 14:54:00 -04:00
bastille_template_linux = 'default/linux'
2021-07-12 14:45:37 -04:00
fi
2020-11-26 12:44:40 -05:00
if [ -z ${ bastille_template_thick +x } ] ; then
bastille_template_thick = 'default/thick'
fi
2022-01-15 11:32:28 -04:00
if [ -z ${ bastille_template_clone +x } ] ; then
bastille_template_clone = 'default/clone'
fi
2020-11-26 12:44:40 -05:00
if [ -z ${ bastille_template_thin +x } ] ; then
bastille_template_thin = 'default/thin'
fi
if [ -z ${ bastille_template_vnet +x } ] ; then
bastille_template_vnet = 'default/vnet'
fi
2025-01-28 17:31:51 -07:00
if check_target_exists " ${ NAME } " ; then
2025-05-01 12:38:14 -06:00
error_exit " [ERROR]: Jail already exists: ${ NAME } "
2025-01-28 17:31:51 -07:00
fi
2025-04-25 20:33:09 -06:00
2025-04-26 11:32:59 -06:00
create_jail " ${ NAME } " " ${ RELEASE } " " ${ IP } " " ${ INTERFACE } "
2025-04-30 11:21:41 -06:00
2025-05-02 08:37:51 -06:00
echo