本页目录
- 第 1 步 - 在 FreeBSD 上安装 Iocage
- 第 2 步 - 下载 FreeBSD 发行版
- 第 3 步 - 配置共享 IP 与 Pf 防火墙
- 第 4 步 - 使用 Iocage 创建新 Jail
- 第 5 步 - 测试
- 参考资料
Jail 是 FreeBSD 上操作系统级虚拟化的术语。它由 Poul-Henning Kamp 于 1999 年提出,并从 4.x 版本起被 FreeBSD 采用。
Jail 允许系统管理员在 FreeBSD 系统内创建一个隔离且独立的迷你系统或“jail”。该“jail”拥有自己的根系统与配置,当你希望在隔离环境中部署应用时非常有用。
Iocage 是一个用 Python 编写的 FreeBSD Jail 管理器。它简洁易用,并提供了简单易懂的命令语法。Iocage Jail 管理器专为 jail 内的 ZFS 数据集而设计,允许你基于“VNET”虚拟网络栈和/或“共享 IP”方式创建 jail。借助 Iocage,你可以创建 jail 模板、基础 jail 和普通 jail。
本教程将向你展示如何使用 Iocage Jail 管理器搭建并配置 FreeBSD jail。我们将在 FreeBSD 上安装 Iocage,使用共享 IP 创建新 jail,配置 pf 防火墙,然后在 jail 内安装 nginx 网页服务器用于测试。
前置条件
在本指南中,你需要在安装了 ZFS(Z File System)的 FreeBSD 系统上安装并配置 Iocage Jail 管理器。同时请确保在你的 FreeBSD 系统上已启用 pf 防火墙。
以下是关于在 ZFS 上安装 FreeBSD 以及配置 pf 防火墙的指南。
如何在 ZFS 上安装 FreeBSD 12.0 如何在 FreeBSD 上配置 pf 防火墙
我们将进行以下操作:
- 安装 Iocage Jail 管理器
- 下载 FreeBSD 发行版
- 配置共享 IP 与 Pf 防火墙
- 使用 Iocage 创建新 Jail
- 测试
第 1 步 - 在 FreeBSD 上安装 Iocage
首先,我们将在 FreeBSD 系统上安装并配置 Iocage Jail 管理器。Iocage 使用 Python 编写,可通过 FreeBSD 二进制包仓库获取。
使用以下 pkg 命令将 Iocage 安装到 FreeBSD 系统。
pkg install py36-iocage
输入 'y' 以接受 Iocage Python 包的安装,随后安装将开始。
安装完成后,使用以下 zpool 命令检查系统上可用的 ZFS 存储池。
zpool list
现在为 Iocage 安装选择 ZFS 存储池。在本指南中,我们将使用 FreeBSD 安装时默认的名为 'zroot' 的 ZFS 存储池。
使用以下命令激活 'zroot' 存储池以供 Iocage 使用。
iocage activate zroot
至此,FreeBSD 12.0 上的 Iocage 安装已完成,你可以使用 iocage 命令行来创建和管理 FreeBSD jail(监狱)。

此外,你可以通过使用以下 sysrc 命令将 iocage 服务添加到 '/etc/rc.conf' 文件,使 jail 在系统启动时自动启用。
sysrc iocage_enable=yes
要创建新的 jail,你需要下载 FreeBSD 发行版。你也可以创建一个与宿主机 FreeBSD 版本不同的 jail。
使用以下 iocage 命令查看可用的发行版版本。
使用以下 iocage 命令查看可用的 Release 版本。
iocage fetch
现在,你将看到不同版本的 Release。根据需要选择版本并输入对应数字。输入数字 '2' 可下载最新的 Release 版本。

如果你想下载其他镜像,可以使用以下命令。
如果你想下载其他镜像,可以使用以下命令。
iocage fetch 11.3-RELEASE
第 3 步 - 配置共享 IP 与 Pf 防火墙
下载完 jail 的基础镜像后,我们将配置系统的网络与 pf 防火墙。我们将创建一个名为 'bridge0' 的新网络接口,其网络 IP 地址为 '10.8.8.1/24',该接口将由 jail 使用。
通过运行以下命令,向 '/etc/rc.conf' 文件添加新配置。
运行以下命令,向 '/etc/rc.conf' 文件添加新的配置。
sysrc cloned_interfaces+="bridge0"
sysrc ifconfig_bridge0="10.8.8.1/24"
创建一个新的 'bridge0' 网络接口,并配置网络 IP 地址 '10.8.8.1/24'。
ifconfig bridge0 create
ifconfig bridge0 10.8.8.1/24 up

既然已创建 'bridge0' 接口,使用以下命令检查它。
ifconfig bridge0
你将得到如下所示的结果。

