虽然jail可以有复杂或高度专业化的配置,但在专用IP地址上建立一个简单的jail非常简单。jail本身需要一个专用的根目录、一个IP地址和一个主机名。你需要一个用户区的安装源。我们将从使用FreeBSD原生工具开始,然后继续使用iocage。
jail有“thin”和“thick”两种。thin jail是ZFS对另一个jail的克隆。thick jail是FreeBSD系统的完整、独立的副本。我们的标准jail是thick jail,而iocage默认为thin jail。
首先,我们将建造两个标准jail。一个是 loghost
,它运行 rsyslogd
来收集网络中的所有内容,而第二个是 logdb
,它运行 PostgreSQL
并聚合这些日志消息。然后我们将建造两个iocage jail,www1
和 www2
。我们将使用这些来测试应用程序,以轻松查看日志数据。
每个jail都需要一个根目录。那个目录下的所有东西都属于jail。我以标准jail主机名命名我的根目录。在本章中,我将使用 /jail/loghost 和 /jail/logdb 。
让我们从讨论核心配置和网络开始。
第二章:Jail要点Jail 网络Jail Sysctls参数和属性/etc/jail.conf定义标准 Jails默认设置覆盖默认值变量Iocage 配置更改参数Iocage布尔值Iocage默认值标准 Jail 用户空间Iocage 用户空间你的第一个 Jail使用 jail(8)
创建和销毁 Jails创建、查看、重命名和销毁Iocage jailsJail 目录测试最终 Jail 配置DNS时区/etc/fstab/etc/rc.confRoot密码和帐户其他设置
jail的网络连接与主机和其他jail隔离。每个jail都有一个IP专用。这听起来不错,直到您点击localhost和环回接口。
理论上,每台使用TCP/IP的计算机都可以访问环回接口以及环回地址 127.0.0.1(IPv4)和 ::1(IPv6)。这些是人工构造,意思是“这台机器就在这里”。主机只能连接一个环回地址,不能将其委托给jail。那么jail是如何获得环回地址的呢?
内核欺骗他们。
jail用jail的主IP地址代替环回地址。当你在jail中使用 127.0.0.1 地址时,你实际上是在使用jail的公共地址。对于许多应用程序来说,这根本不重要……除非它重要。如果你在 127.0.0.1 地址上运行一个jailed的守护进程,期望它与公共网络隔离,你会失望的。守护进程正在监听jail的外部地址。
虽然环回地址不再像以前那么重要,但许多软件包仍然需要它,许多系统管理员希望它可用。没有环回地址,你就不能运行一个DNS解析器供本地使用,另一个供公众使用。您网站的数据库需要配置为使用本地套接字而不是TCP/IP端口。只要您意识到这些问题,它们都不是不可克服的。
第9章讨论了通过vnet为jail提供自己的专用网络堆栈和合法的环回接口。
FreeBSD在sysctl树中有一整段专门用于jail的 security.jail
。所有jail系统都是运行时可调的;您不必重新启动来调整它们。但是,您可能需要重新启动jail,以便新设置对其产生影响。这些系统中的许多只是默认值,可以被jail参数覆盖,如下一节所述。
程序和用户可以检查 security.jail.jailed sysctl
,看看他们是否在监狱里。sysctl在主机上为0,但在jail内为1。
parameters —— 参数 properties —— 属性
用参数(也称为属性)配置jail,这些参数决定了jail应该如何运行。jail的根文件系统?这是一个参数。分配给jail的IP地址?也是一个参数。jail可以挂载文件系统吗?如果可以,可以挂载哪些类型的文件系统?是的,一个参数。一些参数管理 jail(8)
,而另一些则传递给主机的内核。
与内核相关的参数控制与内核交互的函数。jail如何呈现挂载点和文件系统?jail可以看到哪些设备?这个jail能建造更多的jail吗?如果可以,有多少个?我们应该为System V IPC分配一块内存吗?所有这些都需要摆弄内核。其中一些参数,如jail的安全级别,可以在jail运行时更改。一些参数,例如那些不太知名的文件系统的参数,与特定的内核模块相关联。
非内核(non-kernel)参数仅用于初始配置jail。这些命令包括“在某个阶段运行此命令”、“将控制台记录到此文件”、“使用此虚拟网络堆栈”和“设置此主机名”。它们确实涉及内核,但仅以其他程序所做的方式。
Jail参数是故意按照sysctls建模的,由句点分隔的项组成,如 ip4.addr
、 allow.mount.devfs
和 allow.socket_af
。在Jail配置文件 /etc/jail.conf 中设置Jail的参数。
iocage有一组类似的参数。Jail和iocage参数通常共享名称,但它们是独立的实体。iocage使用其参数为 jail(8)
命令设置相应的标志、参数和选项。iocage参数使用下划线,而jail参数使用句点。我在上一段中给出的示例jail参数映射到iocage参数 ip4_addr
、 allow_mount_devfs
和 allow_socket_af
。一般来说,适用于标准jail参数的任何内容也适用于iocage参数。
我们通过为参数赋值来配置jail。对于这些示例,我们将使用 jail(8)
格式,但即使配置方法不同,这些值在iocage中的工作方式也完全相同。参数值可以包含任何非空格字符。如果一个值包含字母、数字、点、破折号和下划线以外的任何内容,请在该值周围加上单引号或双引号。(从技术上讲,你可以用反斜杠来避开其他角色,但很快就会变得难看。)
某些参数的值被赋予等号。您将使用这样一个参数,通过path参数告诉jail它的根目录:
xxxxxxxxxx
Path="/jail/mariadb";
这个jail的根目录是 /jail/mariadb 。
一些参数有默认值,如 jail(8)
所示。参数的存在意味着默认设置,但您可以更改该默认设置。在这里,我设置了参数ip4,以默认值启用该功能:
xxxxxxxxxx
ip4;
使用等号将ip4等参数设置为非默认值。您可以在 jail.conf 和iopage中通过将其设置为“false”或“no”来禁用此功能:
xxxxxxxxxx
ip4=false;
一些参数可以有多个值。用逗号分隔这些值:
xxxxxxxxxx
ip4.addr="203.0.113.231,203.0.113.232";
复杂的参数值可能不允许用逗号分隔值。在这种情况下,使用 +=
语法重复参数赋值以添加值。在这里,我为ip4.addr分配了两个复数值:
xxxxxxxxxx
ip4.addr="jpublic|203.0.113.225";
ip4.addr+="jprivate|198.51.100.225";
您可以安全地使用 +=
来初始化变量。
其他参数仅通过它们的存在就改变了环境,就像达斯·维德走进房间时整个房间的气氛都会发生变化一样。在这里,我设置了 allow.mount
参数,允许jail的系统管理员挂载额外的jail安全文件系统:
xxxxxxxxxx
allow.mount;
许多 jail.conf 参数都有一个“no”版本,可以关闭函数。它通常用于关闭默认设置,相当于将该参数设置为“否”或零。在这里,我不允许挂载其他文件系统:
xxxxxxxxxx
allow.nomount;
iocage没有无版本的参数。您不能在iocage中设置 allow_noset_hostname
;您必须将 allow_set_hostname
设置为0。
现在让我们看看如何使用 jail.conf 。
任何系统管理员都应该熟悉 /etc/jail.conf 的格式。每个jail都需要一个配置块,用花括号隔开。每个参数声明都以分号结尾。与几乎所有其他Unix配置文件一样,/etc/jail.conf 中的哈希标记表示注释。
以下是 jail.conf 中的loghost条目:
xxxxxxxxxx
loghost {
host.hostname="loghost.mwl.io";
ip4.addr="203.0.113.231";
path="/jail/loghost";
mount.devfs;
exec.clean;
exec.start="sh /etc/rc";
exec.stop="sh /etc/rc.shutdown";
}
每个jail都有一个名字。name
参数没有明确标记,但始终出现在开始大括号的前面。jail(8)
命令将创建一个名为“loghost”的jail。
大括号内的第一个参数 host.hostname
给出了jail的主机名。我称之为jail loghost,但虚拟机通过互联网主机名loghost.mwl.io来标识自己。
使用 ip4.addr
,我为jail分配了一个IP地址 203.0.113.231
。对于我们的初始测试,请使用已连接到主机的IP地址。第9章讨论了让 jail(8)
自动添加和删除主机中的IP地址。
path
参数给出了jail的根目录。
mount.devfs
的存在告诉 jail(8)
将设备文件系统附加到jail的 /dev 目录。分配给jail的默认设备文件系统仅包括基本jail操作所需的设备节点。它不会为硬件、内核转储、声卡等获取设备节点。jail不需要任何这些设备节点,访问这些节点可能会让聪明的囚犯逃离监狱。
jailed的进程可以从其父进程继承环境变量。这几乎总是不好的。在这里,我明确定义了 exec.clean
参数,以便在启动jail时剥离 jail(8)
命令环境。
最后,jail必须知道在启动和关闭时运行什么程序。一个小jail可能只运行一个命令。一个功能齐全的jail需要 exec.start
和 exec.stop
中定义的完整FreeBSD启动和关闭过程。我在第三章讨论了jail的启动和关闭。
许多jail共享共同的环境。我所有的jail都是从通过 exec.clean
剥离shell环境开始的。我几乎所有的jail都运行完整的FreeBSD安装,从 /etc/rc 开始,用 /etc/rc.shutdown 关闭。每个jail都需要一个设备文件系统。为每个jail定义这些将是乏味和重复的。
幸运的是, jail.conf 允许您为jail设置系统范围的默认值。在配置文件的开头指定默认值:
xxxxxxxxxx
mount.devfs;
exec.clean;
exec.start="sh /etc/rc";
exec.stop="sh /etc/rc.shutdown";
loghost {
host.hostname="loghost.mwl.io";
ip4.addr="203.0.113.221";
path="/jail/loghost";
}
此主机上的每个jail都会获得 mount.devfs
、exec.clean
、exec.start
和 exec.stop
设置。定义新jail变成了只定义独特环境的问题。
当jail需要默认值以外的参数设置时,请覆盖默认值。也许jail mariadb
有一个独特的启动命令:
xxxxxxxxxx
mariadb {
host.hostname="mariadb.mwl.io";
exec.start="sh /etc/rc.mariadb";
ip4.addr="203.0.113.232";
path="/jail/mariadb";
}
这个jail继承了所有默认值,但也运行自定义启动命令 /etc/rc.mariadb ,而不是完整的FreeBSD启动。
如果默认参数通过其存在激活了一个功能,但您必须为jail禁用该功能,请在jail中将该参数的值设置为 no
。
当您使用 +=
语法在默认值中链接多个语句时,覆盖默认值会变得有点棘手。您可以覆盖jail定义中的默认值,但必须在jail定义中给出所有所需的语句。考虑这个默认值:
xxxxxxxxxx
#default settings
exec.created="logger jail $name has started";
exec.created+="cpuset -c -j $name -l 2-5";
…
exec.created
参数在创建jail时运行一个命令,但在第一个jail进程启动之前。我们运行两个命令,logger
和 cpuset
。(第11章介绍了 cpuset
。)我需要为我的jail logdb运行一个稍微不同的 cpuset
命令。我不能使用普通的 +=
并在前两个命令之上堆叠第三个命令,因为这两个 cpuset
命令不兼容;运行默认值会排除运行特定于jail的命令。
xxxxxxxxxx
logdb {
exec.created="logger jail logdb has started";
exec.created+="cpuset -j logdb -cl 6-7";
…
我在第一个 exec.created
语句中使用了一个普通的等号,删除了之前的所有定义。由于+=
,第二条 exec.created
语句被添加到列表中。如果你不明白为什么jail工作不正常,请仔细检查你是否忘记了其中一个参数中的加号。
仔细阅读示例的人可能想知道默认设置中的 $name
。让我们来谈谈变量。
变量替换简化了jail管理。你可以定义自己的变量,或者从jail的设置中提取一些变量。双引号和无引号字符串中的变量会被展开,但单引号字符串中则不会。
用户定义变量的一个明显位置是jail文件系统的路径。如果我将数百个jail从 /jail 移动到另一个分区,我必须更新每个监狱的配置条目。这似乎很简单,但我了解我。我会搞砸的。相反,我为该文件系统定义了一个变量:
xxxxxxxxxx
$j="/jail";
…
loghost {
…
path="$j/loghost";
}
现在,将我的jail迁移到另一个分区只需要更新一个 jail.conf 条目。
然而,更有趣的是能够将jail参数用作变量。一旦定义了一个参数,你就可以在后续的配置语句中使用该参数的值。这对ip4来说并不是特别有用,但与name等参数配合使用时效果极佳。
xxxxxxxxxx
$j="/jail";
path="$j/$name";
host.hostname="$name.mwl.io"
loghost {
ip4.addr="203.0.113.231";
}
我们现在可以为jail的主机名和根目录定义全局默认值。每个jail唯一的信息是分配的IP地址。这还有一个额外的优点,即主机名与 jail(8)
使用的标签同步。
带句点的参数可以用作变量,但参数名称必须用大括号括起来。在jail中部署多个域名的人可能更喜欢使用完全限定的域名作为根目录路径的一部分。这是一个支持该功能的默认设置:
xxxxxxxxxx
path="/jail/${host.hostname}";
使用参数作为变量,结合连贯的目录布局,可以通过jail的唯一参数进行配置。
现在,您可以执行基本的标准监狱配置。让我们看看iocage。
使用 iocage(8)
命令执行所有jail配置,该命令与 zfs(8)
和 zpool(8)
非常相似。与标准jail一样,iocage为每个jail配置参数。与标准jail不同,iocage将所有jail配置与jail文件一起存储。
iocage为每个jail创建一个数据集,其中包含一个 fstab ,它包含要挂载到该jail中的特殊文件系统的详细信息;以及一个 config.json ,用于记录jail的参数。您还将看到jail实际文件系统所在的根数据集。
配置文件按字母顺序列出了jail的参数:
xxxxxxxxxx
{
"CONFIG_VERSION": "18",
"allow_chflags": "0",
"allow_mount": "0",
"allow_mount_devfs": "0",
"allow_mount_nullfs": "0",
…
它用肉眼看非常易读。可读性是JSON的设计目标。可写?嗯……是的,从技术上讲,你可以手动编辑JSON。不过,手工编辑是引入错误的好方法。iocage为您读写配置文件参数,并将结果验证为合法的JSON。
用 iocage get
读取jail的参数。您还需要两个参数,即感兴趣的参数和jail名称。在这里,我从jail www1中获取sysvshm参数的值:
xxxxxxxxxx
# iocage get sysvshm www1
new
要查看jail的所有参数,请使用 -a
参数和jail名称:
xxxxxxxxxx
# iocage get -a www1 | less
CONFIG_VERSION:11
allow_chflags:0
allow_mount:0
allow_mount_devfs:0
...
这看起来很像配置文件,不是吗?
要从每个iocage jail中检索参数,请添加 -r
标志。
xxxxxxxxxx
# iocage get -r sysvshm
+----------+----------------+
| NAME | PROP - sysvshm |
+==========+================+
| db5 | new |
+----------+----------------+
这默认打印一个具有ASCII边框的花哨表格,非常适合眼球,但我最常在脚本中使用,脚本不喜欢花哨的边框。添加 -h
标志以去除装饰并生成简单的制表符分隔的输出。在这里,我想检查我的所有主机,看看是否有人将特定参数调整为禁止的设置:
xxxxxxxxxx
# iocage get -rh sysvshm | grep inherit
db5 inherit
【此处疑为 iocage get -rh ip4 | grep inherit】
请参阅第8章,了解我为什么要对设立名为db5的jail的人大喊大叫。
使用 iopage set
更改参数:
xxxxxxxxxx
# iocage set sysvshm=new db5
Property: sysvshm has been updated to new
新的设置将在jail重新开放后生效。
iocage配置文件包含一些参数,这些参数不会出现在 jail(8)
中,也不会在 jail.conf 中工作。这些参数支持克隆和基本jail等功能。我们将在第6章讨论它们。
一大堆参数都是功能上的开关。该功能处于 on
或 off
、enabled
或 disabled
、 true
或 false
、0
或 1
状态。这些布尔参数都存储为 0
或 1
。
虽然iocage的默认值不错,但毫无疑问,你的组织在某个时候、某个地方需要一个不同的默认值。jail名称默认值保留用于iocage的默认设置。要查看每个可能的iocage参数及其初始设置,请查询此jail:
xxxxxxxxxx
# iocage get -a default
要更改所有jail的默认设置,请更改默认jail:
xxxxxxxxxx
# iocage set sysvshm=disable default
默认设置对所有未更改参数的jail生效。如果您手动调整了jail上的参数,然后手动将其设置回默认值,则更改该参数的默认设置不会影响jail。如果你在jail上更改了sysvshm,那么在默认情况下更改sysvshm并不会改变该jail的sysvshm。你碰过它,你拥有它。
当前的iocage默认值存储在 /iocage/defaults.json 中。要摆脱对iocage默认值的所有自定义设置,请删除该文件。下次运行iocage时,将出现一个新的默认文件。将单个参数更改回默认值意味着要弄清楚默认值是什么,并手动更改它。你确实有一个测试主机,对吧?
获取用户空间的最简单方法是从FreeBSD版本或构建中获取 base.txz 文件。将旧的用户区安装源代码保存在jail主机上的一个类似于 /jail/media 的位置,在以版本命名的子目录中。如果您重建、重新安装或复制监狱,您将需要安装介质。
您还可以使用 /usr/src 和 /usr/obj 中本地构建的用户区。不过,通过在临时目录中安装来制作自己的用户区tarball。不要直接安装在监狱里;你需要可复制的监狱。FreeBSD的构建过程包括在非标准目录中安装自定义世界的选项,这要归功于 DESTDIR
选项。
xxxxxxxxxx
# cd /usr/src
# make installworld DESTDIR=/tmp/jail
# make distribution DESTDIR=/tmp/jail
make installworld
命令将FreeBSD的程序文件复制到目标并设置相应的权限。 make distribution
命令创建支持目录和文件,例如来自 / 等的许多目录和文件。最终的结果是一个原始的用户空间。
将其打包以部署到您的jail。
xxxxxxxxxx
# tar -cf /jail/media/2019-05-25-current.txz --xz -C /tmp/jail/
用这个tarball安装你的实际jail。
请记住,jail中的用户区不能比主机的内核更新:2020年6月的用户区在2019年4月的内核上无法可靠工作。
iocage旨在用于基于FreeBSD官方版本的大规模部署。您不会从 /usr/src 安装和升级jail;相反,您将使用 release tarball
和 freebsd-update(8)
。iocage fetch
命令为您抓取发布:
xxxxxxxxxx
# iocage fetch
You’ll get a list of available releases.
[0] 9.3-RELEASE (EOL)
[1] 10.1-RELEASE (EOL)
[2] 10.2-RELEASE (EOL)
[3] 10.3-RELEASE (EOL)
[4] 10.4-RELEASE (EOL)
[5] 11.0-RELEASE (EOL)
[6] 11.1-RELEASE (EOL)
[7] 11.2-RELEASE
[8] 12.0-RELEASE
Releases marked with EOL are past their end of life. While FreeBSD continues to offer them for download, they do not receive security patches and you run them at your own risk.
Type the number of the desired RELEASE
Press [Enter] to fetch the default selection: (Not a RELEASE)
Type EXIT to quit: 7
我想要最新的FreeBSD 11版本,所以我打了7。根据我的连接速度,我可以从冰箱里拿午餐,也可以去La Snootiér吃12道菜的小吃。
xxxxxxxxxx
Fetching: 11.2-RELEASE
Downloading : MANIFEST [####################] 100% 0Mbit/s
Downloading : base.txz [######--------------] 29% 19.57Mbit/s
…
下载的文件将缓存在 /iocage/download 中。一旦iocage获取了某个版本的所有文件,它就会自动提取这些文件并应用最新的安全更新。我最终获得了11.2-RELEASE以及所有可用的补丁。
要禁用安全更新,可以在 iocage fetch
命令中添加 -NU
或 --noupdate
选项。那是个坏主意。不要这样做。
如果您的本地防火墙需要代理配置或身份验证,您可能需要手动下载发布分发文件,然后将其导入iocage。您还可以导入自己的自定义FreeBSD版本。在FreeBSD下载服务器上找到所需的版本https://download.FreeBSD.org并获取文件MANIFEST、base.txz、doc.txz,kernel.txz和src.txz。将它们全部放在以版本命名的目录中。-f
标志告诉iocage从本地文件而不是网络中提取版本。使用 -d
指定目录,使用 -r
为iocage提供此版本的名称。在这里,我将12.0的文件提取到 /home/mwl/releases/12.0 目录中:
xxxxxxxxxx
# iocage fetch -f -d /home/mwl/releases/ -r 12.0
您可能希望iocage在 /usr/src 中提供主机软件构建中的文件,而无需制作完整版本。这需要离开iocage,但这是可行的。首先,为该版本创建一个数据集,并在其下创建一个单独的根数据集。我的主机运行的是FreeBSD 13-current。如果你打算每隔一段时间从-current创建新的版本,你可能会发现以你正在构建的SVN版本命名iocage版本很有用。
xxxxxxxxxx
# zfs create -p iocage/iocage/releases/r343907/root
现在将jail用户区安装到该目录:
xxxxxxxxxx
# cd /usr/src
# make installworld DESTDIR=/iocage/releases/r343907/root
# make distribution DESTDIR=/iocage/releases/r343907/root
如果你计划定期更新你的jail到最新版本,我建议使用thick(厚)jail,甚至可能是一个有厚起源的base jail。ZFS克隆将迅速偏离其起源。如果jail存在的时间足够长,导致分歧成为问题,则按照第12章的讨论导出和导入jail。
iocage仅在 freebsd-update(8)
支持该版本的情况下应用安全更新。我必须亲手修补我现在的jail。我不会对标准的生产jail这样做,但我通过在我的环境中执行预发布测试为FreeBSD做出了贡献。
对于一个版本,您可以多次运行 iocage fetch
。它不会重新下载文件,但会重新提取以前下载的文件并应用所有当前的安全更新。如果你进入发布目录并弄乱了文件,这会清理你的烂摊子。
如果我知道我想获取什么版本,我可以在命令行上使用 -r
选项指定它。
要查看您已经下载了哪些版本,请运行 iocage list -r
。
xxxxxxxxxx
# iocage list -r
+---------------+
| Bases fetched |
+===============+
| 9.3-RELEASE |
+---------------+
| 11.2-RELEASE |
+---------------+
| 12.0-RELEASE |
+---------------+
我可以选择其中的任意一个来安装jail。
要删除已下载的版本,请使用 iocage destroy -d
命令。用 -r
指定发布版本。FreeBSD 9.3早就不存在了,我不想再用它安装任何jail:
xxxxxxxxxx
# iocage destroy -d -r 9.3-RELEASE
This will destroy RELEASE: 9.3-RELEASE
Are you sure? [y/N]: y
9.3-RELEASE has dependent jails (who may also have dependents), use --recursive to destroy:
www1
噢。我仍然有一个9.3-RELEASE的jail在运行。我必须在iocage允许我销毁下载的版本之前消除那个监狱。iocage安装是ZFS克隆,因此即使将jail升级到较新的版本,也无法消除底层版本。如果你需要独立,可以考虑thick jails 或 base jails(第6章)。
要更改克隆的或“thin”的jail,使其不再依赖于版本或模板,请导出并重新导入jail(第12章)。所有exported的jail都变成了thick jails。
现在你有了可以在jail里运行的软件,你可以建立第一个jail。您将对原始 jail(8)
和 iocage(8)
使用不同的方法。
jail(8)
创建和销毁 Jails用 jail(8)
构建一个jail意味着用FreeBSD用户区填充目录树,然后在 jail.conf
中配置它。在将用户区粘贴到目录中之前,请考虑如何排列jail文件。jail可能需要额外的支持文件,这些文件不会进入jail,但对于启动或配置jail是必要的。一个关键的例子是 fstab
文件(第8章)。你想把这些文件放在jail里,还是分开保存?
我将所有jail用户区放在 /jail 下的一个目录中,比如 /jail/loghost ,然后将附加文件放在主题特定的目录中,如 /jail/fstab 。其他人更喜欢将jail的用户放在更靠下的一个目录中,比如 /jail/loghost/root/ ,让他们将附加文件放在 /jail/loghost 下。做任何对你有意义的事。
在这里,我想建立一个名为 loghost 的jail,运行FreeBSD 11.2。原始分发文件位于 /jail/media/11.2/base.txz 中,我希望将jail放在 /jail/loghost 中。用 tar(1)
提取释放物。如果您手头有磁盘映像,请记住tar可以直接从未安装的ISO中提取文件。
xxxxxxxxxx
# tar -xpf /jail/media/11.2/base.txz -C /jail/loghost
如果需要其他分发集,如系统源代码或文档,也可以将它们提取到目录树中。
现在创建一个 jail.conf 条目。在讨论jail配置时,我们创建了一个非常合适的配置,包括其他jail的变量。
xxxxxxxxxx
$j="/jail";
path="$j/$name";
host.hostname="$name.mwl.io"
loghost {
ip4.addr="203.0.113.231";
}
jail已经准备好启动了。
要删除jail,请删除其目录、所有内容和 jail.conf 条目。
就像安装一个标准的jail一样,要创建一个iocage jail,你必须知道jail的IP地址、FreeBSD版本和jail的名称。
使用 -n
选项命名jail。如果你不指定名称,iocage会指定一个通用唯一标识符(UUID),一个32个字符的十六进制字符串。这对你的负载驱动部署系统来说很好,但对人类来说很糟糕。
-r
选项允许您指定版本。
您还可以在命令行上指定任何其他参数。在这里,我使用 ip4_addr
参数指定IP地址:
xxxxxxxxxx
# iocage create -n www1 ip4_addr="203.0.113.234" -r 11.2-RELEASE
www1 创建成功了。
jail创建过程非常快,因为它利用了ZFS克隆。不过,克隆会保留其父数据集的附件。不过,你可能会认为jail会很快偏离父数据集,并希望提前做好准备。thick jail使用数据集的副本而不是克隆作为基础。它的创建速度较慢,但从长远来看会为你避免痛苦——特别是如果你预计这个jail会持续很长时间。使用 -T
标志指定thick jail。
xxxxxxxxxx
# iocage create -T -n dns4 -r 11.2-RELEASE ip4_addr="203.0.113.243"
建造一个thick jail比克隆一个jail要慢得多,但这是一次性成本。
如果你想创建一个高度定制的jail——比如,如果你想从 /usr/src 和 /usr/obj 进行老派安装——用 -e
创建一个空jail。
使用 iocage list
命令查看现有iocage jail:
xxxxxxxxxx
# iocage list
+-----+------+-------+--------------+---------------+
| JID | NAME | STATE | RELEASE | IP4 |
+=====+======+=======+==============+===============+
| - | www1 | down | 11.2-RELEASE | 203.0.113.234 |
+-----+------+-------+--------------+---------------+
iocage将jail的文件存储在 /iocage/jailes/www1 中。您将找到iocage的jail配置文件 config.json ,以及iocage在启动jail之前用于挂载额外文件系统的fstab文件。 root 子目录是jail的实际根目录。
要查看每个iocage jail的更多详细信息,请在 iocage list
中添加 -l
标志以生成“长列表”。您需要一个宽终端来使用长列表。-q
标志将输出缩减为jail名称和IP地址。添加 -s
可以按任何标题排序。在这里,我列出了我所有的jail,按照它们安装的版本进行排序,并去掉了花哨的标题:
xxxxxxxxxx
# iocage list -s RELEASE -h
13 wdb1 up 11.2-RELEASE 203.0.113.236
12 www1 up 11.2-RELEASE 203.0.113.234
15 wdb2 up 12.0-ALPHA2 203.0.113.237
14 www2 up 12.0-ALPHA2 203.0.113.235
使用 iocage destroy
命令销毁一个jail和它的数据集:
xxxxxxxxxx
# iocage destroy www1
This will destroy jail www1
Are you sure? [y/N]: y
Stopping www1
Destroying www1
ioc-www1: removed
要告诉iocage跳过确认,请添加 -f
标志。不过要小心;在需要的东西上意外运行 iocage destroy -f
可能会导致损坏。
此命令可以同时销毁多个jails:
xxxxxxxxxx
# iocage destroy www3 www2 www1
如果你搞砸了,给jail起了个错误的名字,不要销毁并重新安装。使用 iocage rename
来更改jail的名称。在这里,我修复了一个最常见的拼写错误:
xxxxxxxxxx
# iocage rename wwww1 www1
Jail: wwww1 renamed to www1
现在,我们测试一下我们的jails。
通过在jail中运行单个命令来测试jail目录树。
对于标准jail,使用 jail(8)
在jail内运行命令。jail命令有四个参数:jail的路径、名称和主IP地址,以及在jail内运行的命令。这将启动监狱并运行命令。当你退出命令时,jail也会关闭。
xxxxxxxxxx
# jail path name address command
我想在我的jail loghost中运行一个shell。它位于目录 /jail/loghost 中,IP地址为203.0.113.231:
xxxxxxxxxx
# jail /jail/loghost/ loghost 203.0.113.231 /bin/sh
#
我收到了一个命令提示符……但它不是同一个命令提示。
xxxxxxxxxx
# uname -a
FreeBSD loghost 13.0-CURRENT FreeBSD 13.0-CURRENT #5 r336638: Mon Jul 22 13:32:15 EDT 2019
root@storm:/usr/obj/usr/src/amd64.amd64/sys/GENERIC amd64
我在jail里面了!具体来说,我被锁定在 /jail/loghost 中,现在将其视为我的根目录。这个jail的运行方式非常类似于单用户模式。看看这个jail里运行的程序:
xxxxxxxxxx
# ps -ax
ps: /dev/null: No such file or directory
没有 /dev ?我们还没有挂载一个,所以:没有。除了shell之外,没有其他进程正在运行,但你可以运行一些基本命令,如 ls(1)
和 mount(8)
。
要测试启动iocage监狱,请运行 iocage console
:
xxxxxxxxxx
# iocage console www1
jail www1现在正在运行。就像标准jail一样,主人被剥光了衣服。没有用户帐户或已安装的软件包。然而,退出控制台并不会关闭jail。
在真正开始之前配置每个jail。
无论你是使用原始的(raw)FreeBSD工具还是iocage进行安装,你的新jail都比FreeBSD安装程序创建的jail更为简陋。没有用户。没有root密码。网络有一个IP,但没有解析器(resolver)。“时区?你说的这个‘时区’是什么?”在把用户锁在jail里之前,花一分钟装饰一下jail。
您必须运行的许多设置命令都没有jail意识。passwd(1)
和 adduser(8)
程序对jail一无所知,只能影响 /etc 中的文件。不过,你不需要在 jail(8)
下启动它们来建立你的jail:一个简单的 chroot(8)
就足够了。
xxxxxxxxxx
# chroot /jail/loghost adduser
# chroot /jail/loghost passwd root
如果你使用的命令会影响进程,比如运行数据库客户端,你真的必须从jail的进程上下文中执行程序。开始整个jail。
每个jail都执行自己的DNS解析。您必须为标准jail提供解析器配置。在许多环境中,您可以直接从主机复制它。也许你有一个递归的名称服务器jail,你想让主机使用。在 /etc/rc.conf 中将 local_unbound
设置为YES得到的本地缓存服务器有问题,因为它无法真正连接到环回地址。要么为你的jail设置一个地方来回答他们的DNS查询,要么将所有jail都指向你的提供商。
如果你愿意,你可以在主机上使用 local_unbound
为监狱提供DNS;设置一个ACL,只允许从jail网络和localhost访问,并使用 interface automatic unbound
选项帮助服务器正确返回响应。
当jail启动时,iocage会自动将主机的 /etc/resolv.conf 复制到jail中。resolver
参数允许您在主机上指定一个不同的文件,以复制到jail的resolv.conf。
jail可能共享主机的时区。你可以将主机的 /etc/localtime 复制到jail中。不过,如果jail需要一个独特的时区设置,请运行 tzsetup(8)
。方便的是,tzsetup
知道jail。使用 -C
标志指定chroot目录。如果你知道你想要的时区,把它作为最后的论据:
xxxxxxxxxx
# tzsetup -sC /jail/loghost UTC
iopage程序会自动将主机的时区设置复制到监狱中。通过将 host_time
参数设置为 no
来禁用此功能。
我鼓励你在所有jail和host中使用相同的时区。其他人不同意。
所有核心文件系统的挂载都应该在主机中进行,这样jail就可以在没有文件系统表的情况下工作。然而,许多可以在jail中运行的程序都希望找到 /etc/fstab ,并假设如果文件不存在,一切都出了大问题。使用 touch(1)
创建一个空的文件系统表:
xxxxxxxxxx
# touch /jail/loghost/etc/fstab
jail的系统管理员可以将他们自己的自定义文件系统条目添加到此文件中。但是,只有您授予了这些挂载权限,它们才能工作。见第4章。
如果jail运行完整的FreeBSD安装,如本章所述,您可能会使用FreeBSD启动脚本 /etc/rc 。Jail创建不需要 /etc/rc.conf ,但您可能希望Jail在启动时启动其他程序。如果没有别的,用户将通过SSH管理大多数jail。值得庆幸的是,sysrc(8)
有一个 -j
标志,可以从主机修改jail的 rc.conf :
xxxxxxxxxx
# sysrc -j loghost sshd_enable="YES"
添加jail需要的任何其他 rc.conf
设置。
您必须在jail文件系统中才能添加用户帐户或更改密码。不过,用户管理命令不需要在jail的进程名称空间中运行;它们只需植根于jail的根文件系统。你可以使用 chroot(8)
。
您还可以运行本章前面的“jial测试”中讨论的shell,并使用 passwd(1)
设置根密码。
如果要使用SSH管理此jail,请运行 adduser(8)
以添加至少一个用户。
如果您的网络有其他要求,可以通过编辑配置文件来满足,那么现在是设置它们的时候了。您是否使用LDAP进行身份验证?立即将您的配置文件复制到jail中。在我们安装第5章中的软件包之前,您不想更改 nsswitch.conf ,但安装 ldap.conf 不会有什么坏处。
虽然iocage在下载FreeBSD版本时安装了所有可用的安全补丁,但它不会安装在您下载版本和安装jail之间发布的任何补丁。同样,对于标准jail,您必须运行 freebsd-update(8)
(第4章)来安装所有当前补丁。
你的jail现在可以使用了。