zl程序教程

您现在的位置是:首页 >  其他

当前栏目

Wireguard笔记(一) 节点安装配置和参数说明

2023-03-07 09:39:37 时间

目录

Wireguard笔记(一) 节点安装配置和参数说明
Wireguard笔记(二) 命令行操作
Wireguard笔记(三) lan-to-lan子网穿透和多网段并存

简介

虚拟子网软件,类似于OpenWPN,使用虚拟网卡,但是只支持UDP协议连接,配置简单。在Kernel 5.6之后已经内置。

中继服务器

作为中继服务器(Bounce Server),和普通的对等节点一样,它能够在 NAT 后面的客户端之间充当中继服务器,可以将收到的任何子网流量转发到正确的对等节点,这个过程并非由WireGuard处理,而是由系统内核和iptables处理的。公网可达的子网不需要中继服务器,只有当有节点位于 NAT 后面时才需要。

在WireGuard里客户端和服务端的功能是平等的,差别只是谁主动连接谁而已。如果双方都在监听端口,谁主动连接,谁就是客户端。主动连接的一方需要预知对方的公网地址和端口(Endpoint),被动连接的一方则不需要。如果双方都位于NAT后面,则需要加一个中继节点,双方都以中继服务器作为对等节点,它们的通信流量会先进入中继服务器,然后再转发给对方。

如果某一端同时连接了多个对端,当它想访问某个IP时,如果有具体的路由可用,则优先使用具体的路由,否则就会将流量转发到中继服务器,中继服务器再根据系统路由表进行转发。可以通过检查wg show wg0route找到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->RR->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/ 主要的设置有三处:

  1. 服务器和子网节点: 在sysctl中开启ip forward
  2. 服务器和子网节点: 在[Interface]中增加PostUp和PostDown的路由设置
  3. 服务器: 需要设置一下端口号,并在防火墙中打开此端口
  4. 服务器和子网节点如果安装了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