一切都应该从我办了联通宽带以及整了个小型家庭服务器说起,有了公网IP之后就老想着搞点事情,能方便在外面的时候也能随时随地连回家里访问我在内网配置的各种服务。在对比了各种服务之后,我最终选择了使用WireGuard作为连回家里的方案,但是我发现,我最常用的Debian系统在国内还是没有很好的配置资料可以参考,导致在配置的过程中走了不少弯路,所以我这里准备将我的配置过程记录一下。

现有条件及目的

首先说下我在配置之前所处的环境:

  • 光猫拨号,没有专门配置路由器
  • 运营商分配了公网IP,80和443没试,但是高位端口测试能连通
  • 已经获取到了光猫的超管权限,可以做DMZ及端口映射
  • 家庭服务器已经装好了PVE环境,为了节省资源,我打算将网络相关的服务都部署到我PVE里面创建的一台Debian虚拟机上

我的目的也比较明确:

  • 有公网IP,不做内网穿透
  • 端口直连,尽量不直接将SSH等敏感服务暴露到公网
  • 回家服务尽量配置简单,尽量不给前期配置以及后期维护增加难度
  • 尽量通过一项服务就能完全访问家里内网的所有资源
  • 随时随地可以访问,回家服务需要支持各种网络各种操作系统,不管是公司还是出门在外,不管是macOS还是Windows或者iOS系统

所以对比了各种老牌的vxn以及各种新晋的内网穿透工具之后,我最终决定选择WireGuard作为我的回家工具。

WireGuard安装之前

我个人喜欢Debian系统,因为Debian对比其他常见的发行版,简单轻量,官方源自带的包足够多,且节省内存。

目前Debian最新的稳定版是Debian 11,官方源已经自带了WireGuard相关包,且因为Linux Kernel使用的是5.10,所以如果和我一样使用的Debian11系统,不需要修改repo相关就能直接安装WireGuard,如果是别的版本比如说Debian10或者Ubuntu 20.04以下的可能需要添加额外的源仓库等。

安装之前需要为WireGuard准备一个没有被其他服务占用的端口,我并没有在官方文档查到WireGuard指定使用哪个端口,但是官方的Quick Start文档使用的是51820,我没有试过其他端口是否可行,我个人也是使用这个端口的。

WireGuard官方文档明确说明了,WireGuard使用的是UDP,至少目前不支持TCP,如果涉及到安全组或者端口映射,需要注意放行对应端口的UDP而不是TCP,只放行TCP会导致无法连接到服务器。

Debian安装配置WireGuard服务端

安装过程我使用的是root账户,如果目前登录的不是root账户,建议切换到root以方便后面生成秘钥以及修改配置文件。

虽说WireGuard没有服务器/客户端的概念,配置得当每个节点都可以是互联节点,但是对于我这种初学者来说,为了方便理解,我还是使用C/S来表述以方便理解。

我将我在家穿透端口出来的哪台有公网IP运行Debian11的虚拟机称为服务器,而没有公网IP的公司的电脑以及手上的iOS设备称为客户端。对于我来说,我是使用手上的设备通过WireGuard客户端连回家里的WireGuard服务器。

安装命令:

apt update
apt install wireguard iptables

生成密钥以及新建配置文件:

# 进入WireGuard的配置目录
cd /etc/wireguard/
# 生成节点公钥以及私钥
wg genkey | tee privatekey | wg pubkey > publickey

生成之后,可以使用cat命令查看生成的秘钥内容,比如说我这里生成的:

root@ZocoXX:/etc/wireguard# cat privatekey 
2AhYjL82utlPE3XiXq0n22w1890WgR4vgSsYdwZSg1k= #服务端私钥,注意保密,不能泄露
root@ZocoXX:/etc/wireguard# 
root@ZocoXX:/etc/wireguard# cat publickey 
8zXAgoCyqxAjX9wOBGQnBu80pDyBNplZmulUGhhtnik= #服务端公钥,可以分发,后续客户端可能会用到

然后选择选择一个在各个客户端内网都没有使用的内网IP段,用来WireGuard组网,避开各个客户端使用的内网IP段是为了避免后续如果有流量转发需求的情况出现问题,我这里选择的IP段是10.10.10.0/24,服务端IP设置成为10.10.10.1,选择的端口是51820,在WireGuard默认配置文件目录新建一个文件,名称可以随便取,我这里按照惯例取名wg0.conf,服务端配置如下:

