目录 
•  在NAS上部署WireGuard(Peer1) WireGuard是一种近几年新开源的现代化VPN协议,具有高效、轻量和易于配置的特点。它通过使用最新的加密技术,提供了强大的安全性和隐私保护。WireGuard的代码库非常简洁,易于审计和维护,因此被广泛认为比传统的VPN协议(如OpenVPN和IPSec)更安全和高效。 
本文介绍如何使用WireGuard搭建VPN环境,实现在外部网络环境下远程访问家庭内网。 
网络环境 •  公网服务器 :具有固定公网IP的Linux服务器,作为WireGuard网络的中枢节点 •  NAS :通过Docker运行WireGuard客户端,连接公网服务器 •  笔记本 :模拟通过手机5G热点(外部网络)连接公网服务器,通过VPN访问家庭内网 网络拓扑 WireGuard隧道 
WireGuard隧道 
路由转发 
路由转发 
Linux服务器固定公网IPWireGuard Hub中继 前置要求 检查内核支持 在公网服务器和NAS上检查WireGuard内核模块支持: 
# 检查内核模块是否已加载 ~ lsmod | grep wireguard # 尝试加载模块 ~  sudo  modprobe wireguard # 检查内核版本 ~  uname  -r # 查看模块信息 ~ modinfo wireguard 如果内核不支持,需要升级内核,虽然 wireguard 也可以运行在 用户态 [1] ,但性能较差, CentOS 7 操作系统升级内核可以参考 CentOS 7 升级内核 [2] 
部署步骤 部署 WireGuard 有很多方式,社区还有一些 wg-easy [3] 等快速部署的项目可以使用 
这里为了熟悉 WireGuard 的配置细节以及了解常见的部署方式,主要按照以下步骤进行: 
• 在公网服务器上为了尽可能减少性能损耗,使用原生部署方式来运行 WireGuard 中继 •  NAS 系统由于是定制化系统,采用 Docker Compose 方式运行 linuxserver/wireguard [4] 容器,尽量不对系统造成影响 对于 WireGuard 的网络地址,可以使用一些 保留地址 [5] ,不与当前局域网冲突即可,这里选用 192.168.100.0/24 
在公网服务器上部署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. 配置外部笔记本(Peer2) 外部笔记本需要使用peer2的配置进行连接,先编辑一个配置文件内容 
[Interface] PrivateKey = xxxxx  ## peer2的私钥,需要从公网服务器的./config/peer2/privatekey-peer2获取 Address = 192.168.100.3/24   ## peer2的虚拟IP [Peer] PublicKey = xxxxx  ## 服务器的公钥,需要从公网服务器的./config/server/publickey-server获取 Endpoint = xxxx:51999   ## 服务器的公网IP和端口 AllowedIPs = 192.168.100.0/24, 192.168.50.0/24   ## 允许访问的WireGuard网段和家庭局域网 PersistentKeepalive = 10   ## 保持连接活跃,防止超时 安装WireGuard Windows/macOS : 
• 下载官方WireGuard客户端:https://www.wireguard.com/install/ 导入配置 在 WireGuard 客户端中导入上面编辑的配置文件 
启动连接 导入后点击管理隧道,点击启动(启动前别忘了切换笔记本连接热点,使网络不与家庭网络在一起) 
配置家庭网络路由或NAT 完成了上面的服务端、NAS端(peer1)、笔记本(peer2)的配置后,基本上已经可以通过 VPN 从笔记本访问 NAS 了,这里还剩下最后一步,也就是 需要使笔记本(peer2)能通过 VPN 访问家庭局域网的其他设备 
主要有两种方式:一种是使用 NAT ,另一种是使用静态路由,下面分别介绍和说明: 
•  NAT :和上面的服务端配置类似,需要在 NAS 端的 WireGuard 配置中添加 PostUp 和 PostDown 规则,目的是为了将来自 WireGuard 的 192.168.100.0/24 网段进行地址转换后访问到家庭局域网 • 静态路由:静态路由是指将 WireGuard 的 192.168.100.0/24 网段路由到家庭局域网,即将 WireGuard 的 192.168.100.0/24 网段配置到局域网路由表中,这样就省去了 NAT 的开销 这里以静态路由举例,可以把路由配置到家中的路由器上,以我使用的 ASUS RT-AX86U Pro 为例,添加静态路由,把 WireGuard 的 192.168.100.0/24 网段路由到 NAS 主机 
验证连接 检查WireGuard状态 # 在公网服务器上 ~ wg show wg0 interface: wg0   public key: xxxxx   private key: (hidden)   listening port: 51999 peer: xxxxx   endpoint: xxxxx:4503   allowed ips: 192.168.100.2/32, 192.168.50.0/24   latest handshake: 15 seconds ago   transfer: 196.93 KiB received, 132.02 KiB sent peer: xxxxx   endpoint: xxxxx:55562   allowed ips: 192.168.100.3/32   latest handshake: 2 minutes ago   transfer: 83.53 KiB received, 83.42 KiB sent # 在NAS上 ~ docker  exec  -it wireguard-nas wg show interface: wg0   public key: xxxxx   private key: (hidden)   listening port: 36018 peer: xxxxx   endpoint: xxxxxx:51999   allowed ips: 192.168.100.0/24   latest handshake: 18 seconds ago   transfer: 1.26 MiB received, 9.25 MiB sent   persistent keepalive: every 25 seconds 测试连通性 # 从NAS(peer1) ping公网服务器 ping 192.0.2.1 # 从公网服务器ping NAS(peer1) ping 192.0.2.2 # 从外部笔记本(peer2) ping公网服务器 ping 192.0.2.1 # 从外部笔记本ping NAS(peer1) ping 192.0.2.2 # 从笔记本(peer2) 测试家中局域网访问 ping 192.168.50.1   # 家中路由器IP 常见问题排查及其他 连接失败 # 检查容器日志 docker-compose logs wireguard # 检查WireGuard状态 docker  exec  -it wireguard-server wg show # 检查防火墙规则 sudo  iptables -L -n 网络不通 # 检查IP转发 cat  /proc/sys/net/ipv4/ip_forward # 检查路由表 ip route show # 检查网络接口 ip  link  show 如果还是有问题,可以尝试抓包排查 
性能问题 # 检查是否使用内核模块 lsmod | grep wireguard # 检查MTU设置 ip  link  show wg0 # 调整MTU值(在配置文件的[Interface]块中添加) MTU = 1420 # 启用多队列 sudo  ethtool -L eth0 combined 4 容器启动失败 如果遇到以下错误: 
failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: sysctl "net.ipv4.conf.all.src_valid_mark" not allowed in host network namespace 解决方案 : 注释掉有问题的  sysctls  配置: 
# 注释掉整个sysctls部分 # sysctls: #   - net.ipv4.conf.all.src_valid_mark=1 在宿主机上手动设置该参数: 
# 在宿主机上设置 sudo  sysctl -w net.ipv4.conf.all.src_valid_mark=1 # 永久生效 echo   'net.ipv4.conf.all.src_valid_mark=1'  |  sudo   tee  -a /etc/sysctl.conf sudo  sysctl -p 配置DNS # 在peer配置中添加DNS服务器,如果使用ip连接,这个应该没什么用 DNS = 8.8.8.8, 8.8.4.4 wg常用命令 # 查看所有WireGuard接口 wg show # 查看特定接口 wg show wg0 # 查看接口详细信息 wg show wg0 dump # 启动接口 wg-quick up wg0 # 停止接口 wg-quick down wg0 # 重新加载配置 wg syncconf wg0 <(wg-quick strip wg0) 引用链接 [1]  用户态:  https://www.netmaker.io/resources/kernel-module-vs-user-space-wireguard [2]  CentOS 7 升级内核:  https://www.ssgeek.com/docs/linux/system/centos/centos7-upgrade-kernel [3]  `wg-easy`:  https://github.com/wg-easy/wg-easy [4]  `linuxserver/wireguard`:  https://github.com/linuxserver/docker-wireguard [5]  保留地址:  https://zh.wikipedia.org/wiki/%E4%BF%9D%E7%95%99IP%E5%9C%B0%E5%9D%80