如何在 FreeBSD 12.0 上配置 Pf 防火墙
进入 '/usr/local/etc' 目录并编辑配置文件 'pf.conf'。
进入 '/usr/local/etc' 目录并编辑配置文件 'pf.conf'。
cd /usr/local/etc/
vim pf.conf
将内部网络接口 'bridge0' 及其 IP 地址作为 'int_if' 和 'localnet' 变量添加进去。
# Internal interface int_if = "bridge0" localnet = $int_if:network
现在定义主机 jail 的 IP 地址以及需要转发到 jail 的端口。我们将把系统外部接口上的 HTTP 和 HTTPS 连接转发到 jail 主机 IP 地址 '10.8.8.5'。
# Port-Forward http and https to Jail '10.8.8.5'
ports_to_forward="{ 80, 443 }"
forward_host="10.8.8.5"
为 jail 的 'localnet' 变量在 'ext_if' 外部接口上启用 nat(网络地址转换),然后启用从 'ports_to_forward' 变量到主机 'forward_host' 的端口重定向。
# nat jail to internet and internet to jail (http and https only) nat on $ext_if inet from $localnet to any -> ($ext_if) rdr on $ext_if proto tcp from any to any port $ports_to_forward -> $forward_host
现在放行来自 'bridge0' 接口的所有连接,并放行外部接口上发往 HTTP 和 HTTPS 'ports_to_forward' 的入站连接。
pass from { self, $localnet } to any keep state
pass in on $ext_if proto {udp, tcp} from any to any port $ports_to_forward keep state
现在测试 pf 防火墙配置,确保没有错误,然后重新加载 pf 服务。
现在测试 pf 防火墙配置,确保没有错误,然后重新加载 pf 服务。
service pf check
service pf reload
之后,使用以下命令检查 pf 防火墙上的所有规则。
pfctl -s rules
你将得到如下所示的结果。

此外,你可以检查 pf 防火墙上的 nat 状态。
pfctl -v -s nat

以下是完整的 pf 防火墙配置。
以下是完整的 pf 防火墙配置。
cat /usr/local/etc/pf.conf
# Define External Interface and IP Address
ext_if="vtnet0"
ext_ip="198.13.39.207"
# Define TCP and UDP Services
ext_tcp_ports="{ ssh, smtp, smtps, imaps, http, https, domain }"
ext_udp_ports="{ domain, ntp }"
# Internal interface
int_if = "bridge0"
localnet = $int_if:network
# Port-Forward http and https to Jail '10.8.8.5'
ports_to_forward="{ 80, 443 }"
forward_host="10.8.8.5"
# Skip the localhost
set skip on lo0
# Log interface
set loginterface $ext_if
# nat jail to internet and internet to jail (http and https only)
nat on $ext_if inet from $localnet to any -> ($ext_if)
rdr on $ext_if proto tcp from any to any port $ports_to_forward -> $forward_host
# Default Policy
block in all
pass out all keep state
# Allow Ping
pass inet proto icmp icmp-type echoreq
pass from { self, $localnet } to any keep state
pass in on $ext_if proto {udp, tcp} from any to any port $ports_to_forward keep state
# Allow Services
pass in proto tcp from any to any port $ext_tcp_ports
pass in proto tcp from any to any port $ext_udp_ports
# Log access for ssh and http
pass log quick proto tcp from any to any port { ssh,http }
在 FreeBSD 系统上完成网络与 pf 防火墙的配置后,我们准备使用 iocage 创建新 jail。
使用以下 iocage 命令创建一个名为 'jail01'、基于 FreeBSD 发行版 '12.0-RELEASE' 的新 jail。
使用以下 iocage 命令创建一个名为 'jail01'、基于 FreeBSD '12.0-RELEASE' 的新 jail。
iocage create -n jail01 -r 12.0-RELEASE
现在添加 jail 的 IP 地址和默认路由网关。我们将为 'jail01' 分配 IP 地址 10.8.8.5,默认路由网关为 'bridge0' 主机 IP 地址 '10.8.8.1'。
iocage set ip4_addr="bridge0|10.8.8.5" jail01
iocage set defaultrouter="10.8.8.1" jail01
启用 jail 在系统启动时自动启动。
iocage set boot=on jail01
现在检查 jail 列表。
iocage list
你将看到 'jail01',其 IP 地址为 '10.8.8.5',基于 FreeBSD '12.0' release。

接下来,使用以下命令启动 'jail01'。
iocage start jail01
一旦 jail 启动,使用以下命令进入 jail。
iocage console jail01
你将获得 jail01 内部的一个新 shell,如下所示。

在 jail 内部,检查 'jail01' 上 'bridge0' 接口的 IP 地址。
ifconfig bridge0
你将看到 'bridge0' 接口的 IP 地址为配置好的 '10.8.8.5'。

第 5 步 - 测试
在这一步,我们将通过在 'jail01' 上安装 Nginx 网页服务器来进行测试,然后尝试从网络外部访问该 Nginx,连接将被重定向到 'jail01'。
首先,使用以下 pkg 命令更新 jail 上的二进制包。
首先,使用以下 pkg 命令更新 jail 上的二进制软件包。
pkg update

之后,使用以下 pkg 命令在 jail 内部安装 nginx Web 服务器。
pkg install nginx
安装完成后,将 nginx 服务加入系统启动项并启动 nginx 服务。
sysrc nginx_enable=yes
service nginx start
现在检查 'jail01' 上开放的端口列表。
sockstat -l4
你将看到 Nginx 服务已在 HTTP '80' 端口上启动并运行。

进入 '/usr/local/www/' 目录并编辑 'index.html' 文件。
进入 '/usr/local/www/' 目录并编辑 'index.html' 文件。
cd /usr/local/www/
edit nginx-dist/index.html
做相应修改后退出。
cat nginx-dist/index.html

http://198.xx.xx.207/
你将看到 'jail01' 内部的 nginx index.html 页面。
你将看到 'jail01' 内部的 nginx index.html 页面。

参考资料
['https://www.freebsd.org/doc/handbook/jails.html', 'https://iocage.readthedocs.io/en/latest/']
- https://www.freebsd.org/doc/handbook/jails.html
- https://iocage.readthedocs.io/en/latest/