Wireguard笔记(一) 节点安装配置和参数说明
目录
Wireguard笔记(一) 节点安装配置和参数说明
Wireguard笔记(二) 命令行操作
Wireguard笔记(三) lan-to-lan子网穿透和多网段并存
简介
虚拟子网软件,类似于OpenWPN,使用虚拟网卡,但是只支持UDP协议连接,配置简单。在Kernel 5.6之后已经内置。
中继服务器
作为中继服务器(Bounce Server),和普通的对等节点一样,它能够在 NAT 后面的客户端之间充当中继服务器,可以将收到的任何子网流量转发到正确的对等节点,这个过程并非由WireGuard处理,而是由系统内核和iptables处理的。公网可达的子网不需要中继服务器,只有当有节点位于 NAT 后面时才需要。
在WireGuard里客户端和服务端的功能是平等的,差别只是谁主动连接谁而已。如果双方都在监听端口,谁主动连接,谁就是客户端。主动连接的一方需要预知对方的公网地址和端口(Endpoint),被动连接的一方则不需要。如果双方都位于NAT后面,则需要加一个中继节点,双方都以中继服务器作为对等节点,它们的通信流量会先进入中继服务器,然后再转发给对方。
如果某一端同时连接了多个对端,当它想访问某个IP时,如果有具体的路由可用,则优先使用具体的路由,否则就会将流量转发到中继服务器,中继服务器再根据系统路由表进行转发。可以通过检查wg show wg0
和route
找到WireGuard对一个给定地址的路由方式。
安装
服务器
参考
https://www.iplayio.cn/post/70750984
https://www.cnblogs.com/a5idc/p/13895146.html
https://yooooex.com/2019/05/23/wireguard-deploy/
ubuntu安装
sudo apt install wireguard
centos7安装
先升级Kernel到ml, 现在是5.11.x, 看看是否有wg模块
lsmod|grep wireguard
# 没有就modprobe一下再试试
modprobe wireguard
安装wg工具
yum install epel-release
yum provides wg-quick
yum install wireguard-tools
打开转发
sudo vi /etc/sysctl.conf
# 取消这行的注释
net.ipv4.ip_forward=1
# 保存文件并应用更改
sudo sysctl -p
# 输出:net.ipv4.ip_forward = 1
配置防火墙
Ubuntu: 如果启用了UFW,需要添加规则,本例使用的端口是50004
# 添加端口
sudo ufw allow 50004/udp
# 查看
sudo ufw status verbose
Centos7
firewall-cmd --zone=public --add-port=50004/udp --permanent
firewall-cmd --reload
配置
# 生成公私钥, 如果是对本机进行初始化, 先cd到/etc/wireguard目录下
umask 077
wg genkey | tee private.key | wg pubkey > public.key
# 创建新文件wg0.conf, 这个是服务wg-quick@wg0默认使用的配置文件. 添加以下内容:
sudo vi /etc/wireguard/wg0.conf
# ==================== begin ===================
[Interface]
PrivateKey = [填入服务端私钥]
Address = 10.253.0.1/24
ListenPort = 50004
# 规则说明:接受来源为%i的转发;接受出口为%i的转发;增加对出口为本机网卡的NAT映射
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens160 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens160 -j MASQUERADE
[Peer]
PublicKey = [填入客户端公钥]
# 允许客户端使用的IP段,对于peer的隧道IP, 建议使用/32的固定IP, 以避免和其他peer重复导致无法连接
AllowedIPs = 10.253.0.2/32
# ===================== end ====================
# 启动wg0
sudo wg-quick down wg0
# 停止wg0
sudo wg-quick up wg0
# 查看
sudo wg
# 查看单个
sudo wg show wg0
如果需要支持IPv6
# 启动动作, 要把 ens160 替换成自己的网口名称
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens160 -j MASQUERADE; ip6tables -A FORWARD -i %i -j ACCEPT; ip6tables -A FORWARD -o %i -j ACCEPT; ip6tables -t nat -A POSTROUTING -o ens160 -j MASQUERADE
# 关闭动作
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens160 -j MASQUERADE; ip6tables -D FORWARD -i %i -j ACCEPT; ip6tables -D FORWARD -o %i -j ACCEPT; ip6tables -t nat -D POSTROUTING -o ens160 -j MASQUERADE
设置为自启动
systemctl enable wg-quick@wg0
多个wireguard服务并存
可以在/etc/wireguard/下创建多个配置文件, 例如wg0.conf, wg1.conf配置多个服务
- 使用systemctl enable/start wg-quick@wg0, systemctl enable/start wg-quick@wg1 启动
- 使用wg show能同时看到这些wiguard服务的连接情况
- 各配置使用不同的隧道网段, 会体现到route上
- 各配置当中, peer中的allowedIP会影响route规则, 如果相同会产生冲突
对于非服务端, 配置文件的例子为
[root@vm_ci01 ~]# more /etc/wireguard/wg0.conf
[Interface]
PrivateKey = [填入私钥]
Address = 10.253.0.3/32
ListenPort = 50004
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i %i -j ACCEPT; ip6tables -A FORWARD -o %i -j ACCEPT; ip6tables -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; ip6tables -D FORWARD -i %i -j ACCEPT; ip6tables -D FORWARD -o %i -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey = [填入服务端的公钥]
AllowedIPs = 10.253.0.0/24,192.168.116.0/24
Endpoint = 1.123.45.67:50004(服务端的IP端口)
PersistentKeepalive = 25
客户端(命令行)
先生成公私钥,然后使用配置文件
[Interface]
PrivateKey = [客户端私钥]
Address = 10.253.0.2/24
DNS = 114.114.114.114
[Peer]
PublicKey = [服务端公钥]
# 允许通过的IP段,如果设为0.0.0.0/0则拦截本机所有流量
AllowedIPs = 192.168.116.0/24,10.253.0.0/24
Endpoint = [服务器的IP]:50004
PersistentKeepalive = 25
注意
- 如果这个客户端是作为逆向穿透的节点
- [Interface]中增加PostUp, PostDown, 但是不需要DNS;
- [Interface]中Address掩码可以使用/24也可以使用/32
- [Peer]中增加PersistentKeepalive
- 如果这是Windows Wireguard客户端
- [Interface]中不需要PostUp, PostDown, 可以不需要DNS;
- [Interface]中Address掩码使用/24, 否则会出现连接不上服务端的情况(本地显示已连接, 但是服务端看不到, 并且接收字节为0)
- [Peer]中只需要PublicKey, AllowedIPs, Endpoint
Ubuntu20.04客户端(通过NetworkManager)
NetworkManager界面对Wireguard的支持, 要到版本1.26之后, 如果是Ubuntu20.04, 需要自己编译.
sudo apt install wireguard git dh-autoreconf libglib2.0-dev intltool build-essential libgtk-3-dev libnma-dev libsecret-1-dev network-manager-dev resolvconf
从Github clone对应的项目
git clone https://github.com/max-moser/network-manager-wireguard
cd network-manager-wireguard
./autogen.sh --without-libnm-glib
./configure --without-libnm-glib --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib/x86_64-linux-gnu --libexecdir=/usr/lib/NetworkManager --localstatedir=/var
make
sudo make install
然后在网络配置界面的WPN中点击+号, 就能看到Wireguard的选项了. 配置说明
- Identity
- Name: 可以使用wg0之类的名称, 这个会被用于网口名称, 所以不要太长太复杂
- Interface:
- Address(IPv4): 10.253.0.4/32 这个是开启wg之后本机的隧道IP
- Address(IPv6): 可以留空
- Listen Port: 可以留空, 也可以指定为50004
- Private Key: 本机的私钥
- 其他都可以留空
- Peer
- Public Key: 服务端的公钥
- Allow IPs: 需要走隧道的IP段, 一般包含隧道自身IP段, 以及要借道隧道的IP段, 但是这里设置并不会产生对应的route
- Endpoint: 服务端的IP和端口
- Persis.Keepalive: 25 保持活动的时间间隔
- 其他都可以留空
- IPv4
- IPv4 method: Automatic (DHCP) 实际产生的IP还是之前在Identity->Interface中配置的IP地址
- DNS: Automatic
- Routes: 取消Automatic, 添加
- 10.253.0.0, 255.255.255.0, 10.253.0.102, 5 将10.253.0.0/24这个段的路由, 设置到10.253.0.102(即本机的隧道网口)上
- 192.168.13.0, 255.255.255.0, 10.253.0.102, 5 将192.168.13.0/24这个段的路由也设置到本机隧道网口上
- 如果还有其他需要走隧道的IP段, 则继续添加.
- 不勾选Use this connection only for resources on its network
注意: 如果不手动添加路由, 在启动此wg网口后, 本机路由没有变化, 访问不生效, 但是通过ping 10.253.0.1 -I wg0可以ping通服务端隧道IP, 说明仅是路由的问题.
配置说明
关于AllowedIPs
Wireguard的AllowedIPs因为涉及服务端和客户端的允许IP范围,需要理清一下这个设置的含义
- 首先,AllowedIPs会影响当前机器的路由设置,在AllowedIPs配置的每一段IP,都会在路由表里指向这个wireguard网卡
那么在A节点,如果你要访问B节点后面的网络,你就要把B节点后面网络的IP段,配到Peer.B下面去 - 其次,提供转发的节点,不需要关心从各个节点到来的流量要访问何处,不需要为自身转发的目标网段配置AllowedIPs
比如A节点处于5.5.5.0/24网段,A已经提供了转发,那么A不需要在自己节点下面的Peer的AllowedIPs中配置5.5.5.0/24
服务端和客户端的[Peer]中配置的AllowedIPs
- 无论哪一端,AllowedIPs的IP段都会加入路由表
- AllowedIPs需要包含对方节点的隧道IP
- AllowedIPs需要包含对方节点提供转发的IP网段,这将通过增加路由规则拦截本机对这些IP范围的访问流量
- 当配置的AllowedIPs为0.0.0.0/0时,会将虚拟网卡的Default Gateway设为0.0.0.0,而不是通过路由表
公网中继的AllowedIPs配置问题
使用公网中继节点进行穿透时(例如R为公网中继, A为工作区内网节点, B为个人接入),
如果AllowedIPs配置不正确, 会导致B->R
, R->A
都能访问, 但是B->A
就无法访问的问题. 需要检查A节点的配置, 检查其中R这个节点的[Peer]配置中AllowedIPs是否未包含B节点的隧道IP.
举例:
R节点 有公网IP, 提供前往192.168.116.x和192.168.117.x的中转
[Interface]
Address = 10.253.0.1/32
...
[Peer]
AllowedIPs = 10.253.0.3/32,192.168.117.0/24
A节点 处于192.168.117.0/24的内网
[Interface]
Address = 10.253.0.3/32
[Peer]
AllowedIPs = 10.253.0.1/32,192.168.116.0/24
Endpoint = xx.xx.xx.xx:10004
B节点 个人外网接入, 需要访问192.168.117.0/24网段
[Interface]
Address = 10.253.0.101/24
[Peer]
AllowedIPs = 192.168.116.0/24, 10.253.0.0/24, 192.168.117.0/24
Endpoint = xx.xx.xx.xx:10004
这时候就会出现前面提到的情况, B->R
和R->A
访问都通但是B->A
访问不通, 需要将A配置中R的AllowedIPs改为10.253.0.1/24才行, 如下所示.
[Interface]
Address = 10.253.0.3/32
[Peer]
AllowedIPs = 10.253.0.1/24,192.168.116.0/24
Endpoint = xx.xx.xx.xx:10004
或者更进一步, 仅仅将B节点和R节点的IP放入, 如下所示, 这样就只允许B->R->A
, 其他节点连接到R之后, 无法访问A
[Interface]
Address = 10.253.0.3/32
[Peer]
AllowedIPs = 10.253.0.1/32,10.253.0.101/32,192.168.116.0/24
Endpoint = xx.xx.xx.xx:10004
关于PresharedKey
即PSK 预共享密钥,节点可以给连接自己的每一个peer都分配一个PSK,这个PSK会设置在每对节点的[Peer]中,连接时检查是否一致
# 生成(每个peer一个)
wg genpsk > presharedkey
# 配置格式
[Peer]
PublicKey = P556VVMhhBb+kc2Gm7JV46jh1oRv75YscK8q131iSnM=
PresharedKey = oZ33KPYBwo7aFyxewm5Eutlelztz9lXQ2Z8tyouc7TM=
AllowedIPs = 10.253.0.0/24
Endpoint = 123.123.123.123:31231
...
关于PersistentKeepAlive
这个参数用于内网节点定期发送报文以保持连接。默认情况下WG尽量保持沉默以避免发送太多数据,但是如果连接中一些节点处于内网或防火墙后,在长时间无数据后连接可能被防火墙关闭,此时如果外网节点需要发送数据,会发现连接不可用。这种情况下就需要内网节点定期主动发送数据以保持连接。
注意:这个参数与最后握手时间
是不一样的。一次握手会建立一个约三分钟长度的会话时间,在这个会话时间内,发送keep-alive报文不需要再次建立会话。在实际使用中,如果发送报文时会话时间已经剩余不到1分钟,会在此会话到期前就创建一个新的会话。正常情况下,如果PersistentKeepAlive设为了25,握手时间基本上不会超过3分钟,除非处于移动设备上,因为设备节电等原因导致发送时间滞后等情况。
关于DNS
客户端如果配置为全流量拦截(0.0.0.0/0),则必须设置DNS项,如果不配置DNS,在连接后会不能正确解析域名
关于子网间穿透
Wireguard可以配置通过一个公共服务器同时连接多个子网。这时候需要在服务器和每个子网节点上,都配置同一个网段的隧道IP和相应的路由,可以参考
https://anyisalin.github.io/2018/11/21/fast-flexible-nat-to-nat-vpn-wireguard/ 主要的设置有三处:
- 服务器和子网节点: 在sysctl中开启ip forward
- 服务器和子网节点: 在[Interface]中增加PostUp和PostDown的路由设置
- 服务器: 需要设置一下端口号,并在防火墙中打开此端口
- 服务器和子网节点如果安装了firewalld, 还需要在firewalld中开启masquerade
firewall-cmd --permanent --zone=public --add-masquerade
firewall-cmd --reload
Windows节点
windows做这个穿透会比较复杂,因为windows不像linux那样有iptables可以配置,需要设置的可以参考这篇 https://www.henrychang.ca/how-to-setup-wireguard-vpn-server-on-windows/
使用TCP来避免防火墙的UDP规则影响
可以使用udptunnel
https://gist.github.com/insdavm/90cbeffe76ba4a51251d83af604adf94
或者udp2raw-tunnel
https://github.com/wangyu-/udp2raw-tunnel
以及TunSafe
https://github.com/TunSafe/TunSafe
后两者有支持windows和android的客户端
实现思路是在服务端运行一个TCP隧道, 代理wg的端口, 在客户端运行TCP隧道的客户端, 连接到服务端的TCP隧道, 客户端的wg连接本地端口
iptables规则
单包验证SPA规则
# 清空iptables
iptables -F
# 已经建立的tcp连接允许通过 -m state --state ESTABLISHED 只针对tcp
iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT
# 允许访问udp 62201端口
iptables -A INPUT -p udp --dport 62201 -j ACCEPT
# 允许22端口通过
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# 允许入包回环
iptables -A INPUT -i lo -j ACCEPT
# 出包的tcp
iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT
# 出包的udp
iptables -A OUTPUT -p udp -j ACCEPT
# 允许出包回环
iptables -A OUTPUT -o lo -j ACCEPT
# 允许建立的FORWARD通过
iptables -A FORWARD -m state --state ESTABLISHED -j ACCEPT
# 最后一步 关闭IMPUT,OUTPUT,FORWARD
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
其他
提供内核支持的发行版
在Ubuntu20.04最近的更新中, Kernel已经升级到5.8.0, 自带了wireguard
~$ uname -a
Linux milton-t550 5.8.0-43-generic #49~20.04.1-Ubuntu SMP Fri Feb 5 09:57:56 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
~$ sudo modprobe wireguard
[sudo] password for milton:
~$ lsmod
Module Size Used by
wireguard 86016 0
curve25519_x86_64 49152 1 wireguard
libchacha20poly1305 16384 1 wireguard
chacha_x86_64 28672 1 libchacha20poly1305
poly1305_x86_64 28672 1 libchacha20poly1305
libblake2s 16384 1 wireguard
blake2s_x86_64 20480 1 libblake2s
ip6_udp_tunnel 16384 1 wireguard
udp_tunnel 16384 1 wireguard
对于Centos7, 可以升级内核至5.11.x: Centos7 和 Centos8 升级内核
Debug日志
启用WireGuard debug
echo 'module wireguard +p' | sudo tee /sys/kernel/debug/dynamic_debug/control
Disable WireGuard debug
echo 'module wireguard -p' | sudo tee /sys/kernel/debug/dynamic_debug/control
查看输出
dmesg
# or
journalctl -f
性能测试
https://www.reddit.com/r/linux/comments/9bnowo/wireguard_benchmark_between_two_servers_with_10/
对Wireguard性能的测试, 比较的对象是直接传输和OpenVPN. 用netperf在MTU8500~9000的情况下, 三者的速度对比是44:23:1
netperf -t TCP_STREAM -l 600 -H 10.0.9.11