# 11.1 Jail 基础配置

## FreeBSD Jail 概述

操作系统级虚拟化（Operating System-level virtualization）是一种在单一内核实例上运行多个隔离用户空间实例的技术范式。FreeBSD Jail 作为该领域的先驱技术，提供了轻量级、安全的资源隔离机制。

Jail 本意是“监狱、监禁”的意思，此处指一种基于 Chroot 改进的容器隔离技术。该技术于 1999 年在 FreeBSD 4.0 中首次引入，是首个商用化的操作系统级虚拟化解决方案，其设计目标是通过文件系统、进程空间和网络资源的三重隔离实现安全的多租户环境。

Jail 的发音为 \[dʒeɪl]（英/美），接近汉语文字“杰诶尔”的发音（或“宅奥”），“炸儿”不是正确发音。

## 创建 jail 目录

### 获得 FreeBSD 基本系统文件

#### 编译基本系统（可选）

```sh
# mkdir -p /usr/jail  # 创建 jail 路径
# cd /usr/src                          # 切换到 FreeBSD 源码路径，若没有可参照其他文章获得 
# make buildworld                      # 编译基本系统
# make installworld DESTDIR=/usr/jail # 安装到 jail
# make distribution DESTDIR=/usr/jail # 或者使用该命令
```

#### 解压分发文件集（可选）

也可通过下载或从 ISO 镜像中提取 `base.txz` 分发文件集，将其解压到 jail 目录。

```sh
# tar -xJf base.txz -C /usr/jail
```

devfs 文件系统提供了对系统设备节点的访问接口，使 Jail 内的应用程序能够与底层硬件设备进行受控交互。挂载 devfs 可让 Jail 访问必要的设备文件，推荐进行此项配置。

```sh
# mount -t devfs devfs /usr/jail/dev
```

相关文件结构：

```sh
/
├── usr
│   ├── jail
│   │   └── dev        # devfs 挂载点
│   └── src            # FreeBSD 源码路径
└── etc
    ├── rc.conf        # 系统启动配置
    ├── jail.conf      # Jail 配置文件
    └── resolv.conf    # DNS 配置
```

### 在 `/etc/rc.conf` 中启用 jail 服务

启用 jail 服务开机自启动：

```sh
# sysrc jail_enable="YES"
```

创建 `/etc/jail.conf` 配置文件（也可以写入 `/etc/rc.conf` 文件，但单独配置更便于管理，且符合现代系统管理的最佳实践，将服务配置与系统配置分离）。

```ini
www {                                   # Jail 名称为 www
host.hostname = www.example.org;         # 主机名
ip4.addr = 192.168.0.10;                # IP 地址
path = "/usr/jail";                      # jail 路径
devfs_ruleset = "www_ruleset";          # devfs ruleset
mount.devfs;                            # 挂载 devfs 文件系统到 jail
exec.start = "/bin/sh /etc/rc";         # 启动命令
exec.stop = "/bin/sh /etc/rc.shutdown"; # 关闭命令
}
```

## jail 实例状态管理

使用 `jls` 命令可查看当前运行中的 jail 信息列表。`jls` 是 FreeBSD 系统用于列出当前活动 jail 实例的标准工具，可显示 jail 的标识符、网络地址、主机名和根目录路径等关键信息。

以下为 `jls` 命令的示例输出：

```sh
JID IP Address    Hostname   Path
3   192.168.0.10  www       /usr/jail/www
```

字段说明（中英对照）：

| 英语         | 中文      |
| ---------- | ------- |
| JID        | jail ID |
| IP Address | IP 地址   |
| Hostname   | 主机名     |
| Path       | jail 路径 |

## Jail 服务的启动与停止

使用 service 命令管理 Jail 的启动与停止：

```sh
# service jail start www   # 启动名为 www 的 Jail
# service jail stop www    # 停止名为 www 的 Jail
```

也可以使用 jail 命令直接操作：

```sh
# jail -c www   # 启动名为 www 的 Jail
# jail -r www   # 停止名为 www 的 Jail
```

