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

反向VPN(WireGuard)环境下邮件服务器的iptables规则正确性验证及配置问题咨询

反向VPN(WireGuard)环境下邮件服务器的iptables规则正确性验证及配置问题咨询

问题描述

我搭建了一台VPS作为反向VPN,用来连接内网自建的邮件服务器(mailcow Docker容器),目前遇到了两个核心问题,希望能得到大佬的指导:

  1. 我自己拼凑了一套iptables规则脚本,想确认这套规则是否合理、正确,符合当前的架构需求;
  2. 邮件服务器的WireGuard配置中,按照教程设置AllowedIPs = 0.0.0.0/0时完全无法传输流量,但改用明确指定的IP地址就能正常工作,我对iptables完全是新手,不知道哪里出了问题。

环境架构说明

  • VPS:Oracle Linux 8系统,运行Docker和内核级WireGuard;上面部署了反向代理容器,负责VPS本地应用及内网邮件服务器的公网反向代理。
  • 内网邮件服务器:Rocky Linux 8系统,同样运行Docker和内核级WireGuard,位于NAT后方,除了mailcow容器外还托管了其他私有Web应用,本地也有反向代理容器。

当前配置文件

VPS端iptables规则脚本(/etc/wireguard/scripts/vps-load-wg-iptables.sh)

#!/bin/bash

set -x

# set up install and uninstall directives

A=-A

I=-I

if [[ "$1" == "down" ]]; then

A=-D

I=-D

fi

ip4_localip=10.0.0.11

ip4_wg_subnet=10.20.100

ip4_source=$ip4_wg_subnet.10

ip4_dest=$ip4_wg_subnet.11

# SET PUBLIC IP INTERFACE NAME

ni=enp0s3

# SET WIREGUARD INTERFACE NAME

wg=wg0

# SET FORWARDED PORTS

TCP_PORTS="25 110 143 465 587 993 995 4190"

# Accept it all.

# Per docker manual: iptables -I DOCKER-USER -i src_if -o dst_if -j ACCEPT

# to preserve linux routing capabilities.

# Docker requires forwards to be on its own chain, use DOCKER-USER instead of FORWARD

sudo iptables $I DOCKER-USER -i $wg -o $ni -j ACCEPT

sudo iptables $I DOCKER-USER -s $ip4_wg_subnet.0/24 -j ACCEPT

sudo iptables $I DOCKER-USER -m state --state RELATED,ESTABLISHED -j ACCEPT

for p in $TCP_PORTS

do

# Allow traffic on specified ports.

sudo iptables $A DOCKER-USER -i $ni -o $wg -p tcp --syn --dport $p -m conntrack --ctstate NEW -j ACCEPT

# Forward traffic from public network to wireguard on specified ports

sudo iptables -t nat $A PREROUTING -i $ni -p tcp --dport $p -j DNAT --to-destination $ip4_dest

# Forward traffic from wireguard back to public network on specified ports

sudo iptables -t nat $A POSTROUTING -o $wg -p tcp --dport $p -d $ip4_dest -j SNAT --to-source $ip4_source

done

# Source nat.

sudo iptables -t nat $A POSTROUTING -s $ip4_wg_subnet.0/24 ! -d $ip4_wg_subnet.0/24 -j SNAT --to $ip4_localip

# Masquerade.

sudo iptables -t nat $A POSTROUTING -o $wg -j MASQUERADE

VPS端wg0.conf

[Interface]
Address = 10.20.100.10/24
MTU = 1280
PrivateKey = KEY
ListenPort = 51820
PreUp = sysctl -w net.ipv4.ip_forward=1
PostUp = /etc/wireguard/scripts/vps-load-wg-iptables.sh
PostDown = /etc/wireguard/scripts/vps-load-wg-iptables.sh down
PostDown = sysctl -w net.ipv4.ip_forward=0

[Peer]
PublicKey = KEY
PresharedKey = KEY
AllowedIPs = 10.20.100.11/32, 10.20.1.11/32
PersistentKeepalive = 20

邮件服务器端wg0.conf

[Interface]
Address = 10.20.100.11/32
MTU = 1280
PrivateKey = KEY
PreUp = sysctl -w net.ipv4.ip_forward=1
PostDown = sysctl -w net.ipv4.ip_forward=0

[Peer]
PublicKey = KEY
PresharedKey = KEY
AllowedIPs = 10.20.100.10/32, 10.0.0.11/32
Endpoint = VPS_PUBLIC_IP:51820
PersistentKeepalive = 20

