You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用iptables mangle设置fwmark指定路由表时数据包源IP异常的原因及无需MASQUERADE的解决方案

iptables mangle设置fwmark指定路由表时数据包源IP异常的原因及无需MASQUERADE的解决方案

问题根源:Linux路由决策的两步顺序

你遇到的核心问题是Linux内核处理数据包的顺序导致的
当程序发起网络请求时,内核会分两步做路由决策:

  1. 第一步:选择源IP地址——这一步内核默认只会参考主路由表(table 254),不会考虑你设置的fwmark规则。你的主路由表默认走公网网关,所以内核直接选了服务器的公网IP作为数据包的源地址。
  2. 第二步:选择出口网关——这时候才会检查fwmark规则,把数据包转到你自定义的TABLE路由表,走WireGuard的网关。但此时源IP已经确定是公网IP了,VPN服务器收到这种来源的数据包自然会拒绝,导致请求失败。

你后来加的MASQUERADE只是事后补救:把发往wg0接口的数据包源IP改成wg0的内部IP,让VPN服务器接受,但这确实是个“绕路”的办法。

无需MASQUERADE的解决方案:让源IP选择也用自定义路由表

要从根本上解决,我们需要让内核在选择源IP的时候就使用自定义的TABLE,而不是只在选网关时才用。这里有两种更直接的方式:

方式一:直接基于用户组添加策略路由(推荐)

跳过iptables标记的步骤,直接让指定组的所有流量从源IP选择到路由转发都用TABLE:

  1. 先清理之前的fwmark相关规则(如果已经配置过):
    # 删除iptables标记规则
    iptables -t mangle -D OUTPUT -m owner --gid-owner GROUPNAME -j MARK --set-mark MARK
    # 删除fwmark对应的路由规则
    ip rule del fwmark MARK table TABLE
    
  2. 获取目标组的GID(组ID):
    getent group GROUPNAME | cut -d: -f3
    
  3. 添加基于GID的策略路由规则,优先级设得比主表高(主表默认优先级32766),确保这条规则先被匹配:
    ip rule add gidrange [GID]:[GID] table TABLE priority 100
    
  4. 确保自定义TABLE的路由配置完整:
    # 让VPN子网的流量直接走wg0接口
    ip route add VPN_SUBNET/24 dev wg0 table TABLE
    # 默认路由指向VPN网关
    ip route add default via VPN_GATEWAY table TABLE
    # 关键:VPN服务器的公网IP必须走原来的公网网关,不然连不上VPN服务器本身
    ip route add VPN_SERVER_IP via INTERNET_GATEWAY table TABLE
    

这样配置后,当GROUPNAME组的程序发数据包时,内核会直接用TABLE来选源IP——TABLE里有wg0的子网路由,所以会自动选wg0的内部IP作为源,完全不需要MASQUERADE。

方式二:保留fwmark,但补充源地址选择规则

如果你想保留iptables标记的方式,需要额外加一条规则,让标记了MARK的数据包在选源IP时也用TABLE:

# 先保留原来的iptables标记规则和fwmark路由规则
# 再添加这条规则,让标记包的源IP选择用TABLE
ip rule add fwmark MARK from all lookup TABLE priority 101

这条规则会告诉内核:所有标记了MARK的数据包,在选择源IP时也要查询TABLE,这样就能选到wg0的内部IP了。

验证方法

配置完成后,用ip rule show查看规则是否生效,然后用sudo -g GROUPNAME curl ifconfig.me测试,返回的应该是你的VPN内部IP,而不是服务器公网IP。

备注:内容来源于stack exchange,提问作者g00dds

火山引擎 最新活动