vim wg0.conf

[Interface]
Address = 10.10.10.1/24
SaveConfig = false
ListenPort = 51820
PrivateKey = 2AhYjL82utlPE3XiXq0n22w1890WgR4vgSsYdwZSg1k=
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o ens18 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -A FORWARD -o wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o ens18 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o ens18 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o ens18 -j MASQUERADE

Address以及ListenPort可以修改成想要的,但是注意要跟后续客户端配置对应。PrivateKey是上述通过命令生成的,复制即可。

最后的PostUp以及PostDown两行,分别是启动及停止时执行的两条iptables命令,也就是一开始安装WireGuard的时候为什么要一并安装iptables,当然,如果不需要服务端转发流量,也可以不用这两行。

上述PostUp以及PostDown两行里面的eth0需要替换成服务端实际在用的网卡,名字可以使用ip a查看到,如果是用PVE默认步骤安装的Debian,名字应该是en18s0。

需要注意的是,如果是新手,SaveConfig参数建议设置成false,避免后续调试的时候修改了配置文件停止WireGuard之后又被覆盖。

服务端开启IPv4流量转发

因为我是打算使用服务端转发所有流量,所以服务器端需要开启流量转发,如果没有这种需求可以不开:

echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf
sysctl -p

WireGuard客户端配置

每个系统都有对应的WireGuard App,我这里同样使用命令行的Debian11来作为第一个客户端作为演示,只要在命令行调试成功了,后续图形化界面的软件使用也能很快上手。

安装以及生成密钥及配置文件步骤都和上述服务端类似,我这里就简单说下步骤,注意,和上述操作不同的是,下面这部分操作是在客户端进行的:

apt update
apt install wireguard iptables
cd /etc/wireguard/
wg genkey | tee privatekey | wg pubkey > publickey

和服务端不同的是,wg0.conf整体内容如下:

[Interface]
PrivateKey = IJlFI0f+j3UqXf0NWhpZHJjS7AQ7TRBozUh0o1iSDEg=
Address = 10.10.10.2/24
DNS = 114.114.114.114 #指定DNS

[Peer]
PublicKey = 8zXAgoCyqxAjX9wOBGQnBu80pDyBNplZmulUGhhtnik=
AllowedIPs = 0.0.0.0/0 #转发的网段,我是需要转发所有的流量,所以指定了0.0.0.0/0,如果只是指定网段,直接输入指定网段即可,例如192.168.1.1/24,10.0.0.1/8
Endpoint = wg.zocoxx.com:51820
PersistentKeepalive = 20

配置文件中的两个PrivateKey、PublicKey尤其要注意,Interface里面的PrivateKey是客户端生成的,Peer里面的PublicKey是服务端生成的,一定要注意不要复制出错。

而Address及AllowedIPs这两个网段需要一致。其中,Address是分配给客户端的每个客户端不能重复,上述在服务端设置成了10.10.10.1,这里我设置成了10.10.10.2,注意后面的子网掩码,不能设置成24,需要是32。

Endpoint是WireGuard服务端对应的域名/IP及对外公网开放的端口,这个值需要在外网能访问通,否则肯定是连不上服务端的。

PersistentKeepalive是发送心跳包,这个值可以随便设置,建议不要太大。

WireGuard服务端添加客户端信息

客户端配置好后,还要回到服务端修改wg0.conf配置,将客户端Peer信息加入到服务端配置文件中,服务端完整配置如下:

[Interface]
Address = 10.10.10.1/24
SaveConfig = true
ListenPort = 51820
PrivateKey = 8zXAgoCyqxAjX9wOBGQnBu80pDyBNplZmulUGhhtnik=
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o ens18 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -A FORWARD -o wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o ens18 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o ens18 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o ens18 -j MASQUERADE

[Peer]
PublicKey = 9Lt6RKQf1jk2l0L/6hLIkG2GWPlQOyKIlQxGjefQzUs=
AllowedIPs = 10.10.10.2/32

注意,这里的PublicKey是客户端的PublicKey,并不是服务端本身的PublicKey。

WireGuard进程控制

WireGuard进程控制有两种,如果是临时使用或者调试,可以使用wg-quick命令,如果需要开机自启等,可以使用系统自带的systemctl进行控制,相关命令如下,其中wg0为上述的配置文件名称,命令服务端及客户端通用:

