快速入门
您首先要确保对 概念概述 有很好的掌握,然后 安装 WireGuard。之后,请继续阅读此处。
配置实战
单个配置如下所示:
wg(8) 演练
命令行界面
可以通过 添加新接口,该接口应自动处理模块加载:ip-link(8)
# ip link add dev wg0 type wireguard BASH |
IP 地址和 peer 可以通过 ifconfig(8)
或ip-address(8)
分配
# ip address add dev wg0 192.168.2.1/24 BASH |
或者,如果总共只有两个 peer ,则可以:
# ip address add dev wg0 192.168.2.1 peer 192.168.2.2 BASH |
该接口可以使用随附的 wg(8)
实用程序配置密钥和对等(peer)端点(endpoint):
# wg setconf wg0 myconfig.conf BASH |
或
# wg set wg0 listen-port 51820 private-key /path/to/private-key peer ABCDEF... allowed-ips 192.168.88.0/24 endpoint 209.202.254.14:8172 BASH |
最后,可以使用 ifconfig(8)
或 ip-link(8)
激活接口:
# ip link set up dev wg0 BASH |
还有 wg show
和 wg showconf
命令,用于查看当前配置。不带参数的 wg
调用 wg show
默认为对所有 WireGuard 接口进行调用。
wg(8) 工具
wg(8)
和 ip(8)
的许多例行的启动和拆卸动作都可以通过随附的 wg-quick(8)
工具 实现自动化:
wg- 快速(8)工具
密钥生成
WireGuard 需要 base64 编码的公钥和私钥。这些可以使用 wg(8)
实用程序生成:
umask 077 wg genkey > privatekey BASH |
这将在 stdout 上创建包含新私钥 privatekey
的内容。
然后,您可以从私钥派生公钥:
wg pubkey < privatekey > publickey BASH |
这将从 stdin 读取 privatekey
并将相应的公钥 publickey
写入 stdout。
当然,您可以一次完成所有操作:
wg genkey | tee privatekey | wg pubkey > publickey BASH |
NAT 和防火墙遍历持久性
默认情况下,WireGuard 在不使用时会尝试尽可能保持静默;这不是一个健谈的协议。在大多数情况下,它仅在对等方希望发送数据包时传输数据。当系统未要求它发送数据包时,它会停止发送数据包,直到再次被请求。在大多数配置中,这运行良好。但是,当对等方位于 NAT 或防火墙后面时,它可能希望能够接收传入的数据包,即使它不发送任何数据包。由于 NAT 和有状态防火墙会跟踪 " 连接 ",因此,如果 NAT 或防火墙后面的对等方希望接收传入的数据包,他必须通过定期发送保持活动数据包来保持 NAT/ 防火墙映射有效。这称为 持久保持活动( persistent keepalives)。启用此选项后 *,每隔几秒钟 * 就会向服务器终结点(endpoint)发送一次保持活动状态的数据包。适用于各种防火墙的合理间隔为 25 秒。将其设置为 0 会关闭该功能,这是默认设置,因为大多数用户不需要此功能,并且会使 WireGuard 稍微更健谈。可以通过将字段 PersistentKeepalive =
添加到配置文件中的对等项或在命令行中进行设置 persistent-keepalive
来指定此功能。如果不需要此功能,请不要启用它。但是,如果您位于 NAT 或防火墙后面,并且希望在网络流量静默很久之后接收传入连接,则此选项将使 " 连接 " 在 NAT 眼中保持打开状态。
配置详解
WireGuard 使用 INI 语法作为其配置文件格式。配置文件可以放在任何路径下,但必须通过绝对路径引用。默认路径是 /etc/wireguard/wg0.conf
。
配置文件的命名形式必须为 ${WireGuard 接口的名称 }.conf
。通常情况下 WireGuard 接口名称以 wg
为前缀,并从 0
开始编号,但你也可以使用其他名称,只要符合正则表达式 ^[a-zA-Z0-9_=+.-]{1,15}$
就行。
你可以选择使用 wg
命令来手动配置 VPN,但一般建议使用 wg-quick
,它提供了更强大和用户友好的配置体验,可以通过配置文件来管理配置。
下面是一个配置文件示例:
[Interface] # Name = peer1.private Address = 10.4.1.3/32 ListenPort = 51820 PrivateKey = thisPeerPrivateKeyXXXXXXXX= DNS = 223.5.5.5 MTU = 1500 PreUp = echo WireGuard PreUp PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PreDown = echo WireGuard PreDown PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE [Peer] # Name = peer2.private AllowedIPs = 10.4.1.1/24 Endpoint = peer1.private:51820 PublicKey = remotePeerPublicKeyXXXX= PersistentKeepalive = 25 INI |
✔️ 实用配置 :
PostUp 和 PostDown 可以按照上文进行配置:
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
当然,目前的体验最好的实践是傻瓜式地通过 Netmaker 完成所有配置。
[Interface]
这一节定义本地 VPN 配置。例如:
- 如果本地节点是客户端,只需路由自身的流量,那就只暴露一个 IP(作为客户端嘛,就不需指定端口)。
[Interface] # Name = phone.private Address = 10.4.1.5/32 PrivateKey = <private key for phone.private> INI |
- 如果本地节点是中继服务器,它需要将流量转发到其他对等节点(peer),并公开整个 VPN 子网的路由。
[Interface] # Name = public-server1.example-vpn.tld Address = 10.4.1.1/24 ListenPort = 51820 PrivateKey = <private key for public-server1.example-vpn.tld> DNS = 223.5.5.5 INI |
Address
定义本地节点应该对哪个地址范围进行路由。
- 如果是常规的客户端,则将其设置为节点本身的单个 IP(使用 CIDR 指定,例如 10.4.1.3/32);
- 如果是中继服务器,则将其设置为可路由的子网范围。
例如:
- 常规客户端,只路由自身的流量:
Address = 10.4.1.3/32
- 中继服务器,可以将流量转发到其他对等节点(peer):
Address = 10.4.1.1/24
(注意是/24
, 即整个子网) - 也可以指定多个子网或 IPv6 子网:
Address = 10.4.1.1/24,2001:DB8::/64
ListenPort
当本地节点是中继服务器时,需要通过该参数指定端口来监听传入 VPN 连接,默认端口号是 51820
。常规客户端(只作为客户端,不作为服务器端)则不需要此选项。
PrivateKey
本地节点的私钥,所有节点(包括中继服务器)都必须设置。不可与其他服务器共用。
DNS
通过 DHCP 向客户端宣告 DNS 服务器。客户端将会使用这里指定的 DNS 服务器来处理 VPN 子网中的 DNS 请求,但也可以在系统中覆盖此选项。例如:
- 如果不配置则使用系统默认 DNS
- 可以指定单个 DNS:
DNS = 223.5.5.5
- 也可以指定多个 DNS:
DNS = 223.5.5.5,223.6.6.6
MTU
定义连接到对等节点(peer)的 MTU
(Maximum Transmission Unit,最大传输单元),默认不需要设置,一般由系统自动确定。
PreUp
启动 VPN 接口之前运行的命令。这个选项可以指定多次,按顺序执行。
例如:
- 添加路由:
PreUp = ip rule add ipproto tcp dport 22 table 1234
PostUp
启动 VPN 接口之后运行的命令。这个选项可以指定多次,按顺序执行。
例如:
- 从文件或某个命令的输出中读取配置值:
PostUp = wg set %i private-key /etc/wireguard/wg0.key <(some command here) INI |
- 添加一行日志到文件中:
PostUp = echo "$(date +%s) WireGuard Started" >> /var/log/wireguard.log INI |
- 调用 WebHook:
PostUp = curl https://events.example.dev/wireguard/started/?key=abcdefg INI |
- 添加路由:
PostUp = ip rule add ipproto tcp dport 22 table 1234 INI |
- 添加 iptables 规则,启用数据包转发:
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE INI |
- 强制 WireGuard 重新解析对端域名的 IP 地址:
PostUp = resolvectl domain %i "~."; resolvectl dns %i 10.4.1.1; resolvectl dnssec %i yes INI |
PreDown
停止 VPN 接口之前运行的命令。这个选项可以指定多次,按顺序执行。
例如:
- 添加一行日志到文件中:
PreDown = echo "$(date +%s) WireGuard Going Down" >> /var/log/wireguard.log INI |
- 调用 WebHook:
PreDown = curl https://events.example.dev/wireguard/stopping/?key=abcdefg INI |
PostDown
停止 VPN 接口之后运行的命令。这个选项可以指定多次,按顺序执行。
例如:
- 添加一行日志到文件中:
PostDown = echo "$(date +%s) WireGuard Going Down" >> /var/log/wireguard.log INI |
- 调用 WebHook:
PostDown = curl https://events.example.dev/wireguard/stopping/?key=abcdefg INI |
- 删除 iptables 规则,关闭数据包转发:
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE INI |
[Peer]
定义能够为一个或多个地址路由流量的对等节点(peer)的 VPN 设置。对等节点(peer)可以是将流量转发到其他对等节点(peer)的中继服务器,也可以是通过公网或内网直连的客户端。
中继服务器必须将所有的客户端定义为对等节点(peer),除了中继服务器之外,其他客户端都不能将位于 NAT 后面的节点定义为对等节点(peer),因为路由不可达。对于那些只为自己路由流量的客户端,只需将中继服务器作为对等节点(peer),以及其他需要直接访问的节点。
举个例子,在下面的配置中,public-server1
作为中继服务器,其他的客户端有的是直连,有的位于 NAT 后面:
public-server1
(中继服务器)[peer]
:public-server2
,home-server
,laptop
,phone
public-server2
(直连客户端)[peer]
:public-server1
home-server
(客户端位于 NAT 后面)[peer]
:public-server1
,public-server2
laptop
(客户端位于 NAT 后面)[peer]
:public-server1
,public-server2
phone
(客户端位于 NAT 后面)[peer]
:public-server1
,public-server2
配置示例:
- 对等节点(peer)是路由可达的客户端,只为自己路由流量
[Peer] # Name = public-server2.private Endpoint = public-server2.private:51820 PublicKey = <public key for public-server2.private> AllowedIPs = 10.4.1.2/32 INI |
- 对等节点(peer)是位于 NAT 后面的客户端,只为自己路由流量
[Peer] # Name = home-server.private Endpoint = home-server.private:51820 PublicKey = <public key for home-server.private> AllowedIPs = 10.4.1.3/32 INI |
- 对等节点(peer)是中继服务器,用来将流量转发到其他对等节点(peer)
[Peer] # Name = public-server1.example-vpn.tld Endpoint = public-server1.example-vpn.tld:51820 PublicKey = <public key for public-server1.example-vpn.tld> # 路由整个 VPN 子网的流量 AllowedIPs = 10.4.1.1/24 PersistentKeepalive = 25 INI |
Endpoint
指定远端对等节点(peer)的公网地址。如果对等节点(peer)位于 NAT 后面或者没有稳定的公网访问地址,就忽略这个字段。通常只需要指定 中继服务器 的 Endpoint
,当然有稳定公网 IP 的节点也可以指定。例如:
- 通过 IP 指定:
Endpoint = 123.123.123.123:51820 INI |
- 通过域名指定:
Endpoint = public-server1.private:51820 INI |
AllowedIPs
允许该对等节点(peer)发送过来的 VPN 流量中的源地址范围。同时这个字段也会作为本机路由表中 wg0 绑定的 IP 地址范围。如果对等节点(peer)是常规的客户端,则将其设置为节点本身的单个 IP;如果对等节点(peer)是中继服务器,则将其设置为可路由的子网范围。可以使用 ,
来指定多个 IP 或子网范围。该字段也可以指定多次。
当决定如何对一个数据包进行路由时,系统首先会选择最具体的路由,如果不匹配再选择更宽泛的路由。例如,对于一个发往 10.4.1.3
的数据包,系统首先会寻找地址为 10.4.1.3/32
的对等节点(peer),如果没有再寻找地址为 10.4.1.1/24
的对等节点(peer),以此类推。
例如:
- 对等节点(peer)是常规客户端,只路由自身的流量:
AllowedIPs = 10.4.1.3/32 INI |
- 对等节点(peer)是中继服务器,可以将流量转发到其他对等节点(peer):
AllowedIPs = 10.4.1.1/24 INI |
- 对等节点(peer)是中继服务器,可以转发所有的流量,包括外网流量和 VPN 流量:
AllowedIPs = 0.0.0.0/0,::/0 INI |
- 对等节点(peer)是中继服务器,可以路由其自身和其他对等节点(peer)的流量:
AllowedIPs = 10.4.1.3/32,10.4.1.4/32 INI |
- 对等节点(peer)是中继服务器,可以路由其自身的流量和它所在的内网的流量:
AllowedIPs = 10.4.1.3/32,192.168.1.1/24 INI |
PublicKey
对等节点(peer)的公钥,所有节点(包括中继服务器)都必须设置。可与其他对等节点(peer)共用同一个公钥。
公钥可通过命令 wg pubkey < example.key > example.key.pub
来生成,其中 example.key
是上面生成的私钥。
例如:PublicKey = somePublicKeyAbcdAbcdAbcdAbcd=
PersistentKeepalive
如果连接是从一个位于 NAT 后面的对等节点(peer)到一个公网可达的对等节点(peer),那么 NAT 后面的对等节点(peer)必须定期发送一个出站 ping 包来检查连通性,如果 IP 有变化,就会自动更新Endpoint
。
例如:
- 本地节点与对等节点(peer)可直连:该字段不需要指定,因为不需要连接检查。
- 对等节点(peer)位于 NAT 后面:该字段不需要指定,因为维持连接是客户端(连接的发起方)的责任。
- 本地节点位于 NAT 后面,对等节点(peer)公网可达:需要指定该字段
PersistentKeepalive = 25
,表示每隔25
秒发送一次 ping 来检查连接。