8.4. 使用 nftables 配置 NAT
有了 nftables
,您就可以配置以下网络地址转换(NAT)类型:
- 伪装
- 源 NAT(SNAT)
- 目标 NAT(DNAT)
- 重定向
您只能在 iifname
和 oifname
参数中使用实际的接口名称,不支持替代名称(altname
)。
8.4.1. NAT 类型
这些是不同的网络地址转换(NAT)类型:
- 伪装和源 NAT(SNAT)
使用以上 NAT 类型之一更改数据包的源 IP 地址。例如,互联网服务提供商(ISP)不会路由私有 IP 范围,如
10.0.0.0/8
。如果您在网络中使用私有 IP 范围,并且用户可以访问互联网上的服务器,请将这些范围内的数据包的源 IP 地址映射到公共 IP 地址。伪装和 SNAT 相互类似。不同之处是:
- 伪装自动使用传出接口的 IP 地址。因此,如果传出接口使用了动态 IP 地址,则使用伪装。
- SNAT 将数据包的源 IP 地址设置为指定的 IP 地址,且不会动态查找传出接口的 IP 地址。因此,SNAT 要比伪装更快。如果传出接口使用了固定 IP 地址,则使用 SNAT。
- 目标 NAT(DNAT)
- 使用此 NAT 类型重写传入数据包的目标地址和端口。例如,如果您的 Web 服务器使用私有 IP 范围内的 IP 地址,因此无法直接从互联网访问,那么您可以在路由器上设置一个 DNAT 规则,来将传入的流量重定向到此服务器。
- 重定向
- 这个类型是 IDT 的特殊示例,它根据链 hook 将数据包重定向到本地机器。例如,如果服务运行在与其标准端口不同的端口上,您可以将传入的流量从标准端口重定向到此特定端口。
8.4.2. 使用 nftables 配置伪装
伪装使路由器动态地更改通过接口到接口 IP 地址发送的数据包的源 IP。这意味着,如果接口被分配了一个新 IP,nftables
会在替换源 IP 时自动使用新的 IP。
将通过 ens3
接口离开主机的数据包源 IP 替换为 ens3
上设置的 IP。
流程
创建一个表:
# nft add table nat
向表中添加
prerouting
和postrouting
链:# nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
重要即使您没有向
prerouting
链中添加规则,nftables
框架也会要求此链与传入的数据包回复匹配。请注意,您必须将
--
选项传递给nft
命令,以防止 shell 将负优先级值解释为nft
命令的选项。向
postrouting
链中添加一条规则,来匹配ens3
接口上传出的数据包:# nft add rule nat postrouting oifname "ens3" masquerade
8.4.3. 使用 nftables 配置源 NAT
在路由器中,源 NAT(SNAT)可让您将通过接口发送的数据包 IP 改为专门的 IP 地址。然后,路由器会替换传出数据包的源 IP。
流程
创建一个表:
# nft add table nat
向表中添加
prerouting
和postrouting
链:# nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
重要即使您没有向
postrouting
链添加规则,nftables
框架也会要求此链与传出数据包回复相匹配。请注意,您必须将
--
选项传递给nft
命令,以防止 shell 将负优先级值解释为nft
命令的选项。向
postrouting
链中添加一条规则,该规则将使用192.0.2.1
替换通过ens3
的传出数据包的源 IP :# nft add rule nat postrouting oifname "ens3" snat to 192.0.2.1
8.4.4. 使用 nftables 配置目标 NAT
目标 NAT (DNAT)可让您将路由器上的流量重定向到从互联网无法访问的主机。
例如,对于 DNAT,路由器将发送到端口 80
和 443
的传入流量重定向到 IP 地址为 192.0.2.1
的 Web 服务器。
流程
创建一个表:
# nft add table nat
向表中添加
prerouting
和postrouting
链:# nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; } # nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
重要即使您没有向
postrouting
链添加规则,nftables
框架也会要求此链与传出数据包回复相匹配。请注意,您必须将
--
选项传递给nft
命令,以防止 shell 将负优先级值解释为nft
命令的选项。向
prerouting
链中添加一条规则,该规则将路由器的ens3
接口上端口80
和443
的传入流量重定向到 IP 地址为192.0.2.1
的 web 服务器:# nft add rule nat prerouting iifname ens3 tcp dport { 80, 443 } dnat to 192.0.2.1
根据您的环境,添加 SNAT 或伪装规则,将从 Web 服务器返回的数据包的源地址改为发送者:
如果
ens3
接口使用动态 IP 地址,请添加一条伪装规则:# nft add rule nat postrouting oifname "ens3" masquerade
如果
ens3
接口使用静态 IP 地址,请添加一条 SNAT 规则。例如,如果ens3
使用198.51.100.1
IP 地址:# nft add rule nat postrouting oifname "ens3" snat to 198.51.100.1
启用数据包转发:
# echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf # sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf
其他资源
8.4.5. 使用 nftables 配置重定向
重定向
功能是目标网络地址转换(DNAT)的一种特殊情况,它根据链 hook 将数据包重定向到本地计算机。
例如,您可以将发送到本地主机端口 22
的流量重定向到端口 2222
。
流程
创建一个表:
# nft add table nat
向表中添加
prerouting
链:# nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; }
请注意,您必须将
--
选项传递给nft
命令,以防止 shell 将负优先级值解释为nft
命令的选项。向
prerouting
链中添加一条规则,其将端口22
上的传入流量重定向到端口2222
:# nft add rule nat prerouting tcp dport 22 redirect to 2222
其他资源
8.4.6. 使用 nftables 配置 flowtable
nftables
工具使用 netfilter
框架为网络流量提供网络地址转换(NAT),并提供基于快速路径功能的 flowtable
机制来加快数据包转发。
flowtable 机制有以下功能:
- 使用连接跟踪来绕过典型的数据包转发路径。
- 避免通过绕过经典数据包处理来重新访问路由表。
- 只适用于 TCP 和 UDP 协议。
- 硬件独立软件快速路径。
流程
添加
inet
系列的一个example-table
:# nft add table inet <example-table>
添加一个带有
ingress
钩子和filter
作为优先级类型的example-flowtable
flowtable :# nft add flowtable inet <example-table> <example-flowtable> { hook ingress priority filter \; devices = { enp1s0, enp7s0 } \; }
将
example-forwardchain
流添加到数据包处理表中的 flowtable :# nft add chain inet <example-table> <example-forwardchain> { type filter hook forward priority filter \; }
此命令添加了一个带有
forward
钩子和filter
优先级的filter
类型的 flowtable 。添加一个
established
连接跟踪状态的规则,来卸载example-flowtable
流:# nft add rule inet <example-table> <example-forwardchain> ct state established flow add @<example-flowtable>
验证
验证
example-table
的属性:# nft list table inet <example-table> table inet example-table { flowtable example-flowtable { hook ingress priority filter devices = { enp1s0, enp7s0 } } chain example-forwardchain { type filter hook forward priority filter; policy accept; ct state established flow add @example-flowtable } }
其他资源
-
您系统上的
nft (8)
手册页