> For the complete documentation index, see [llms.txt](https://handbook.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://handbook.bsdcn.org/di-17-zhang-jail-yu-rong-qi/17.14.-geng-duo-jail-xuan-xiang.md).

# 17.14.更多 jail 选项

[jail(8)](https://man.freebsd.org/cgi/man.cgi?query=jail\&sektion=8\&format=html) 暴露的参数远比本章示例使用的要多。jail 是强大的隔离边界，但并非绝对的。每个 `allow.*` 放松都以能力换取隔离性，使 jail 的特权用户向宿主 `root` 的特权靠近一步。仅授予 jail 中工作负载真正需要的权限，其余保留在其更严格的默认值。完整列表见 [jail(8)](https://man.freebsd.org/cgi/man.cgi?query=jail\&sektion=8\&format=html) 和 [jail.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=jail.conf\&sektion=5\&format=html)；下面是管理员最常使用的参数。

## 17.14.1. allow.\* 权限

`allow.*` 参数是布尔值，可向 jail 授予个别特权。根据 [jail(8)](https://man.freebsd.org/cgi/man.cgi?query=jail\&sektion=8\&format=html)，“除了 allow\.set\_hostname 和 allow\.reserved\_ports 外，这些布尔参数默认关闭”，因此 jail 默认是锁定的，每项能力都必须显式授予。

| 参数                              | 默认值 | 效果                                                                                                                                                                                                       |
| ------------------------------- | --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `allow.set_hostname`            | 开启  | jail 可更改自己的主机名。                                                                                                                                                                                          |
| `allow.reserved_ports`          | 开启  | jail 中的 `root` 可绑定 1024 以下的保留端口。                                                                                                                                                                         |
| `allow.raw_sockets`             | 关闭  | 启用原始套接字，使 [ping(8)](https://man.freebsd.org/cgi/man.cgi?query=ping\&sektion=8\&format=html) 和 [traceroute(8)](https://man.freebsd.org/cgi/man.cgi?query=traceroute\&sektion=8\&format=html) 可在 jail 中工作。 |
| `allow.chflags`                 | 关闭  | jail 中的 `root` 可像在宿主上一样操作系统文件标志。                                                                                                                                                                         |
| `allow.mount`                   | 关闭  | jail 可挂载和卸载文件系统，配合 `allow.mount.*` 子参数。                                                                                                                                                                  |
| `allow.quotas`                  | 关闭  | jail 可管理文件系统配额。                                                                                                                                                                                          |
| `allow.read_msgbuf`             | 关闭  | jail 中的进程可通过 [dmesg(8)](https://man.freebsd.org/cgi/man.cgi?query=dmesg\&sektion=8\&format=html) 读取内核消息缓冲区。                                                                                              |
| `allow.socket_af`               | 关闭  | 允许 IPv4、IPv6、local 和 route 之外的套接字地址族。                                                                                                                                                                    |
| `allow.mlock`                   | 关闭  | jail 中的进程可通过 [mlock(2)](https://man.freebsd.org/cgi/man.cgi?query=mlock\&sektion=2\&format=html) 锁定物理内存。                                                                                                 |
| `allow.unprivileged_proc_debug` | 关闭  | 非特权用户可对自己的进程使用调试设施。                                                                                                                                                                                      |
| `allow.vmm`                     | 关闭  | jail 可使用 [vmm(4)](https://man.freebsd.org/cgi/man.cgi?query=vmm\&sektion=4\&format=html) 管理程序运行 [bhyve(8)](https://man.freebsd.org/cgi/man.cgi?query=bhyve\&sektion=8\&format=html) 客户机。                 |
| `allow.nfsd`                    | 关闭  | jail 可运行 NFS 服务器。                                                                                                                                                                                        |

权衡每项放松所暴露的内容：`allow.raw_sockets` 让 jail 中的进程可伪造数据包，`allow.chflags` 让 jail 中的 `root` 可清除宿主依赖的不可变和仅追加标志，而 `allow.mount` 开放了文件系统命名空间。

在 jail 内运行 NFS 服务器（FreeBSD 14.0 发行说明中提及）需要设置 `allow.nfsd`，需要一个根目录本身是文件系统挂载点的 VNET jail，且 `enforce_statfs` 不得设置为 `0`。

## 17.14.2. System V IPC

依赖 System V 共享内存、信号量和消息队列的数据库及其他软件，可通过 `sysvmsg`、`sysvsem` 和 `sysvshm` 参数按模块控制。每个参数接受三个值之一：`inherit` 使宿主的所有 IPC 对象对 jail 可见，`new` 给 jail 自己私有的键命名空间，`disable` 使相关系统调用失败。

对于在 jail 中运行 PostgreSQL 的经典案例，`new` 是正确的选择，可为数据库提供自己的共享内存命名空间而不暴露宿主的：

```sh
sysvmsg = new;
sysvsem = new;
sysvshm = new;
```

较早的 `allow.sysvipc` 参数已被弃用。它等价于将三个模块参数都设置为 `inherit`，即将宿主范围的 IPC 命名空间与 jail 共享，因此推荐使用上面的按模块参数。

## 17.14.3. 挂载文件系统

`allow.mount` 让 jail 可挂载文件系统，一族子参数选择哪些类型：`allow.mount.devfs`、`allow.mount.fdescfs`、`allow.mount.fusefs`、`allow.mount.nullfs`、`allow.mount.procfs`、`allow.mount.linprocfs`、`allow.mount.linsysfs`、`allow.mount.tmpfs` 和 `allow.mount.zfs`。根据 [jail(8)](https://man.freebsd.org/cgi/man.cgi?query=jail\&sektion=8\&format=html)，每个子参数“仅在配合 allow\.mount 且 enforce\_statfs 设置为低于 2 的值时才有效”。便利参数 `mount.devfs`、`mount.fdescfs` 和 `mount.procfs` 会为 jail 自动挂载这些文件系统，`mount.fstab` 指向包含额外挂载的 fstab 文件。

`enforce_statfs` 参数既控制 jail 能看到的挂载点，又通过上面的规则控制 `allow.mount.*` 权限是否生效。它接受三个值：

| 值       | jail 可见的挂载点         |
| ------- | ------------------- |
| `0`     | 宿主上的所有挂载点，无限制。      |
| `1`     | 仅 jail 根目录之下的挂载点。   |
| `2`（默认） | 仅 jail 根目录所在的单一挂载点。 |

由于 `allow.mount.*` 权限要求值低于 `2`，因此必须挂载自己文件系统的 jail 通常配置为 `enforce_statfs = 1`。

## 17.14.4. 按 jail 设置的 securelevel

`securelevel` 参数设置 jail 的 `kern.securelevel`，并在 jail 内部提高内核的不可变标志和设备保护。根据 [jail(8)](https://man.freebsd.org/cgi/man.cgi?query=jail\&sektion=8\&format=html)，“jail 的 securelevel 不会低于其父系统，但通过设置此参数，可有更高的值”。因此，面向网络的 jail 可在加固的 `securelevel = 3` 下运行，而宿主保持默认值。

## 17.14.5. 分层 jail

jail 本身可创建子 jail，这是构建嵌套或分层 jail 层次结构的方式。`children.max` 参数设置一个 jail 可创建的子 jail 数量；默认为 `0`，表示不允许子 jail，只读的 `children.cur` 报告当前存在的数量。子 jail 永远不能超过其父 jail 的权限：根据 [jail(8)](https://man.freebsd.org/cgi/man.cgi?query=jail\&sektion=8\&format=html)，“jail 中的进程不允许授予比自己拥有的更大的权限”。这使得在 jail 内运行 jail 管理器成为可能。

## 17.14.6. 空和持久 jail

默认情况下，jail 仅在有运行进程时存在；当其最后一个进程退出时，jail 消失。根据 [jail(8)](https://man.freebsd.org/cgi/man.cgi?query=jail\&sektion=8\&format=html) 的话，设置 `persist` 参数“允许 jail 在没有任何进程的情况下存在”。这正是使 jail 在创建为空后、填充内容之前保持活动的原因，也是锚定仅持有网络状态的 VNET jail 的依据。可创建一个空 jail 并保持其活动以便实验：

```sh
# jail -c name=test path=/rescue persist
```

使用 `nopersist` 清除该标志，让 jail 在再次空闲时被移除。

## 17.14.7. 呈现不同的 OS 发行版本

jail 的用户空间可能比宿主内核旧，但其中的工具仍会通过 [uname(1)](https://man.freebsd.org/cgi/man.cgi?query=uname\&sektion=1\&format=html) 读取宿主的版本，除非另有指示。`osrelease` 参数设置 jail 的 `kern.osrelease` 和 `uname -r` 报告的字符串，`osreldate` 设置 `kern.osreldate` 和 `uname -K` 报告的数字。将它们设置成让较旧的用户空间报告自己的发行版本，可使 [uname(1)](https://man.freebsd.org/cgi/man.cgi?query=uname\&sektion=1\&format=html)、[sysctl(8)](https://man.freebsd.org/cgi/man.cgi?query=sysctl\&sektion=8\&format=html) 消费者和版本探测构建工具行为正确，包括在 jail 内运行的 [freebsd-update(8)](https://man.freebsd.org/cgi/man.cgi?query=freebsd-update\&sektion=8\&format=html)。软件包管理不受影响，因为 [pkg(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=8\&format=html) 从 jail 自己二进制文件的 ELF 注释派生其 ABI，而非从 [uname(1)](https://man.freebsd.org/cgi/man.cgi?query=uname\&sektion=1\&format=html)。这补充了 jail 用户空间不能比宿主内核更新的规则；参见 [升级 jail](/di-17-zhang-jail-yu-rong-qi/17.12.-geng-xin-jail.md)。