专家解答

一、WireGuard AllowedIPs 无法使用 0.0.0.0/0 的原因及修复

你遇到的这个问题是典型的路由冲突+Peer配置不匹配导致的:

  1. 路由优先级冲突:当邮件服务器设置AllowedIPs = 0.0.0.0/0时,WireGuard会添加一条默认路由(优先级高于内网默认网关),接管所有出站流量。但内网邮件服务器原本的默认网关指向NAT路由器,这时候两条默认路由会让系统无法判断流量走向,导致丢包。
  2. VPS端Peer配置限制:VPS的Peer配置中AllowedIPs仅包含10.20.100.11/32, 10.20.1.11/32,这意味着VPS只会转发发往这两个IP的流量,而不会处理邮件服务器发往公网的反向流量(当邮件服务器用0.0.0.0/0时,所有流量都会发往VPS,但VPS会因为AllowedIPs不匹配而丢弃这些流量)。

针对性修复方案

根据你的需求选择一种:

  • 需求1:仅让邮件入站流量通过VPS转发
    不需要把所有流量走WireGuard,邮件服务器的AllowedIPs只需设置为VPS的WireGuard IP和公网IP:

    AllowedIPs = 10.20.100.10/32, VPS_PUBLIC_IP/32
    

    这样邮件服务器只会和VPS通信,其他流量走内网默认网关,避免路由冲突。

  • 需求2:邮件服务器的所有流量(入站+出站)都通过VPS转发

    • 邮件服务器端:设置AllowedIPs = 0.0.0.0/0,并添加Table = auto让WireGuard自动管理路由表:
      [Interface]
      Address = 10.20.100.11/24
      MTU = 1280
      PrivateKey = KEY
      Table = auto
      PreUp = sysctl -w net.ipv4.ip_forward=1
      PostDown = sysctl -w net.ipv4.ip_forward=0
      
    • VPS端:修改Peer的AllowedIPs为0.0.0.0/0,允许接收邮件服务器的所有流量:
      [Peer]
      PublicKey = KEY
      PresharedKey = KEY
      AllowedIPs = 0.0.0.0/0
      PersistentKeepalive = 20
      

二、iptables规则的优化与正确性验证

你的脚本整体方向是对的,但有几个冗余和可优化的点:

  1. 规则顺序问题:iptables按匹配顺序执行,建议先处理已建立的连接,再处理新连接,避免规则被跳过:
    # 先放行已建立/相关的连接
    sudo iptables $I DOCKER-USER -m state --state RELATED,ESTABLISHED -j ACCEPT
    # 再放行WireGuard到公网的流量
    sudo iptables $I DOCKER-USER -i $wg -o $ni -j ACCEPT
    
  2. SNAT与MASQUERADE冲突:如果你VPS用的是固定公网IP,MASQUERADE(动态SNAT)完全多余,保留固定IP的SNAT即可,去掉这条规则:
    # 移除这条规则:sudo iptables -t nat $A POSTROUTING -o $wg -j MASQUERADE
    
  3. TCP规则冗余:--syn和--ctstate NEW重复,后者已经涵盖新的TCP连接,简化规则:
    sudo iptables $A DOCKER-USER -i $ni -o $wg -p tcp --dport $p -m conntrack --ctstate NEW -j ACCEPT
    
  4. WireGuard UDP端口放行:你完全漏掉了WireGuard本身的UDP端口(51820),需要在VPS的防火墙(比如firewalld)里放行,否则邮件服务器连不上VPS的WireGuard:
    sudo firewall-cmd --add-port=51820/udp --permanent
    sudo firewall-cmd --reload
    
  5. 冗余的SNAT规则:邮件服务器回复流量会自动通过WireGuard回到VPS,你添加的POSTROUTING针对邮件端口的SNAT规则完全多余,可以移除:
    # 移除这条规则:sudo iptables -t nat $A POSTROUTING -o $wg -p tcp --dport $p -d $ip4_dest -j SNAT --to-source $ip4_source
    

三、额外测试建议

  • 用iptables -L -v -n查看当前规则的匹配计数,确认流量是否命中规则;
  • 在VPS和邮件服务器的WireGuard接口用tcpdump抓包:
    # VPS端抓包
    sudo tcpdump -i wg0 port 25 or 465 or 587
    # 邮件服务器端抓包
    sudo tcpdump -i wg0 port 25 or 465 or 587
    
    通过抓包可以直观看到流量是否正常传输。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 13:27:45