You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用nftables在接口间转发时对IP地址段进行NAT转换

解决方案:WireGuard自动推送路由 + nftables段到段NAT映射

刚好碰到过类似的部署场景,我来帮你搞定这两个头疼的问题——不用让VPN客户端手动加路由,还能解决多设备间的vlan子网IP冲突,结合WireGuard的原生配置和nftables的段映射NAT就能完美解决,一步步来:

一、搞定客户端手动加路由的问题

其实不用碰nftables,直接在WireGuard服务端配置里就能自动给客户端推送目标子网的路由,省得用户每次连接都要敲命令:

  1. 编辑WireGuard服务端的wg0.conf配置文件:
    • 如果你是给特定客户端推送路由,就在对应的[Peer]段落里更新AllowedIPs,先把原来的192.168.0.0/24加进去(后续做NAT后再调整):
      [Peer]
      PublicKey = <你的客户端公钥>
      AllowedIPs = 10.0.0.2/32, 192.168.0.0/24
      
    • 要是想给所有连接的客户端都推这条路由,就在服务端的[Interface]段加PostUp命令,同时确保路由转发生效:
      [Interface]
      PrivateKey = <服务端私钥>
      Address = 10.0.0.1/16
      ListenPort = 51820
      PostUp = nft add rule ip nat POSTROUTING oifname wg0 masquerade; ip route add 192.168.0.0/24 dev eth0.vlan1
      PostDown = nft delete rule ip nat POSTROUTING oifname wg0 masquerade; ip route del 192.168.0.0/24 dev eth0.vlan1
      
  2. 重启WireGuard服务让配置生效:
    wg-quick down wg0 && wg-quick up wg0
    

这样客户端一连接VPN,就会自动获取到目标子网的路由,再也不用手动执行ip route add了。

二、解决多设备vlan子网IP冲突:nftables段到段NAT映射

核心思路是把每个设备上的192.168.0.0/24子网,映射到各自WireGuard子网下的一个专属段——比如第一台设备用10.0.1.0/24映射192.168.0.0/24,第二台用10.1.1.0/24,这样就不会冲突了。用nftables的SNAT和DNAT就能实现整个网段的映射:

步骤1:准备nftables的NAT表和链

先确保nat表和必要的链存在(如果之前没配置过的话):

# 创建nat表(不存在就新建)
nft add table ip nat

# 创建POSTROUTING链,用来做源地址转换
nft add chain ip nat POSTROUTING { type nat hook postrouting priority 100 \; }

# 创建PREROUTING链,用来做目的地址转换
nft add chain ip nat PREROUTING { type nat hook prerouting priority -100 \; }

步骤2:添加段到段的NAT规则

假设当前设备的WireGuard子网是10.0.0.0/16,我们把192.168.0.0/24映射到10.0.1.0/24:

1. SNAT:把vlan设备的源IP转成映射后的10段IP

当eth0.vlan1上的设备访问VPN客户端时,自动把源IP从192.168.0.x换成10.0.1.x:

nft add rule ip nat POSTROUTING oifname wg0 ip saddr 192.168.0.0/24 snat to 10.0.1.0/24

2. DNAT:把VPN客户端的目标IP转成vlan设备的真实IP

当VPN客户端访问10.0.1.x时,自动把目标IP换成对应的192.168.0.x:

nft add rule ip nat PREROUTING iifname wg0 ip daddr 10.0.1.0/24 dnat to 192.168.0.0/24

步骤3:保存规则,确保重启不丢失

把当前的nftables规则保存到配置文件,这样重启后还能生效:

nft list ruleset > /etc/nftables.conf

然后启用nftables服务开机自启:

systemctl enable --now nftables

步骤4:更新WireGuard的路由推送

现在客户端不需要访问原来的192.168.0.0/24了,而是访问映射后的10.0.1.0/24,所以要更新服务端的AllowedIPs:

[Peer]
PublicKey = <客户端公钥>
AllowedIPs = 10.0.0.2/32, 10.0.1.0/24

这样客户端连接后会自动获取10.0.1.0/24的路由,访问这个网段的流量会通过VPN转发,再被nftables转换成真实的192.168.0.0/24地址。

三、验证配置是否生效

  1. 查看WireGuard的连接状态,确认客户端的AllowedIPs已经更新:
    wg show wg0
    
  2. 查看nftables的规则,确认SNAT和DNAT规则已经添加:
    nft list table ip nat
    
  3. 客户端连接VPN后,尝试ping10.0.1.1(对应真实的192.168.0.1),看看能不能连通。

几个要注意的点

  • 每台VPN设备的映射子网要不一样:比如第二台设备用10.1.1.0/24映射192.168.0.0/24,第三台用10.2.1.0/24,这样映射后的网段就不会冲突了。
  • 一定要开启Linux内核的IP转发:
    echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf
    sysctl -p
    
  • 如果你之前有其他nftables的转发规则,要确保这些NAT规则和现有规则兼容,别让流量被拦截了。

内容的提问来源于stack exchange,提问作者Oliver Gaskell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 12:27:39