wg-quick up wg0 #启动
wg-quick down wg0 #停止

systemctl start wg-quick@wg0 #启动
systemctl stop wg-quick@wg0 #停止
systemctl restart wg-quick@wg0 #重启
systemctl enable wg-quick@wg0 #开机自启

wg #查看信息

如果一切都正确无误,服务端以及客户端同时启动之后,应该是能互相访问的。

以我上门相关配置来说,结果证明如下。

服务端截图:

WireGuard服务端截图,不包括流量转发相关部分配置

这是客户端截图:

WireGuard客户端截图,不包括流量转发相关部分配置

可以看到,服务端与客户端都是可以互通的,说明两个机器之前已经组成了同一个内网了。

WireGuard无法连接错误排查

作为一个一路踩坑过来的人,我也知道,WireGuard配置过程中有很多需要注意的地方,可能一不小心就出错了,导致最后怎么都无法ping通,比如说如下错误:

root@ZocoXXWireGuardServer:/etc/wireguard# ping 10.10.10.2
PING 10.10.10.2 (10.10.10.2) 56(84) bytes of data.
From 10.10.10.2 icmp_seq=1 Destination Host Unreachable

ping: sendmsg: Required key not available

如果是这个错误,可能需要检查服务端配置文件中是否漏加了Peer部分配置。

如果是这种错误日志:

Jan  1 14:06:39 ZocoXXWireGuardServer kernel: [ 1061.075603] [UFW BLOCK] IN=enp1s0 OUT= MAC=56:00:03:c4:fc:b0:fe:00:03:c4:fc:b0:08:00 SRC=207.246.101.121 DST=207.246.107.155 LEN=176 TOS=0x00 PREC=0x00 TTL=59 ID=17819 PROTO=UDP SPT=37190 DPT=51820 LEN=156
Jan  1 14:07:00 ZocoXXWireGuardServer kernel: [ 1082.324042] [UFW BLOCK] IN=enp1s0 OUT= MAC=56:00:03:c4:fc:b0:fe:00:03:c4:fc:b0:08:00 SRC=207.246.101.121 DST=207.246.107.155 LEN=176 TOS=0x00 PREC=0x00 TTL=59 ID=21179 PROTO=UDP SPT=37190 DPT=51820 LEN=156
Jan  1 14:07:20 ZocoXXWireGuardServer kernel: [ 1101.846659] [UFW BLOCK] IN=enp1s0 OUT= MAC=56:00:03:c4:fc:b0:fe:00:03:c4:fc:b0:08:00 SRC=79.124.62.86 DST=207.246.107.155 LEN=40 TOS=0x00 PREC=0x00 TTL=238 ID=60026 PROTO=TCP SPT=51614 DPT=24718 WINDOW=1024 RES=0x00 SYN URGP=0

可能是系统自带的UFW防火墙没有放行。

根据我一路的踩坑经验,如果遇到问题,可以考虑如下几种情况。

1、像是阿里云、腾讯云这种有安全组的服务器,检查是否在服务器的安全组放行,如果没有放行,外部肯定是无法连接到服务器指定的端口的。

2、像我上述所说,WireGuard使用的是UDP,安全组是否放行的是UDP协议。

3、有些服务商提供的系统镜像中默认开启了防火墙,比如说我上述使用的Vultr的服务中,其自带的Debian11 x64镜像就默认开启了UFW,如果始终无法访问,建议查看系统自带的防火墙比如说ufw、iptables等是否默认开启,如果开启,可能需要对防火墙策略进行修改。

4、运营商QOS限制了UDP导致无法连接到服务器,遇到这种问题,我目前没有什么比较好的方法,实在不行要不换换别的协议吧。

5、打印日志。WireGuard的Quick Start中提供开启日志的方法,连接在这:WireGuard Quick Start

WireGuard个人使用

WireGuard所使用的技术相关问题我也没必要不懂装懂,对于其技术问题的讲解网上已经有很多了,我只从我自身需求及目的出发,说说用了一段时间之后我个人对WireGuard的使用体会。

用了一段时间之后发现,针对我的需求来说,WireGuard真的很方便,简单几步即可将所有流量从指定节点进行转发,而且可以添加多个节点,每个节点可以分流,简单灵活且强大。