# 17.3.主机配置

在宿主系统上创建任何 jail 之前，必须进行一些配置，并获取宿主系统的一些信息。

这包括配置 [jail(8)](https://man.freebsd.org/cgi/man.cgi?query=jail\&sektion=8\&format=html) 工具、创建用于配置和安装 jail 的必要目录、获取宿主系统的网络信息，以及检查宿主是否使用 OpenZFS 或 UFS 作为文件系统。

> **技巧**
>
> jail 中运行的 FreeBSD 版本不得高于宿主系统运行的版本。

## 17.3.1. jail 工具

[jail(8)](https://man.freebsd.org/cgi/man.cgi?query=jail\&sektion=8\&format=html) 工具用于管理 jail。

若要在系统启动时自动启动 jail，执行以下命令：

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

> **技巧**
>
> 启用 `jail_parallel_start` 后，所有已配置的 jail 将在后台同时启动。

## 17.3.2. 网络配置

FreeBSD jail 的网络可以通过几种不同的方式进行配置：

**宿主网络模式（IP 共享）**\
在宿主网络模式中，jail 与宿主系统共享同一个网络协议栈。当以此模式创建 jail 时，它使用相同的网络接口和 IP 地址。这意味着 jail 没有独立的 IP 地址，其网络流量将与宿主的 IP 绑定。

**虚拟网络（VNET）**\
虚拟网络是 FreeBSD jail 提供的一项高级网络功能，比基础的宿主网络模式更灵活。VNET 允许为每个 jail 创建独立的网络协议栈，为其分配独立的 IP 地址、路由表和网络接口。这提供了更高程度的网络隔离，使 jail 的运行行为更像是独立的虚拟机。

**netgraph 系统**\
[netgraph(4)](https://man.freebsd.org/cgi/man.cgi?query=netgraph\&sektion=4\&format=html) 是一个通用的内核框架，用于创建自定义网络配置。它可用于定义 jail 与宿主之间、以及多个 jail 之间网络流量的流向方式。

## 17.3.3. 设置 jail 目录结构

jail 的文件不需要放在特定路径。

有些管理员使用 **/jail**，有些使用 **/usr/jail**，也有些使用 **/usr/local/jails**。本章将使用 **/usr/local/jails**。

除了 **/usr/local/jails**，还将创建以下目录：

* **media**：用于存放下载的用户环境压缩包。
* **templates**：使用薄 jail 时用于存放模板。
* **containers**：用于存放各个 jail。

如果使用 OpenZFS，执行以下命令以为这些目录创建数据集：

```sh
# zfs create -o mountpoint=/usr/local/jails zroot/jails
# zfs create zroot/jails/media
# zfs create zroot/jails/templates
# zfs create zroot/jails/containers
```

> **技巧**
>
> 此处使用 `zroot` 作为父数据集，也可以使用其他数据集。

如果使用 UFS，执行以下命令以创建这些目录：

```sh
# mkdir /usr/local/jails/
# mkdir /usr/local/jails/media
# mkdir /usr/local/jails/templates
# mkdir /usr/local/jails/containers
```

## 17.3.4. jail 配置文件

配置 jail 有两种方式。

第一种是在 **/etc/jail.conf** 文件中为每个 jail 添加一个条目。另一种方式是在 **/etc/jail.conf.d/** 目录中为每个 jail 创建一个独立的配置文件。

如果宿主系统上只运行少量 jail，可以直接将每个 jail 的配置写入 **/etc/jail.conf** 文件。若宿主系统上运行多个 jail，建议在 **/etc/jail.conf.d/** 目录下为每个 jail 分别创建一个配置文件。

**/etc/jail.conf.d/** 中的文件必须使用 `.conf` 作为扩展名，并且需要在 **/etc/jail.conf** 中通过以下语句引入：

```sh
.include "/etc/jail.conf.d/*.conf";
```

一个典型的 jail 配置条目如下：

```ini
jailname { ①
  # 启动与日志
  exec.start = "/bin/sh /etc/rc"; ②
  exec.stop = "/bin/sh /etc/rc.shutdown"; ③
  exec.consolelog = "/var/log/jail_console_${name}.log"; ④

  # 权限设置
  allow.raw_sockets; ⑤
  exec.clean; ⑥
  mount.devfs; ⑦

  # 主机名与路径
  host.hostname = "${name}"; ⑧
  path = "/usr/local/jails/containers/${name}"; ⑨

  # 网络配置
  ip4.addr = 192.168.1.151; ⑩
  ip6.addr = ::ffff:c0a8:197 ⑪
  interface = em0; ⑫
}
```

* ① `jailname` jail 的名称。
* ② `exec.start` 在 jail 创建时运行的命令。常见写法为 `/bin/sh /etc/rc`。
* ③ `exec.stop` 在 jail 被销毁前运行的命令。常见写法为 `/bin/sh /etc/rc.shutdown`。
* ④ `exec.consolelog` 用于记录命令输出（stdout 和 stderr）的日志文件路径。
* ⑤ `allow.raw_sockets` 允许在 jail 中创建原始套接字。启用后，可以在 jail 中使用如 [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) 等工具。
* ⑥ `exec.clean` 在干净的环境中运行命令。
* ⑦ `mount.devfs` 将 [devfs(5)](https://man.freebsd.org/cgi/man.cgi?query=devfs\&sektion=5\&format=html) 文件系统挂载到 jail 的 **/dev** 目录，并应用 `devfs_ruleset` 中定义的规则集来限制 jail 可见的设备。
* ⑧ `host.hostname` jail 的主机名。
* ⑨ `path` jail 的根目录路径。通过 jail 或 [jexec(8)](https://man.freebsd.org/cgi/man.cgi?query=jexec\&sektion=8\&format=html) 执行的命令均在该目录下运行。
* ⑩ `ip4.addr` IPv4 地址。可设置单个 IP 或多个 IP 地址。另一种方式是使用 `ip4 = inherit;` 来继承宿主的 IP。
* ⑪ `ip6.addr` IPv6 地址。可设置单个 IP 或多个 IP 地址。另一种方式是使用 `ip6 = inherit;` 来继承宿主的 IP。
* ⑫ `interface` 绑定 jail 的 IP 地址所使用的网络接口，通常为宿主系统的接口名。

关于配置变量的更多信息，可参考 [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)。
