服务公告
WireGuard:故障排查
发布时间:2026-04-23 10:02
WireGuard:故障排查
一、前言
搞过WireGuard的人都晓得,这玩意儿配起来快,出问题排查起来是真他妈的蛋疼。明明配置文件看着没问题,ping就是不通,手册看烂了还是一头雾水。这篇不废话,直接从实战出发,手把手教你把WireGuard的疑难杂症一个个揪出来。
二、操作步骤
步骤1:确认WireGuard服务状态和内核模块加载
很多问题根源在于WireGuard压根没跑起来,先把基础状态摸清楚。
# 检查内核模块是否加载(所有发行版通用)
lsmod | grep wireguard
# 预期输出:
# wireguard 212992 0
# ip6_udp_tunnel 16384 1 wireguard
# udp_tunnel 16384 1 wireguard
# 检查wg0接口是否存在
ip link show wg0
# 预期输出(已配置):
# 4: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
# link/nopeer 10.0.0.1 peer 10.0.0.2
# 检查服务状态(systemd系统)
systemctl status wg-quick@wg0
# 预期输出:
# ● wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0
# Loaded: loaded (/lib/systemd/system/wg-quick@.service; enabled)
# Active: active (exited) since Mon 2024 01:30:00 CST; 2 days ago如果模块没加载,手动加载一下:
# 加载内核模块
modprobe wireguard
# 确认版本
wg --version
# 预期输出:
# wg 1.0.20210424步骤2:核对服务端配置文件
服务端配置错一个字符都白搭,这条老哥们踩的坑最多。
# 查看当前运行配置(关键!这是实际生效的配置)
wg show
# 预期输出示例:
# interface: wg0
# public key: XXXXXXXXXXXXXXX=
# private key: (hidden)
# listening port: 51820
# peer: YYYYYYYYYYYYYYY=
# endpoint: 203.0.113.50:51820
# allowed ips: 10.0.0.2/32
# persistent keepalive: every 25 seconds
# 查看配置文件内容
cat /etc/wireguard/wg0.conf
# CentOS/RHEL路径
cat /etc/wireguard/wg0.conf
# Ubuntu路径(同样适用)
cat /etc/wireguard/wg0.conf
# 预期输出结构:
# [Interface]
# Address = 10.0.0.1/24
# ListenPort = 51820
# PrivateKey = SERVER_PRIVATE_KEY_BASE64
# PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# [Peer]
# PublicKey = CLIENT_PUBLIC_KEY_BASE64
# AllowedIPs = 10.0.0.2/32⚠️ 警告:PostUp/PostDown里的iptables命令执行后不可逆,操作前确认好规则。
步骤3:核对客户端配置和密钥配对
密钥不配对,握手都别想成功。这是80%连接失败的原因。
# 服务端生成本机密钥对(如果还没生成)
wg genkey | tee privatekey | wg pubkey > publickey
# 在服务端查看客户端的公钥
# 假设客户端把你的公钥发过来了,服务端配置里应该有对应的Peer
wg show wg0 peers
# 预期输出:
# YYYYYYYYYYYYYYY= <-- 这是客户端的公钥
# 客户端配置示例(/etc/wireguard/wg0.conf)
# [Interface]
# PrivateKey = CLIENT_PRIVATE_KEY_BASE64
# Address = 10.0.0.2/24
# DNS = 8.8.8.8
# [Peer]
# PublicKey = SERVER_PUBLIC_KEY_BASE64
# Endpoint = your-server-ip:51820
# AllowedIPs = 0.0.0.0/0
# PersistentKeepalive = 25
# 验证公钥是否匹配
# 在服务端和客户端分别执行:
wg pubkey < privatekey
# 两边的PublicKey必须完全一致步骤4:测试网络连通性
配置没问题但不通,先确认网络层能不能到达。
# 客户端测试到服务端UDP端口的连通性
# 注意:WireGuard用UDP,不是TCP!
nc -vzu SERVER_IP 51820
# 预期输出:
# Connection to SERVER_IP 51820 port [udp/*] succeeded!
# 或者用nmap(如果没有nc)
nmap -sU -p 51820 SERVER_IP
# 预期输出:
# PORT STATE SERVICE
# 51820/udp open|filtered unknown
# 检查服务端是否在监听
ss -ulnp | grep 51820
# 预期输出:
# UNDEFIED 0 0 *:51820 *:* users:(("wg-quick",pid=1234),("wg-crypt",pid=1235))
# 从服务端ping客户端的WireGuard IP(需要在AllowedIPs范围内)
ping -c 3 10.0.0.2
# 预期输出:
# PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
# 64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=50.2 ms
# 如果ping不通但配置都正确,检查客户端防火墙是否允许ICMP步骤5:检查防火墙规则
防火墙是个大坑,无数人栽在这。服务端和客户端都要检查。
# ================ 服务端操作 ================
# 检查iptables FORWARD链(CentOS/RHEL和Ubuntu通用)
iptables -L FORWARD -v -n
# 预期输出应包含:
# ACCEPT all -- wg0 * 0.0.0.0/0 0.0.0.0/0
# ACCEPT all -- * wg0 0.0.0.0/0 0.0.0.0/0
# 检查NAT/POSTROUTING规则
iptables -t nat -L POSTROUTING -v -n
# 预期输出应包含:
# MASQUERADE all -- * eth0 10.0.0.0/24 0.0.0.0/0
# CentOS/RHEL额外检查firewalld
firewall-cmd --list-all
# 预期输出:
# public (active)
# interfaces: eth0
# services: dhcpv6-client ssh wireguard
# 如果没有wireguard服务,手动添加
firewall-cmd --permanent --add-service=wireguard
firewall-cmd --reload
# CentOS/RHEL检查SELinux
getenforce
# 预期输出:Disabled 或 Enforcing(如果Enforcing需要配置)
# ================ 客户端操作 ================
# Ubuntu/Debian检查ufw
ufw status
# 如果开启,确保允许wg0
ufw allow from 10.0.0.0/24
ufw reload
# macOS客户端检查系统偏好设置
# 确保VPN配置已启用且允许连接⚠️ 警告:iptables -F 会清空所有规则,非必要勿用。调试时用 -C 检查而非 -A。
步骤6:检查MTU和分片问题
MTU不匹配会导致包被丢弃,表现为能ping但实际流量不通。
# 检查服务端wg0接口MTU
ip link show wg0
# 预期输出:
# 4: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420
# 检查物理接口MTU
ip link show eth0
# 预期输出:
# 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
# MTU计算:物理MTU - WireGuard头(60) - IP头(20) = 典型值1420
# 如果物理MTU是1500,wg0应该是1420
# 从客户端测试MTU路径
tracepath -m 5 SERVER_PUBLIC_IP
# 预期输出:
# 1?: [LOCALHOST] pmtu 1500
# 1: gateway 58ms
# 2: SERVER_IP 55ms pmtu 1500
# 手动设置MTU(如果需要调整)
# 在/etc/wireguard/wg0.conf的[Interface]段添加:
# MTU = 1380
# 调试:使用ping测试分片
ping -M do -s 1300 SERVER_WG_IP
# 如果不通,降低-s值重试步骤7:查看握手和加密日志
WireGuard加密出问题会导致握手失败。
# 实时监控WireGuard状态变化(调试模式)
# 重启wg0接口观察日志
wg-quick down wg0
wg-quick up wg0
# journalctl查看systemd日志
journalctl -u wg-quick@wg0 -f --since "1 minute ago"
# CentOS/RHEL和Ubuntu通用
# 检查是否有握手时间戳(判断是否在通讯)
wg show wg0
# 预期输出:
# peer: YYYYYYYYYYYYYYY=
# endpoint: 203.0.113.50:51820
# allowed ips: 10.0.0.2/32
# latest handshake: 45 seconds ago <-- 这个时间戳说明握手正常
# transfer: 10.50 MiB received, 2.30 MiB sent
# 如果latest handshake显示Never,说明没有成功握手
# 启用WireGuard调试日志(临时)
echo 'module wireguard +p' | sudo tee /sys/kernel/debug/dynamic_debug/control
# 预期输出:
# module wireguard +p
# 查看调试日志
dmesg -w | grep wireguard步骤8:验证路由和AllowedIPs
AllowedIPs配置错误是最容易被忽视的问题源头。
# 查看服务端路由表
ip route
# 确保有类似这样的路由:
# 10.0.0.0/24 dev wg0 proto kernel scope link src 10.0.0.1
# 查看详细路由信息
ip route show dev wg0
# 预期输出:
# 10.0.0.0/24 proto kernel link src 10.0.0.1
# 在客户端检查路由(Split Tunnel vs 全流量)
# Split Tunnel模式(只有特定流量走WireGuard):
ip route | grep wg0
# 10.0.0.0/24 dev wg0 proto kernel scope link src 10.0.0.2
# 全流量模式(所有流量走WireGuard):
ip route
# default dev wg0 proto static metric 50
# 10.0.0.0/24 dev wg0 proto kernel scope link src 10.0.0.2
# 测试特定IP是否走WireGuard
ip route get 8.8.8.8
# 全流量模式预期:
# 8.8.8.8 dev wg0 src 10.0.0.2 mark 0xdeadbeef
# Split Tunnel模式预期:
# 8.8.8.8 via 实际网关 dev eth0 src 实际IP三、常见问题FAQ
Q1: "latest handshake显示Never,配置检查八百遍了还是不通,什么鬼?"
老哥,别光看配置,先用tcpdump抓包确认包到底到没到:
# 服务端抓UDP 51820端口
tcpdump -i eth0 udp port 51820 -n
# 预期输出(如果客户端发包了):
# 15:30:01.234567 IP CLIENT_IP.12345 > SERVER_IP.51820: UDP, length 148
# 15:30:01.234800 IP SERVER_IP.51820 > CLIENT_IP.12345: UDP, length 148
# 如果只看到发出去没收到回来,检查:
# 1. 服务端防火墙是否拦住入站UDP
# 2. 云服务商安全组是否放行UDP 51820(这条坑了最多人)
# 3. NAT类型问题
# 云平台安全组检查(AWS EC2为例):
# 入站规则必须允许:Custom UDP 51820 0.0.0.0/0
# 阿里云安全组:
# 自定义UDP 51820 0.0.0.0/0Q2: "能ping通WireGuard IP,但访问内网服务就超时,脑子嗡嗡的"
这明显是路由或防火墙的锅,别慌:
# 第一步:确认服务端FORWARD是否开启
cat /proc/sys/net/ipv4/ip_forward
# 必须输出 1,否则:
echo 1 | tee /proc/sys/net/ipv4/ip_forward
# 永久生效(CentOS/RHEL):
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
# 永久生效(Ubuntu):
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.d/99-wireguard.conf
# 第二步:确认MASQUERADE规则存在
iptables -t nat -L POSTROUTING -n | grep MASQUERADE
# 没有的话补上(CentOS/RHEL和Ubuntu通用):
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# PostUp里没配置的话要手动加
# 第三步:确认FORWARD规则
iptables -L FORWARD -n | grep wg0
# 没有的话:
iptables -A FORWARD -i wg0 -j ACCEPT
iptables -A FORWARD -o wg0 -j ACCEPT
# 第四步:如果是访问内网特定网段,确认AllowedIPs包含那个网段
# 服务端wg0.conf的[Peer]段:
# AllowedIPs = 10.0.0.2/32, 192.168.1.0/24Q3: "手机端WireGuard经常断线,电脑端没事,什么原因?"
移动网络环境复杂,NAT超时和Keepalive是核心:
# 确保客户端配置了PersistentKeepalive(25秒是个经验值)
# 在客户端/etc/wireguard/wg0.conf的[Peer]段:
[Peer]
PublicKey = SERVER_PUBLIC_KEY_BASE64
Endpoint = your-server-ip:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
# 服务端也可以设置,但客户端设置更关键
# 如果移动网络特别差,可以降到15秒
# 检查服务端是否限制了连接数
# 有些云服务商会限制UDP并发连接数
# 查看握手日志判断断线频率
wg show wg0
# 如果latest handshake时间一直在跳动但频繁重置,说明网络不稳定
# 如果latest handshake一直是固定时间(几小时前),说明已经断了
# 建议在手机上开启WireGuard的"Connect on Demand"功能(iOS/Android)
# 这样只在需要时建立连接,减少断线重连的频率Q4: "服务端重启后客户端全部需要重新导入配置,烦死了"(这条是老手向)
服务端重启不会影响客户端配置,除非你换了密钥:
# 如果重启后客户端全挂,检查以下原因:
# 1. 服务端IP变了(DHCP获取的情况)
# 解决:给服务器绑定静态IP或使用DDNS
# 2. 防火墙规则没持久化
# 检查PostUp/PostDown是否写入/etc/wg-keys.conf等配置文件
# CentOS/RHEL确保iptables服务enabled:
systemctl enable iptables
# Ubuntu确保iptables-persistent包已安装
# 3. 内核模块没自动加载
# 编辑 /etc/modules-load.d/wireguard.conf:
echo "wireguard" > /etc/modules-load.d/wireguard.conf
# 4. wg-quick服务没自动启动
systemctl enable wg-quick@wg0
# CentOS/RHEL和Ubuntu通用
# 5. 配置文件被覆盖(云服务商重置镜像的情况)
# 解决:备份配置到非系统目录四、总结
核心要点
- 排查顺序:服务状态 → 配置文件 → 密钥配对 → 网络连通性 → 防火墙 → MTU → 路由
- 最常见问题:云平台安全组没放行UDP、云服务商限制UDP并发、防火墙拦住包
- 调试神器:wg show 看状态、tcpdump 抓包、journalctl 查日志
- 密钥问题:服务端和客户端公钥必须配对,用 wg pubkey < privatekey 验证
- Keepalive:移动网络必开,25秒是经验值
- MTU:一般设置1420,PPPoE环境要更低(1380)
延伸阅读
- WireGuard官方文档:https://www.wireguard.com/quickstart/
- WireGuard mailing list archives:https://lists.zx2c4.com/mailman/listinfo/wireguard
- 官方故障排查指南:https://www.wireguard.com/known-limitations/
- iptables参考:https://www.frozentux.net/iptables-tutorial/
- Cloudflare关于WireGuard MTU的说明:https://blog.cloudflare.com/announcing-warp-for-linux/
最后说一句:WireGuard这玩意儿配好了是真稳,出问题大概率是配置文件或者防火墙的锅。按这个排查流程走,八成能定位到问题。遇到云平台限制就换端口或者走TCP over WebSocket,别死磕UDP。
相关推荐
上一篇: Claude:安装配置
下一篇: Nmap:安全审计