> 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.8.-nat-he-duan-kou-zhuan-fa.md).

# 17.8.NAT 和端口转发

被分配了私有地址的 jail——位于克隆的 [lo(4)](https://man.freebsd.org/cgi/man.cgi?query=lo\&sektion=4\&format=html) 接口（如 `lo1`）、私有网桥，或内部网络中 VNET epair 上的 jail——自身没有通往互联网的路由。宿主必须将 jail 的流量转换为可路由地址，并且要从外部访问此类 jail 中运行的服务，需将传入连接重定向到 jail。

首先，允许宿主在其接口之间转发数据包。在启动时启用并立即启用，执行以下命令：

```sh
# sysrc gateway_enable="YES"
# sysctl net.inet.ip.forwarding=1
```

对于 IPv6，使用 `ipv6_gateway_enable="YES"` 和 `net.inet6.ip6.forwarding=1`。

然后使用 [pf(4)](https://man.freebsd.org/cgi/man.cgi?query=pf\&sektion=4\&format=html) 在宿主上配置网络地址转换。以下 **/etc/pf.conf** 让私有 `192.168.0.0/24` 网络上的每个 jail 通过宿主的外部接口 `em0` 获得出站访问，并在宿主的 80 端口上发布一个 jail 中的 Web 服务器：

```sh
ext_if = "em0"

# 将 jail 出站流量转换为宿主地址
nat on $ext_if from 192.168.0.0/24 to any -> ($ext_if)

# 将入站 Web 流量转发到 jail 中的服务器
rdr on $ext_if proto tcp to port 80 -> 192.168.0.151
```

`rdr` 的目标必须是 jail 自己的地址。

使用以下命令启用并启动 [pf(4)](https://man.freebsd.org/cgi/man.cgi?query=pf\&sektion=4\&format=html)：

```sh
# sysrc pf_enable="YES"
# service pf start
```

> **注意**
>
> FreeBSD 15.0 新增了 OpenBSD 风格的内联 `nat-to` 和 `rdr-to` 语法，它将转换附加到 `pass` 或 `match` 规则上，例如 `match out on $ext_if from 192.168.0.0/24 to any nat-to ($ext_if)`。上面展示的经典 `nat on` 和 `rdr on` 规则在 FreeBSD 14.x 和 15.x 上均可工作。

关于 [pf(4)](https://man.freebsd.org/cgi/man.cgi?query=pf\&sektion=4\&format=html) 和 [ipfw(8)](https://man.freebsd.org/cgi/man.cgi?query=ipfw\&sektion=8\&format=html) 的完整论述，包括完整的规则集和基于 [ipfw(8)](https://man.freebsd.org/cgi/man.cgi?query=ipfw\&sektion=8\&format=html) 的 NAT，请参见 [防火墙](/di-34-zhang-fang-huo-qiang/34.1.-gai-shu.md) 一章。
