组建WireGuard网络
WireGuard是一种近几年新开源的现代化VPN协议,具有高效、轻量和易于配置的特点。它通过使用最新的加密技术,提供了强大的安全性和隐私保护。WireGuard的代码库非常简洁,易于审计和维护,因此被广泛认为比传统的VPN协议(如OpenVPN和IPSec)更安全和高效
本文介绍如何使用WireGuard搭建VPN环境,实现在外部网络环境下远程访问家庭内网
网络环境
- 公网服务器:具有固定公网IP的Linux服务器,作为WireGuard网络的中枢节点
- NAS:通过Docker运行WireGuard客户端,连接公网服务器
- 笔记本:模拟通过手机5G热点(外部网络)连接公网服务器,通过VPN访问家庭内网
网络拓扑
前置要求
检查内核支持
在公网服务器和NAS上检查WireGuard内核模块支持:
# 检查内核模块是否已加载
~ lsmod | grep wireguard
# 尝试加载模块
~ sudo modprobe wireguard
# 检查内核版本
~ uname -r
# 查看模块信息
~ modinfo wireguard
如果内核不支持,需要升级内核,虽然wireguard也可以运行在用户态,但性能较差,CentOS 7操作系统升级内核可以参考CentOS 7 升级内核
部署步骤
部署WireGuard有很多方式,社区还有一些wg-easy等快速部署的项目可以使用
这里为了熟悉WireGuard的配置细节以及了解常见的部署方式,主要按照以下步骤进行:
- 在公网服务器上为了尽可能减少性能损耗,使用原生部署方式来运行
WireGuard中继 NAS系统由于是定制化系统,采用Docker Compose方式运行linuxserver/wireguard容器,尽量不对系统造成影响
对于WireGuard的网络地址,可以使用一些保留地址,不与当前局域网冲突即可,这里选用192.168.100.0/24
| 名称 | IP |
|---|---|
| 服务器 | 192.168.100.1 |
| NAS(peer1) | 192.168.100.2 |
| 外部笔记本(peer2) | 192.168.100.3 |
在公网服务器上部署WireGuard
开启ip转发
ip转发是Linux网络中的核心功能,允许数据包 在网络接口之间进行转发,从而实现不同网络之间的数据传输
# 设置ip转发
~ echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
# 应用更改
~ sysctl -p
安装WireGuard
上面对服务器内核升级后,系统已经内置了WireGuard内核模块,只需要安装wireguard-tools工具包
~ yum install wireguard-tools -y
配置
首先生成密钥对,生成后默认保存在/etc/wireguard目录下,这里有两个客户端,peer1和peer2,因此需要生成两对密钥
# 生成服务器端密钥对
wg genkey | tee server_privatekey | wg pubkey > server_publickey
# 生成客户端密钥对,有几个客户端就生成几个,后面如果新增客户端需要生成新的密钥对
wg genkey | tee client1_privatekey | wg pubkey > client1_publickey
wg genkey | tee client2_privatekey | wg pubkey > client2_publickey
然后在 /etc/wireguard 目录下创建一个名为 wg0.conf 的配置文件,内容如下
[Interface]
PrivateKey = xxxxx ## 服务端私钥
Address = 192.168.100.1 ## 服务端虚拟IP
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE ## 启动时添加iptables规则:(入站规则)允许通过wg0接口进行数据包转发,eth0为主网卡,对应服务器的公网EIP;(出站规则)允许通过wg0接口进行数据包转发,eth0为主网卡,对应服务器的公网EIP;对从wg0接口发出,通过eth0接口出去的数据包进行源地址NAT转换
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE ## 停止时删除iptables规则,避免iptables规则重复,即删除上面添加的入站、出站、NAT转换的规则
ListenPort = 51999 ## WireGuard监听端口,UDP协议,默认是51820
[Peer]
PublicKey = xxxxx ## peer1公钥
AllowedIPs = 192.168.100.2/32, 192.168.50.0/24 ## 允许peer1访问的IP地址,包括WireGuard NAS虚拟ip和家庭局域网网段。用大白话来说,AllowedIPs 就是“这些 IP 地址可以通过这个 peer 访问”。它是“带有这个 peer key 的数据包,其源 IP 属于这些网络之一,是被允许的”。Wireguard 本身不做路由,但是像wg-quick这样的辅助程序,移动客户端或者 Windows 客户端会改变路由表。
[Peer]
PublicKey = xxxxx ## peer2公钥
AllowedIPs = 192.168.100.3/32 ## 允许peer2访问的IP地址,peer2的虚拟IP,这里不需要反过来通过peer1访问peer2的其他局域网设备,因此仅填写peer2的虚拟IP
修改文件权限
~ chmod 600 /etc/wireguard/*
启动服务
~ wg-quick up wg0 # 启动wg0接口
~ wg show wg0 # 查看状态
interface: wg0
public key: xxxx
private key: (hidden)
listening port: 51999
peer: xxxx
allowed ips: 192.168.100.2/32, 192.168.50.0/24
peer: xxxx
allowed ips: 192.168.100.3/32
~ ifconfig wg0 # 启动后会运行一个wg0的虚拟网卡
wg0: flags=209<UP,POINTOPOINT,RUNNING,NOARP> mtu 1420
inet 192.168.100.1 netmask 255.255.255.255 destination 192.168.100.1
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 1000 (UNSPEC)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
~ wg-quick down wg0 # 停止wg0接口
除了手动启动外,wg-quick工具提供了systemd服务单元,可以通过systemctl命令来管理
~ systemctl status wg-quick@wg0 # 查看状态
~ systemctl start wg-quick@wg0 # 启动
~ systemctl stop wg-quick@wg0 # 停止
~ systemctl restart wg-quick@wg0 # 重启
~ systemctl enable wg-quick@wg0 # 设置开机启动
配置防火墙及安全组
如果服务器配置了安全组规则及防火墙规则,则需要放行上面定义的ListenPort/UDP端口
到这里,服务端已经配置完成,下面开始部署客户端
在NAS上部署WireGuard(Peer1)
创建项目目录
~ mkdir wireguard-nas && cd wireguard-nas
创建docker-compose配置
version: '3.8' # Docker Compose文件版本
services:
wireguard: # 服务名称
# 使用linuxserver/wireguard镜像,详情可以查看官方文档
image: lscr.io/linuxserver/wireguard:latest
# 容器名称,便于管理和调试
container_name: wireguard-nas
# 添加必要的Linux capabilities
cap_add:
- NET_ADMIN # 允许网络管理操作(配置接口、路由等)
- SYS_MODULE # 允许加载内核模块(WireGuard内核模块)
# 系统级配置参数(如果启动报错,可以注释掉下面的sysctls配置)
sysctls:
- net.ipv4.conf.all.src_valid_mark=1 # 允许修改数据包标记,用于路由策略
# 环境变量配置
environment:
- PUID=1000 # 容器内进程用户ID,与宿主机用户保持一致
- PGID=1000 # 容器内进程组ID,与宿主机用户组保持一致
- TZ=Asia/Shanghai # 时区设置
- PEERDNS=auto # 自动配置DNS服务器
- INTERNAL_SUBNET=192.168.100.0 # WireGuard内部网段
- LOG_CONFS=true # 启用配置文件日志记录
# 数据卷挂载
volumes:
- ./config:/config # 配置文件目录,持久化存储
- /lib/modules:/lib/modules:ro # 只读挂载内核模块目录,支持内核态WireGuard
# 重启策略
restart: unless-stopped # 除非手动停止,否则自动重启
# 网络模式
network_mode: host # 使用宿主机网络,避免Docker网络层开销,提升性能
生成配置
启动容器,初始化配置文件
~ docker-compose up -d
查看容器挂载的config目录下生成的文件结构,可以看到生成了模板template目录及文件,以及一个wg_confs的空目录
~
tree ./config/ -L 2
config
├── coredns
│ └── Corefile
├── templates
│ ├── peer.conf
│ └── server.conf
└── wg_confs
NAS作为客户端,容器启动后只会生成基本的目录结构,不会生成完整的WireGuard配置。需要手动创建配置文件
~ vim ./config/wg_confs/wg0.conf
[Interface]
PrivateKey = xxxx ## peer1的私钥,需要从公网服务器的./config/peer1/privatekey-peer1获取
Address = 192.168.100.2/24 ## peer1的虚拟IP
[Peer]
PublicKey = xxxx ## 服务器的公钥,需要从公网服务器的./config/server/publickey-server获取
Endpoint = xxxx:51999 ## 服务器的公网IP和端口
AllowedIPs = 192.168.100.0/24 ## 允许访问的WireGuard网段
PersistentKeepalive = 10 ## 保持连接活跃,防止超时
启动服务
配置完成后,正式启动NAS端的WireGuard服务
~ docker-compose restart
# 检查容器状态
~ docker-compose ps
# 查看日志看是否报错
~ docker-compose logs -f
**** As the wireguard module is already active you can remove the SYS_MODULE capability from your container run/compose. ****
**** If your host does not automatically load the iptables module, you may still need the SYS_MODULE capability. ****
**** Client mode selected. ****
[custom-init] No custom files found, skipping...
**** Disabling CoreDNS ****
**** Found WG conf /config/wg_confs/wg0.conf, adding to list ****
**** Activating tunnel /config/wg_confs/wg0.conf ****
Warning: `/config/wg_confs/wg0.conf' is world accessible
[#] ip link add dev wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 192.168.100.2/24 dev wg0
[#] ip link set mtu 1420 up dev wg0
**** All tunnels are now active ****
[ls.io-init] done.