## 进入 jail

使用 `jexec` 命令可在指定 Jail 中执行命令。以下示例在 Jail ID 为 3 的环境中启动 shell：

```sh
# jexec 3 /bin/sh
```

## 正常关闭 jail

在 Jail 中执行关机脚本可实现正常关闭。以下示例在 Jail ID 为 3 的环境中执行 `/etc/rc.shutdown`：

```sh
# jexec 3 /etc/rc.shutdown
```

## 更新 jail 系统

使用 freebsd-update 可对指定 Jail 进行系统更新。需将 `/usr/jail/www` 替换为实际的 Jail 路径：

```sh
# freebsd-update -b /usr/jail/www fetch     # 获取指定 Jail 的系统更新
# freebsd-update -b /usr/jail/www install   # 安装指定 Jail 的系统更新
```

## 启用 ping 支持

如需在 Jail 中使用 ping 等需要原始套接字的工具，可在 `/etc/jail.conf` 中添加以下配置：

```ini
allow.raw_sockets=1;   # 允许 Jail 使用原始套接字
allow.sysvipc=1;       # 允许 Jail 使用 System V IPC
```

配置完成后请重启 Jail 以使配置生效。由于 Jail 配置在启动时加载，重启是使新配置参数生效的必要步骤。

示例：启动名为 test 的 Jail，并加载其配置文件

```sh
# jail -c test
```

## DNS 网络配置

在 jail 内创建并编辑 `/etc/resolv.conf` 文件，设置 DNS。该文件用于配置域名系统的参数，包括默认搜索域和 DNS 服务器地址，是实现网络名称解析的核心配置文件。

```sh
search lan  # 指定默认搜索域为 lan
nameserver 223.5.5.5 # 指定 DNS 服务器
nameserver 223.6.6.6 # 指定备用 DNS 服务器
```

配置完成后，可以在 Jail 内使用 `nslookup` 或 `ping` 测试 DNS 解析是否正常。注意，`ping` 需要启用原始套接字，如前文所述。

## 故障排除与未竟事宜

### 删除文件时提示没有权限

递归取消目录及其内容的系统不可修改（schg）标志：该标志是 FreeBSD 文件系统的安全特性，设置后可防止文件被意外或恶意修改、重命名或删除，即使是超级用户也无法直接操作，需先取消该标志。注意：在实际使用中，将“directory”替换为需要操作的目录路径。

```sh
# chflags -R noschg directory
```

### 证书验证失败

该问题表现为证书验证错误，报错信息包含 `STORE routines:ossl_store_get0_loader_int:unregistered`。在确认系统时间正常的情况下，此问题通常与 FreeBSD 14.1 RELEASE 和 14.2 RELEASE 中的证书数据库索引有关。

解决方法：更新证书数据库的哈希索引

```sh
# certctl rehash
```

重新执行 `pkg` 命令即可。如果问题持续，尝试清除 pkg 缓存：`# pkg clean -a`。

参考资源：

* FreeBSD Bugzilla. Bug 280031 - Cannot install `pkg` due to 404 on pkg.freebsd.org\[EB/OL]. FreeBSD Bugzilla, \[2026-03-25]. <https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=280031>. 该报告记录了 FreeBSD 14.x 证书验证问题及解决方案，为同类问题提供了权威参考。
* pkg-t. Cannot fetch (and install) `pkg`\[EB/OL]. The FreeBSD Forums, 2024-06-28. <https://forums.freebsd.org/threads/cannot-fetch-and-install-pkg.93976/>. 社区讨论提供了问题复现与 `certctl rehash` 命令的应用场景。

## 课后习题

1. 部署一个 FreeBSD Jail 并在其中安装 nginx 服务，配置端口转发使宿主机外可访问。
2. 修改 Jail 的 devfs\_ruleset，观察哪些设备在 Jail 中可见。
3. 对比使用原始套接字与不使用原始套接字时 Jail 的网络能力差异。
