前言
我并不是程序员,也不是网络工程师,只是一个喜欢动手折腾的普通用户。
之所以想搭一个 WireGuard,最初的原因很简单:出门在外时,希望能安全地访问家里的 NAS、摄像头,或者让手机流量走家里的网络——既为了隐私,也为了方便。
网上关于 WireGuard 的教程很多,但要么太简略,跳过关键细节;要么默认读者已经懂 iptables、NAT、MTU 这些概念,让我这种半路出家的人看得一头雾水。于是,我决定把自己从零开始摸索的过程完整记下来:
- 在树莓派上怎么安装?
- 配置文件每行是什么意思?
- 为什么连上了却上不了网?
- IPv6 怎么一起配?
- 出错了该怎么一步步排查?
这篇文章没有高深理论,只有我在实践中踩过的坑、验证有效的配置,以及最终让它稳定跑起来的经验。如果你和我一样,只是想为自己搭一个简单、安全、能用的私人网络通道,希望这份笔记能帮你少走些弯路。
计算机网络架构理论 —— 分层模型
为了降低复杂性,网络设计普遍采用“分而治之”的思想,将庞大的通信过程划分为多个明确定义的层级。
OSI 七层参考模型(理论模型)
这是一个理论上的标准框架,定义了网络功能的七个层次。虽然实际中并未完全实现,但其思想极具影响力。
| 层级 | 名称 | 功能简介 | 协议数据单元 | 举例 |
|---|---|---|---|---|
| 7 | 应用层 | 为应用程序提供网络服务接口 | 报文/消息 | HTTP, FTP, SMTP |
| 6 | 表示层 | 数据格式转换、加密解密 | 报文/消息 | JPEG, MPEG, SSL/TLS(部分) |
| 5 | 会话层 | 建立、管理和终止会话 | 报文/消息 | RPC, PPTP(现已不常见) |
| 4 | 传输层 | 端到端的连接、可靠性、流量控制 | 段(TCP)/数据报(UDP) | TCP, UDP |
| 3 | 网络层 | 逻辑寻址、路由选择(跨网络) | 分组/包 | IP, ICMP, 路由器 |
| 2 | 数据链路层 | 介质访问、物理寻址(MAC)、差错校验 | 帧 | Ethernet, PPP, 交换机 |
| 1 | 物理层 | 比特流在物理介质上的传输 | 比特 | 双绞线、光纤、无线电波 |
核心思想:每一层为其上一层提供服务,并使用其下一层提供的服务。发送方数据从高层到低层“封装”,接收方则从低层到高层“解封装”。
TCP/IP 四层模型(实际架构)
这是互联网实际使用的、更简洁的架构模型。它常被看作是OSI模型的浓缩和实践。
| TCP/IP 层级 | 对应 OSI 层级 | 核心协议 | 功能 |
|---|---|---|---|
| 应用层 | 应用层、表示层、会话层 | HTTP, FTP, DNS, SMTP | 处理高级别的通信任务 |
| 传输层 | 传输层 | TCP, UDP | 进程到进程的通信、可靠性 |
| 网络层(网际层) | 网络层 | IP, ICMP, ARP | 主机到主机的通信、路由 |
| 网络接口层 | 数据链路层、物理层 | Ethernet, WiFi, PPP | 在本地网络链路上传输数据 |
iptables 防火墙知识
第一部分:核心概念 – “四表五链”与数据包流向
这是理解 iptables 的基石,必须首先掌握。
1. 五链 – 数据包的五个“检查点”
链是规则的集合。数据包经过这些检查点时,会按顺序匹配链中的规则,以决定其命运(放行、丢弃、修改等)。
- PREROUTING链:数据包刚进入网络接口,在路由决策之前。常用于修改目标地址(DNAT)。
- INPUT链:数据包的目标地址是本机(例如,有人访问本机的Web服务)。
- FORWARD链:数据包的目标地址是其他机器,本机充当路由器/网关,需要转发它。
- OUTPUT链:数据包由本机进程产生,正要发送出去。
- POSTROUTING链:数据包即将离开网络接口,在路由决策之后。常用于修改源地址(SNAT/Masquerade)。
2. 四表 – 规则的不同“功能类别”
表是规则的分类,每个表用于实现不同的功能。链中包含着属于不同表的规则。
- filter表:负责过滤数据包(放行、丢弃、拒绝)。最常用的表。
- nat表:负责网络地址转换(例如,端口转发、共享上网)。
- mangle表:负责修改数据包的头信息(如TTL、TOS标记等)。用于高级操作。
- raw表:负责连接跟踪机制前的数据包处理。用于豁免某些连接不被跟踪。
关键记忆点:
- 一个数据包不会经过所有链。
PREROUTING和POSTROUTING是“绕城高速”,处理路过或需要地址转换的包。INPUT和OUTPUT是“市区道路”,处理本机收发的包。FORWARD是“过境通道”,处理由本机转发的包。
第二部分:基本命令语法与常用参数
1. 基本语法结构
iptables [-t 表名] 命令选项 [链名] [匹配条件] -j 目标动作
-t 表名:指定操作的表(如filter,nat)。省略时默认为filter表。- 命令选项:告诉 iptables 要做什么(增、删、改、查规则)。
- 链名:指定操作的链(如
INPUT,FORWARD)。 - 匹配条件:指定规则匹配数据包的特征(如协议、端口、IP等)。
-j 目标动作:数据包匹配规则后要执行的操作(如ACCEPT,DROP)。
2. 常用命令选项
-A|--append:在链的末尾追加一条规则。iptables -A INPUT -s 192.168.1.100 -j ACCEPT-I|--insert:在链的指定位置插入一条规则(默认为第1条)。iptables -I INPUT 3 ...(插入为第3条)-D|--delete:从链中删除一条规则。iptables -D INPUT 2(删除第2条)或iptables -D INPUT -s 192.168.1.100 -j ACCEPT(按内容删除)-L|--list:列出链中的所有规则。iptables -L -n -v:-n(不解析域名,显示IP),-v(显示详细信息),推荐组合使用。iptables -L --line-numbers:显示规则的行号,便于删除。
-F|--flush:清空指定链的所有规则(不指定链则清空所有链)。iptables -F INPUT-P|--policy:设置链的默认策略(默认策略是未被任何规则匹配的数据包的处理方式)。iptables -P INPUT DROP(警告:远程操作时慎用,可能导致断连)-N|--new-chain:创建一条自定义链。-X|--delete-chain:删除一条空的自定义链。
第三部分:各种匹配条件和动作
1. 常用匹配条件
- 通用匹配:
-p | --protocol:协议(tcp,udp,icmp,all)。-s | --source:源IP地址或网段(192.168.1.100或192.168.1.0/24)。-d | --destination:目标IP地址或网段。-i | --in-interface:数据包进入的网络接口(如eth0,wlan0)。常用于INPUT,FORWARD,PREROUTING链。-o | --out-interface:数据包离开的网络接口。常用于OUTPUT,FORWARD,POSTROUTING链。
- 隐含匹配(需用
-p指定协议后自动生效):- TCP/UDP:
--sport | --source-port:源端口。--dport | --destination-port:目标端口。--tcp-flags:TCP标志位匹配(用于高级状态检测)。
- ICMP:
--icmp-type:ICMP类型(如8为请求回显ping,0为回显应答)。
- TCP/UDP:
- 显式匹配(需用
-m显式加载模块):-m state --state:状态匹配(极其重要!)- 状态有:
NEW(新连接),ESTABLISHED(已建立的连接),RELATED(相关的连接,如FTP的数据连接),INVALID(无效的数据包)。 iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT(允许已建立连接及相关连接通过,这是保证通信顺畅的关键规则)。
- 状态有:
-m multiport:多端口匹配。--dports 22,80,443(匹配目标端口22,80,443)。
-m limit:限制匹配速率,用于限制日志记录,防止日志爆满。--limit 5/minute(限制为每分钟5次匹配)。
-m recent:近期匹配,用于防御暴力破解。- 可以动态封禁短时间内频繁连接的IP。
2. 常用目标动作
ACCEPT:接受数据包。DROP:丢弃数据包(无任何响应,对方感觉像掉线一样。比REJECT更安全)。REJECT:拒绝数据包,并返回一个错误信息(如port unreachable)。LOG:将匹配的数据包信息记录到系统日志(如/var/log/syslog或/var/log/messages),然后继续匹配后续规则。用于调试。--log-prefix "IPTABLES-DROPPED: "
SNAT:源地址转换(用于共享上网)。--to-source 1.2.3.4(nat表的POSTROUTING链)。
DNAT:目标地址转换(用于端口转发/内网穿透)。--to-destination 192.168.1.100:8080(nat表的PREROUTING链)。
MASQUERADE:动态SNAT,用于外网IP不固定的情况(如PPPoE拨号)。iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
第四部分:常见配置场景
场景1:配置一台安全的Web服务器
# 1. 清空所有现有规则(谨慎操作)
iptables -F
iptables -t nat -F
iptables -t mangle -F
# 2. 设置默认策略(默认拒绝所有)
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT # 通常允许所有出站
# 3. 允许回环接口的通信(localhost)
iptables -A INPUT -i lo -j ACCEPT
# 4. 允许已建立的连接和相关连接(关键!保证SSH不会断,也能正常响应请求)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 5. 允许SSH连接(假设使用默认22端口)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# 6. 允许HTTP和HTTPS连接
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# 7. 允许ICMP(ping命令)
iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT
# 8. 记录被拒绝的连接(可选,用于调试)
iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables_INPUT_denied: " --log-level 4
场景2:配置路由器/网关,实现共享上网(SNAT)
假设内网网卡为 eth1(网段 192.168.1.0/24),外网网卡为 eth0。
# 1. 开启Linux内核的IP转发功能
echo 1 > /proc/sys/net/ipv4/ip_forward
# 永久生效:编辑 /etc/sysctl.conf,设置 net.ipv4.ip_forward = 1
# 2. 在nat表的POSTROUTING链做SNAT
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE
# 如果用固定IP,可以写 -j SNAT --to-source 你的公网IP
# 3. 在FORWARD链中允许转发
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -s 192.168.1.0/24 -j ACCEPT
场景3:配置DNAT端口转发
将公网IP的8022端口转发到内网服务器 192.168.1.100的22端口(SSH)。
iptables -t nat -A PREROUTING -d 你的公网IP -p tcp --dport 8022 -j DNAT --to-destination 192.168.1.100:22
# 同时需要允许FORWARD链转发这个连接
iptables -A FORWARD -d 192.168.1.100 -p tcp --dport 22 -j ACCEPT
第五部分:高级功能与优化技巧
- 使用自定义链:将特定服务的规则(如Web规则)归类到一个自定义链中,使主链规则更清晰,便于管理。
- 防御暴力破解:使用
recent模块。# 限制SSH密码尝试频率(30秒内尝试超过3次的新连接,封禁5分钟) iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 30 --hitcount 3 --name SSH -j DROP - 连接数限制:防止单个IP发起过多连接(如DDOS)。
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 50 -j DROP - 优化规则顺序:
- 将最常用的规则(如
ESTABLISHED,RELATED)放在前面。 - 将匹配频率高的规则放在前面。
- 使用
-I插入而非-A追加来调整顺序。
- 将最常用的规则(如
- 规则持久化:
- Debian/Ubuntu:
apt-get install iptables-persistent # 保存当前规则 iptables-save > /etc/iptables/rules.v4 # 或使用 netfilter-persistent save - RHEL/CentOS:
service iptables save # 或 /sbin/service iptables save
- Debian/Ubuntu:
小结与建议
- 先规划后操作:在修改规则前,先想好最终的规则集,特别是默认策略,避免把自己锁在外面。可以写一个脚本,出错时一键恢复。
- 勤用日志:不确定规则是否生效时,用
LOG目标记录一下。 - 理解连接跟踪:
state模块是现代防火墙高效易用的关键。 - 从简入手:先实现基本功能,再逐步增加高级规则。
wireguard
WireGuard 是一种现代、高性能、轻量级的虚拟私有网络(VPN)协议,旨在提供比传统 VPN(如 IPsec、OpenVPN)更简单、更安全、更高效的解决方案。在了解上面的内容后,我们可以知道,WireGuard牌TCP/IP四层模型的第三层——传输层,且基于UDP协议运行,这对我们日后的使用和故障排除很重要。
核心特点
- 简洁性:WireGuard 的代码库极小(约 4000 行 C 代码),远小于 IPsec 或 OpenVPN(数万行),便于审计和维护。
- 高性能:基于 UDP 协议,采用现代加密算法,内核态实现,延迟低、吞吐高。
- 安全性:仅使用经过严格验证的现代加密原语,拒绝“加密套件协商”,避免配置错误导致的安全漏洞。
- 无连接状态管理:采用“沉默即断开”模型,无复杂的状态机,连接自动建立/恢复。
- NAT 穿透能力强:适用于移动设备和动态 IP 环境。
技术原理
网络模型:点对点隧道(Peer-to-Peer Tunnel)
WireGuard 在两个端点(称为 peers)之间建立加密的 IP 隧道。每个 peer 拥有一个:
- 私钥(private key)
- 公钥(public key)
- 监听端口(UDP port)
- 允许的 IP 地址范围(AllowedIPs)
通信基于 公钥认证,无需用户名/密码或证书体系。
局限性
- 无用户认证机制:WireGuard 本身只做设备认证(基于密钥),如需用户级认证,需结合外部系统(如 LDAP、OAuth)。
- 动态 IP 管理需额外工具:大规模部署时需配合管理平台(如 wg-easy、Tailscale、ZeroTier)。
- UDP 依赖:在严格 UDP 封锁的网络中可能无法使用(但可通过 UDP over TCP 等代理绕过)。
安装
我使用了github上的一个自动化安装和添加用户的sh脚本,我将它的文件上传到了我gitee上,但不建议使用他的安装,似乎有一些通用配置,不能在树莓派上生效,但是添加用户的维护功能还是好用的。
在linux系统下可以使用apt管理器,安装如下工具,搭建安全、易用的个人VPN网络
sudo apt install -y libqrencode4 qrencode resolvconf wireguard wireguard-tools
| 软件包 | 功能 |
|---|---|
libqrencode4 | 生成二维码的底层库 |
qrencode | 命令行生成二维码的工具 |
resolvconf | 管理系统DNS配置(/etc/resolv.conf) |
wireguard | WireGuard VPN 的内核模块 |
wireguard-tools | 配置和管理 WireGuard 隧道的命令行工具 |
wireguard服务端配置
编辑文件/etc/wireguard/wg0.conf
# WireGuard 服务端配置文件: wg0.conf
# 本文件定义了名为 wg0 的 WireGuard 接口(服务器端)的设置
[Interface]
# 【接口段】定义本机(服务器)的属性
# 本接口(wg0)拥有的 IP 地址。这里为 WireGuard 虚拟局域网分配了地址。
# 10.66.66.1/24 是 IPv4 网段,服务器在此网段的 IP 为 10.66.66.1
# fd42:42:42::1/64 是 IPv6 的 ULA(唯一本地地址)网段,服务器 IP 为 fd42:42:42::1
Address = 10.66.66.1/24, fd42:42:42::1/64
# WireGuard 服务端监听的端口号,客户端需要通过此端口连接
ListenPort = 58120
# 本接口的私钥(出于安全考虑,此处已用 ... 代替)
# 重要:私钥必须严格保密!与之对应的公钥会分发给客户端。
PrivateKey = ...
# 【启动后执行脚本】当 wg0 接口启动(Up)后自动执行的命令
# 这些 iptables 规则用于设置数据包转发(NAT),让客户端能通过服务器访问互联网
# PostUp 规则在 WireGuard 接口启动后执行
# 允许从 eth0(物理网卡)转发到 wg0(VPN 虚拟网卡)的流量
PostUp = iptables -I FORWARD -i eth0 -o wg0 -j ACCEPT
# 允许从 wg0(VPN 虚拟网卡)转发到 eth0(物理网卡)的流量
PostUp = iptables -I FORWARD -i wg0 -o eth0 -j ACCEPT
# 设置 IPv4 源地址转换(SNAT/Masquerade):
# 将所有来自 10.66.66.0/24 网段(VPN客户端)、且不是从 wg0 接口发出的流量进行伪装
# 这样,外部网络看到的源IP是服务器的eth0 IP,从而实现客户端上网
PostUp = iptables -t nat -A POSTROUTING -s 10.66.66.0/24 ! -o wg0 -j MASQUERADE
# 以下是针对 IPv6 的相应规则,原理同 IPv4
PostUp = ip6tables -I FORWARD -i wg0 -o eth0 -j ACCEPT
PostUp = ip6tables -I FORWARD -i eth0 -o wg0 -j ACCEPT
PostUp = ip6tables -t nat -A POSTROUTING -s fd42:42:42::/64 ! -o wg0 -j MASQUERADE
# 【关闭前执行脚本】当 wg0 接口关闭(Down)前自动执行的命令
# 用于清理启动时添加的 iptables 规则,保持系统整洁
# PostDown 规则在 WireGuard 接口关闭前执行,与 PostUp 一一对应,删除规则
PostDown = iptables -D FORWARD -i eth0 -o wg0 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -o eth0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -s 10.66.66.0/24 ! -o wg0 -j MASQUERADE
# 清理 IPv6 规则
PostDown = ip6tables -D FORWARD -i wg0 -o eth0 -j ACCEPT
PostDown = ip6tables -D FORWARD -i eth0 -o wg0 -j ACCEPT
PostDown = ip6tables -t nat -D POSTROUTING -s fd42:42:42::/64 ! -o wg0 -j MASQUERADE
### Client honor30
# 【对等体段】定义允许连接的客户端(Peer)信息
# 每个客户端都有一个独立的 [Peer] 段
[Peer]
# 该客户端的公钥。服务器用此公钥验证客户端的连接请求。
PublicKey = ...
# 预共享密钥(可选,但推荐使用)。在 PSK 模式下提供额外的对称加密,增强安全性。
PresharedKey = ...
# 允许该客户端使用的 IP 地址。
# 这里指定该客户端在 VPN 网络中的固定 IP 为 10.66.66.2 和 fd42:42:42::2
# /32 和 /128 表示单个主机地址,非网段
AllowedIPs = 10.66.66.2/32, fd42:42:42::2/128
# 注意:常见的服务端配置中,如果客户端IP不固定,可能会设置 AllowedIPs = 0.0.0.0/0 以允许任何IP
# 但这里是分配固定IP的更好实践。
生成客户端配置文件client.conf
[Interface]
PrivateKey = <客户端自己的私钥>
Address = 10.66.66.2/32,fd42:42:42::2/128
DNS = 223.5.5.5,119.29.29.29
# Uncomment the next line to set a custom MTU
# This might impact performance, so use it only if you know what you are doing
# See https://github.com/nitred/nr-wg-mtu-finder to find your optimal MTU
MTU = 1420
[Peer]
PublicKey = <服务端公钥>
PresharedKey = <服务端预共享的公钥>
Endpoint = [你的域名或IP]:58120
AllowedIPs = 0.0.0.0/0,::/0
生成客户端私钥和公钥
在树莓派上运行包含以下内容的sh脚本,可以生成一对新的密钥:
# 生成客户端私钥
CLIENT_PRIV_KEY=$(wg genkey)
echo "Client Private Key: $CLIENT_PRIV_KEY"
# 从私钥生成公钥
CLIENT_PUB_KEY=$(echo "$CLIENT_PRIV_KEY" | wg pubkey)
echo "Client Public Key: $CLIENT_PUB_KEY"
使用 qrencode 生成 QR 码
运行以下命令:
sudo qrencode -t ansiutf8 < /etc/wireguard/client.conf
qrencode:调用 QR 码生成工具。-t ansiutf8:指定输出类型为 ANSI UTF-8,这会在终端中直接以彩色方块的形式显示 QR 码。< /etc/wireguard/client.conf:将配置文件的内容作为输入传递给qrencode。
执行后,你会在终端中看到一个黑白方块组成的 QR 码。
(可选) 生成 PNG 图片
如果你想生成一个 PNG 图片以便保存或分享:
sudo qrencode -o client-wg.png -s 10 -m 2 < /etc/wireguard/client.conf
-o client-wg.png:指定输出文件名。-s 10:设置每个“点”的大小为 10 像素。-m 2:设置边距为 2 个点。
然后你可以通过 scp 或其他方式将 client-wg.png 文件从树莓派复制到你的电脑或手机。
基础操作
- 配置文件位置:
/etc/wireguard/wg0.conf - 启动服务:
sudo wg-quick up wg0 - 关闭服务:
sudo wg-quick down wg0 - 查看状态:
sudo wg(最重要) 和sudo systemctl status [email protected] - 重启服务:
sudo systemctl restart [email protected](推荐) - 开机自启:
sudo systemctl enable [email protected] - 调试日志:
sudo journalctl -u [email protected] -f
注意事项
- 性能:所有客户端流量都会经过服务端,服务端的带宽和 CPU 性能会成为瓶颈。
- 延迟:客户端访问互联网的延迟会增加,因为流量需要先到服务端再出去。
- 服务端公网 IP:服务端必须有一个公网 IP 地址,或者你的网络支持端口转发/UPnP。
- 安全:确保服务端的防火墙配置正确,只允许必要的连接。
- MTU:WireGuard 隧道会增加包头,可能导致 MTU 问题。如果遇到网页加载不全等问题,可以在客户端或服务端尝试设置较小的 MTU(如
MTU = 1420)。
故障排查
诊断步骤
我是在树莓派上进行的部署
- 在树莓派上运行
sudo wg:- 确认客户端已连接(
latest handshake时间很新)。 - 确认
transfer数据在收发。
- 确认客户端已连接(
- 在树莓派上检查 IP 转发:
sysctl net.ipv4.ip_forward如果是0,立刻修复。 - 在树莓派上检查 iptables:
sudo iptables -t nat -L POSTROUTING -v -n确认MASQUERADE规则存在,并且pkts在增加。 - 在手机上测试:
- 打开终端 App(如 Termux)或使用网络工具。
ping 10.66.66.1:应该成功。ping 8.8.8.8:如果失败,说明出站路由或 NAT 有问题。nslookup google.com或curl ifconfig.me:如果ping 8.8.8.8成功但这个失败,很可能是 DNS 问题。
- 检查客户端配置的
DNS:- 如果是
10.66.66.1,尝试改成8.8.8.8。
- 如果是
- 尝试添加 MTU: 在客户端配置中加入
MTU = 1420,重启客户端连接。
使用最简化的 PostUp 规则(仅开放端口)
我们先只开放 UDP 端口,排除 FORWARD 和 NAT 规则的干扰。
编辑 /etc/wireguard/test.conf,将 PostUp/PostDown 替换为:
ini编辑# --- 最简化的 PostUp ---
PostUp = sysctl -q net.ipv4.ip_forward=1
PostUp = sysctl -q net.ipv6.conf.all.forwarding=1
# 仅开放 WireGuard 端口
PostUp = iptables -A INPUT -p udp --dport 58120 -j ACCEPT
# --- 最简化的 PostDown ---
PostDown = iptables -D INPUT -p udp --dport 58120 -j ACCEPT
PostDown = sysctl -q net.ipv4.ip_forward=0
PostDown = sysctl -q net.ipv6.conf.all.forwarding=0
移除所有 FORWARD 和 NAT 规则,我们只关心“握手”能否成功。如果成功问题锁定到FORWARD 和 NAT 规则。
检查 sysctl 设置
cat /proc/sys/net/ipv4/ip_forward
cat /proc/sys/net/ipv6/conf/all/forwarding
必须都是 1。如果有0值,FORWARD存在问题,修改 /etc/wireguard/test.conf文件,内容如下:
# ...
# --- 修复后的 PostUp 规则 ---
# 允许转发:客户端 (wg0) -> 互联网 (eth0)
PostUp = iptables -A FORWARD -i wg0 -o eth0 -j ACCEPT
# 允许转发:互联网 (eth0) -> 客户端 (wg0) 响应
PostUp = iptables -A FORWARD -i eth0 -o wg0 -j ACCEPT
# ...
# --- 修复后的 PostDown 规则 (必须与 PostUp 一一对应) ---
PostDown = iptables -D FORWARD -i wg0 -o eth0 -j ACCEPT
PostDown = iptables -D FORWARD -i eth0 -o wg0 -j ACCEPT
# ...
之后验证规则是否生效:
# 检查 FORWARD 链
sudo iptables -L FORWARD -v -n
# 应该看到两条 ACCEPT 规则,方向正确
# 检查 NAT 链
sudo iptables -t nat -L POSTROUTING -v -n
# 应该看到 MASQUERADE 规则
#连接手机客户端,观察 pkts 计数是否开始增长
我踩的坑
Postup = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Postup = iptables -t nat -A POSTROUTING -s 10.66.66.0/24 ! -o wg0 -j MASQUERADE
#这两条命令都是在 WireGuard 接口关闭后(PostDown),从 iptables 的 nat 表中 删除(-D) 一条 NAT 规则。但它们匹配的规则不同。第二条具有代码的健壮性,更推荐。
#我之前使用第一条规则,死活查不出nat上为什么没有pkts的转发。不知是不是树莓派系统的内核问题。
#下面是包含ipv6、nat转发等内容的完整书写
# 启用转发和 NAT
PostUp = iptables -t nat -A POSTROUTING -s 10.66.66.0/24 ! -o wg0 -j MASQUERADE
PostUp = ip6tables -t nat -A POSTROUTING -s fd10:6666:66::/64 ! -o wg0 -j MASQUERADE
PostUp = sysctl -q net.ipv4.ip_forward=1
PostUp = sysctl -q net.ipv6.conf.all.forwarding=1
# 清理规则
PostDown = iptables -t nat -D POSTROUTING -s 10.66.66.0/24 ! -o wg0 -j MASQUERADE
PostDown = ip6tables -t nat -D POSTROUTING -s fd10:6666:66::/64 ! -o wg0 -j MASQUERADE