
使用WireGuard将不同地区的局域网或设备连接起来, 组成一个内部虚拟专用网络; 增加Tailscale方案
背景
WireGuard 是一种现代、快速且安全的虚拟专用网络 (V*P*N) 通信协议和免费开源软件。
WireGuard 的设计目标在于易于使用、高速性能和低攻击面。它利用了最新的加密技术,旨在提供比 IPsec 和 OpenV*P*N 等传统 V*P*N 协议更好的性能和更强大的功能。WireGuard 的核心代码相对精简,被 Linux 之父 Linus Torvalds 称为 艺术品,其核心代码只有四千多行。
此外,WireGuard 协议通过 UDP 传递流量,使其在速度和安全性方面具有显著优势。它被设计为简单、高效,并适用于从低端设备如树莓派到高端服务器的广泛环境。
有什么用
Wireguard 回家
学会配置WireGuard这种V*P*N‘回家’的方式,
主要用于在外办公方便V*P*N 回家的使用场景. 下一步博主就要在 macOS, Android 和 K2P 上体验
公网服务器上部署一个Wireguard 服务器,然后让Openwrt 通过Wireguard 连接到公网服务器,然后客户端可以通过Wireguard 访问Openwrt 的内网设备。
硬件
本例子中使用了
- [done] NAS中docker一个WireGuard Easy服务端
-
The easiest way to run WireGuard V*P*N + Web-based Admin UI.
-
主路由为OpenWrt的情况, 作为远程V*P*N的服务端
- 这样外出的电脑和手机等就可以通过这个WireGuard将数据V*P*N回主路由OpenWrt的物理位置
- 设置繁琐, 放弃该方案
- [done]客户端一: MAC OS 电脑作为一个WireGuard客户端接入V*P*N网络
-
成功
-
客户端二: K2P作为一个WireGuard客户端接入V*P*N网络
-
待续, 需要特定的固件
-
[done]客户端三: 安卓手机作为WireGuard客户端接入V*P*N网络
-
成功
-
客户端四: OpenWrt作为WireGuard客户端接入V*P*N网络
新增章节Tailscale
未完待续….
相关内容
实现方法
OpenWRT创建公钥私钥
预共享密钥
通过SSH登陆到 OpenWRT 后台.
mkdir wg
# 创建目录存放公钥私钥
cd wg
# 进入文件夹
umask 077
# 配置创建密钥的权限
wg genpsk > sharekey
# 创建预共享密钥
cat sharekey
# 获取密钥复制保存: vcjUaJ8laSu11QOwYbeSQoVbyMjzLRxzDZGb1OQiAcI=
服务端公钥私钥
wg genkey | tee server_privatekey | wg pubkey > server_publickey
# 创建服务端公钥和私钥
cat server_privatekey
# 获取服务端私钥复制保存
cat server_publickey
# 获取服务端公钥复制保存
MacOS 客户端公钥
客户端公钥私钥 ( macOS )
重复此操作创建每个客户端的公钥和私钥,请注意修改以下命令中的文件名,本文以 macOS 为例:
wg genkey | tee macos_privatekey | wg pubkey > macos_publickey
# 创建 macOS 客户端公钥和私钥
cat macos_privatekey
# 获取 macOS 客户端私钥复制保存
cat macos_publickey
# 获取 macOS 客户端公钥复制保存
运行发现报错:
zsh: command not found: wg
解决:
# 在线安装wireguard
brew install wireguard-tools
配置 OpenWRT UI
服务端相关配置
登陆 OpenWRT – 网络 – 接口 – 添加新接口

基本设置 – 填写上文获取的服务端私钥
自行填写一个端口号 – 并且在路由器映射该端口的 UDP 协议
IP 地址填写一个 V*P*N 专用的网段 IP – 本文以192.168.100.X为 WireGuard 的专用网段为例,则本 WG 服务器 IP 为192.168.100.1/24
防火墙设置 – 选择 vpn
客户端 Peers 区域为每个客户端添加配置

选择预共享密钥 – 添加
公钥 – 填写上文获取的macOS 客户端公钥;
– 新的客户端, 正在尝试, 直接点击 “生成新的密钥对”进行新的客户端Peer的公钥和私钥生成.
预共享密钥 – 填写上文获取的预共享密钥
允许的 IP – 即表示为此 macOS 客户端分配固定 IP , 本文示例为 192.168.100.2/32 , 注意各客户端 IP 不能冲突.
持续 Keep-Alive – 填写 25
防火墙
网络 – 防火墙 – 自定义防火墙 – 添加以下防火墙 – 重启防火墙
iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o br-lan -j MASQUERADE
# 注意此条防火墙网段 192.168.100.0/24 需和上文服务端 IP 网段保持一致.
再次声明博主的 OpenWRT 是作为旁路由接入,此条防火墙不确定适用于主路由部署 WireGuard 使用.主路由用户可以尝试无需设置防火墙(经朋友测试)
配置了一圈防火墙的规则, 还是卡死
nc -vz wg.carlzeng.com 51820
nc: connectx to wg.carlzeng.com port 51820 (tcp) failed: Connection refused

好像又有在OpenWrt的远程服务端收到数据包, 可是又不知道最终效果是如何的?
比如从什么应用出发? 连接了WireGuard V*P*N以后效果是如何的?
是可以直接ping通的, 比如 ping 10.8.0.5
重启 WireGuard
返回网络 – 接口 – 关闭 – 连接
或者直接重启整个 OpenWRT 最为稳妥.
客户端(MAC)
创建客户端配置文件
创建后缀为.conf的配置文件,例如macos_wireguard.conf,复制以下信息,并且修改对应的公私钥信息:
[Interface]
Address = 192.168.100.2/32
# 对应 macOS 客户段分配的 IP
PrivateKey = qJHywBpl27Ao/TRse85DQ/f+kwfNGRmPDYCq0OC6uUY=
# 此时的配置文件是用于客户端的,所以PrivateKey则为 macOS 客户端的私钥
DNS = 192.168.1.3
# 本地的 DNS 服务器或者公有 DNS 服务器,例如: 114.114.114.114
[Peer]
PublicKey = u7vjXN90uJt7pRjG8tR7hb25ssYOi7PRzJ5h9Diy02I=
AllowedIPs = 192.168.1.0/24, 192.168.100.0/24
# macOS 如上设置可与 ClashX Pro 共存仅代理局域网,互联网走本地网络.
# iPhone iPad 设置为 0.0.0.0/0 全局则模式.
PresharedKey = Pu5xBEBmz9ghhUMNp5o72s+w7nuLwxJJUgNk3EljFVo=
# 预共享密钥
Endpoint = ddns.xxxxx.com:12345
PersistentKeepalive = 25
此时的配置文件是用于客户端的,所以PrivateKey则为 macOS 客户端的私钥,而Peer中的PublicKey则为 OpenWRT 的公钥.请注意反向思考,Endpoint填写家中的 IP 或者 DDNS 域名和端口.
AllowedIPs
值得注意的是AllowedIPs参数.针对不同场景和需求,此处可以配置不用的路由.
当此处为0.0.0.0/0时表示任意网络请求都经过 V*P*N 俗称全局 V*P*N , 由于 iPhone 同时只能有 1 个 V*P*N 软件在线,所以当 WireGuard 启动时,其他类似Quanx,小火箭等软件则无法使用,此时 iPhone 可以全局 V*P*N 使用家中的网络来访问一些外网.
如果是 macOS 或 Windows 客户端,WireGuard和Clash等软件可以共存,此处可以设置为AllowedIPs = 192.168.1.0/24, 192.168.100.0/24,表示访问内网网段才会走 V*P*N .而其他互联网,外网等访问还是走当前网络来利用Clash分流.
macOS
在 macOS App Store 下载 WireGuard,从文件导入隧道.
在 OpenWRT 状态页面能够看到连接成功的状态信息
其他命令
wg-quick down wg0 #停止服务
wg-quick strip wg0 #查看配置
wg-quick #查看所有支持的命令
群晖安装 WireGuard 客户端
WireGuard 官方提供了很多系统的客户端,但是群晖暂时还没有,有开发者打包了对应的安装包,但是 DSM 7.0 中,群晖插件机制有改动,造成无法简单安装使用。
一、在套件中心添加“我不是矿神”套件源
名称随意,位置填 https://spk7.imnks.com/ 然后确定
二、安装Wireguard套件

1、切换到root用户
sudo -i
2、赋予Wireguard套件权限(执行该命令后启动Wireguard套件已经不会自动停用)
sudo sed -i 's/package/root/g' /var/packages/WireGuard/conf/privilege
3、在etc目录下创建wireguard文件夹
mkdir /etc/wireguard/
4、编辑Wireguard配置文件
vi /etc/wireguard/wg0.conf
5、进行相关配置
(1)、按下” i “键进行编辑,复制本地编辑好的配置文件内容,鼠标右键直接粘贴
注意:要将DNS那行删掉
实例的NAS中wg0.conf配置文件
[Interface]
Address = 192.168.100.203/32
PrivateKey = 6ANjSDBrOa+hymme+Ive8Fd1GbqOHPosSEQwDNy0x3s=
# 此时的配置文件是用于客户端的,所以PrivateKey则为 NAS 客户端的私钥
[Peer]
PublicKey = G22pgmNqDPGAYg5+bHdMRrxhPQ3HABRla/yZAj0Tu0I=
# 而`Peer`中的`PublicKey`则为 OpenWRT 的公钥
PresharedKey = vcjUaJ8laSu11QOwYbeSQoVbyMjzLRxzDZGb1OQiAcI=
Endpoint = wg.carlzeng.com:51820
AllowedIPs = 192.168.100.0/24
PersistentKeepalive = 25
要小心,这个地方配置文件中的设置;
要和OpenWrt中的Peer设置不一样的, OpenWrt中的Peer设置要填写下吗这些wg genkey 生成的NAS中的公钥和私钥.
wg genkey | tee nas_privatekey | wg pubkey > nas_publickey
# 创建 NAS 客户端公钥和私钥
cat nas_privatekey
# 获取 NAS 客户端私钥复制保存
cat nas_publickey
# 获取 NAS 客户端公钥复制保存
[已解决]故障: MAC端的peer ( sudo wg show wg0) 可以看到输出; 但是 NAS这样的配置 同样运行( sudo wg show wg0)是无法看到peer的输出的
一顿操作, 修改了配置文件后: 主要是
- ssh中的vi wg0.conf
- OpenWrt中设置/添加相应的Peer
root@DS918:/etc/wireguard# wg show wg0
interface: wg0
public key: 6WNPlSVqB6FfpkHGNDXljl9+SdbAfW2/yTxd+iI7t1A=
private key: (hidden)
listening port: 38586
peer: g0ZlzyRHEIOYtxbFtUHTnGATSzRdrB7k1vJzYH+CJWA=
preshared key: (hidden)
endpoint: 221.218.233.216:51820
allowed ips: 192.168.100.0/24
transfer: 0 B received, 2.89 KiB sent
persistent keepalive: every 25 seconds
carlzeng@Carls-MBP AppTesting % sudo wg show
interface: utun3
public key: g0ZlzyRHEIOYtxbFtUHTnGATSzRdrB7k1vJzYH+CJWA=
private key: (hidden)
listening port: 52623
peer: G22pgmNqDPGAYg5+bHdMRrxhPQ3HABRla/yZAj0Tu0I=
endpoint: 221.218.233.216:51820
allowed ips: 192.168.100.0/24
transfer: 0 B received, 5.64 KiB sent
persistent keepalive: every 25 seconds
[下一步]K2P作为一个WireGuard客户端接入V*P*N网络
固件: https://www.right.com.cn/FORUM/thread-8001722-1-1.html
WireGuard client for routers with Padavan based firmware
这个应用的实用性强, 应用广泛. 可目前缺少时间实践刷固件测试, 排队等待下一步执行…
OpenWrt作为WireGuard客户端接入V*P*N网络
OpenWrt安装
wg-quick
-bash: wg-quick: command not found
opkg install wireguard-tools
Package wireguard-tools (1.0.20210914-2) installed in root is up to date.
原来直接在UI上可以直接设置(导入配置文件), 不需要使用wg-quick命令

抱歉我目前无法做这个测试, 我不能把当前的主路由OpenWrt拿来配置WG 客户端 否者担心流量会走入一个错误的循环, 具体参考:
https://www.youtube.com/watch?v=0_zQAp3V18c
{% raw %}
{% endraw %}
故障及排查解决
mac端也是; transfer: 0 B received, 有 sent

6、启动刚才编辑好的配置(启动Wireguard套件后在执行)
sudo wg-quick up wg0
7、查看连接状态
sudo wg show wg0
解决思路: 切换OpenWrt的服务端 到 docker服务器中, 这样简化了整个设置/配置过程.
NAS中运行wg-quick错误
/usr/local/bin/wg-quick: line 32: resolvconf: command not found
wg-quick up HBY_NAS
[#] ip link add HBY_NAS type wireguard
[#] wg setconf HBY_NAS /dev/fd/63
[#] ip -4 address add 10.8.0.4/24 dev HBY_NAS
[#] ip link set mtu 1420 up dev HBY_NAS
[#] resolvconf -a HBY_NAS -m 0 -x
/usr/local/bin/wg-quick: line 32: resolvconf: command not found
[#] ip link delete dev HBY_NAS
just install it with apt-get install resolvconf and reboot, or comment out all DNS fields in configuration file
本章节参考: https://superuser.com/questions/1500691/usr-bin-wg-quick-line-31-resolvconf-command-not-found-wireguard-debian
sudo wg-quick up HBY_NAS
[#] ip link add HBY_NAS type wireguard
[#] wg setconf HBY_NAS /dev/fd/63
[#] ip -4 address add 10.8.0.4/24 dev HBY_NAS
[#] ip link set mtu 1420 up dev HBY_NAS
[#] wg set HBY_NAS fwmark 51820
[#] ip -6 route add ::/0 dev HBY_NAS table 51820
[#] ip -6 rule add not fwmark 51820 table 51820
[#] ip -6 rule add table main suppress_prefixlength 0
[#] ip6tables-restore -n
ip6tables-restore v1.8.3 (legacy): ip6tables-restore: unable to initialize table 'raw'
Error occurred at line: 1
Try `ip6tables-restore -h' or 'ip6tables-restore --help' for more information.
[#] ip -6 rule delete table 51820
[#] ip -6 rule delete table main suppress_prefixlength 0
[#] ip link delete dev HBY_NAS
通过如下设置, 关闭NAS的IPv6

wg-quick up HBY_NAS
[#] ip link add HBY_NAS type wireguard
[#] wg setconf HBY_NAS /dev/fd/63
[#] ip -4 address add 10.8.0.4/24 dev HBY_NAS
[#] ip link set mtu 1420 up dev HBY_NAS
[#] wg set HBY_NAS fwmark 51820
[#] ip -4 route add 0.0.0.0/0 dev HBY_NAS table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0
[#] sysctl -q net.ipv4.conf.all.src_valid_mark=1
[#] iptables-restore -n
iptables-restore v1.8.3 (legacy): iptables-restore: unable to initialize table 'raw'
Error occurred at line: 1
Try `iptables-restore -h' or 'iptables-restore --help' for more information.
[#] ip -4 rule delete table 51820
[#] ip -4 rule delete table main suppress_prefixlength 0
[#] ip link delete dev HBY_NAS
截至目前, 仍然无法给NAS开启WireGuard客户端, 暂时放弃, 因为它也是WireGuard服务器所在的docker容器也在NAS中.
docker搭建WireGuard服务端
状态实时查看界面: http://192.168.6.203:51821/
docker-compose.yml
volumes:
etc_wireguard:
services:
wg-easy:
environment:
# Change Language:
# (Supports: en, ua, ru, tr, no, pl, fr, de, ca, es, ko, vi, nl, is, pt, chs, cht, it, th, hi)
- LANG=en
# Required:
# Change this to your host's public address
- WG_HOST=raspberrypi.local
# Optional:
# - PASSWORD_HASH=$$2y$$10$$hBCoykrB95WSzuV4fafBzOHWKu9sbyVa34GJr8VV5R/pIelfEMYyG (needs double $$, hash of 'foobar123'; see "How_to_generate_an_bcrypt_hash.md" for generate the hash)
# - PORT=51821
# - WG_PORT=51820
# - WG_CONFIG_PORT=92820
# - WG_DEFAULT_ADDRESS=10.8.0.x
# - WG_DEFAULT_DNS=1.1.1.1
# - WG_MTU=1420
# - WG_ALLOWED_IPS=192.168.15.0/24, 10.0.1.0/24
# - WG_PERSISTENT_KEEPALIVE=25
# - WG_PRE_UP=echo "Pre Up" > /etc/wireguard/pre-up.txt
# - WG_POST_UP=echo "Post Up" > /etc/wireguard/post-up.txt
# - WG_PRE_DOWN=echo "Pre Down" > /etc/wireguard/pre-down.txt
# - WG_POST_DOWN=echo "Post Down" > /etc/wireguard/post-down.txt
# - UI_TRAFFIC_STATS=true
# - UI_CHART_TYPE=0 # (0 Charts disabled, 1 # Line chart, 2 # Area chart, 3 # Bar chart)
# - WG_ENABLE_ONE_TIME_LINKS=true
# - UI_ENABLE_SORT_CLIENTS=true
# - WG_ENABLE_EXPIRES_TIME=true
# - ENABLE_PROMETHEUS_METRICS=false
# - PROMETHEUS_METRICS_PASSWORD=$$2a$$12$$vkvKpeEAHD78gasyawIod.1leBMKg8sBwKW.pQyNsq78bXV3INf2G # (needs double $$, hash of 'prometheus_password'; see "How_to_generate_an_bcrypt_hash.md" for generate the hash)
image: ghcr.io/wg-easy/wg-easy
container_name: wg-easy
volumes:
- ./etc_wireguard:/etc/wireguard
ports:
- "51820:51820/udp"
- "51821:51821/tcp"
restart: unless-stopped
cap_add:
- NET_ADMIN
- SYS_MODULE
# - NET_RAW # Uncomment if using Podman
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
如本文第一章照片所示, 这个工具很人性化, 整个设置非常简便, 节省时间.
Tailscale的V*P*N方案
优点: 安卓的流量全部走远程的服务器, 各个APP都会识别远程的IP(比如 闲鱼 等会识别远程的IP和位置)
注册tailscale建议使用Hotmail/Outlook的微软账号.
设置到旁路由, 或者主路由
mkdir tun && mkdir lib
#下面是docker-compose.yaml
vi docker-compose.yaml
version: '3.8'
services:
tailscale:
image: tailscale/tailscale:latest
container_name: tailscale
network_mode: host
volumes:
- ./tun:/dev/net/tun
- ./lib:/var/lib
environment:
- TS_AUTH_KEY=tskey-auth-kAxuYZ8wMC21CNTRL-Eyia43QCsAagRFUNtZGHBasETVAGGXXX
- TS_STATE_DIR=/var/lib/tailscale
- TS_HOSTNAME=Debian12docker
- TS_EXTRA_ARGS=--advertise-routes=192.168.6.0/24 --advertise-exit-node
设置在Tailscale的Access Control 里面
{
"tagOwners": {
// 设置 tag 和拥有者,tag 可以不用改,后面的邮箱改成你自己的账号名
"tag:docker": ["XXXX@outlook.com"],
},
"autoApprovers": {
// 设置自动开启子网功能:192.168.X.0/24 改成你家里网段,这个很重要,后面也还要用到,简单理解即你家路由器 ip 地址的最后一个数字改成 0 并加上/24 ,假如你的路由器管理页面是 192.168.31.1 ,则应填 192.168.31.0/24
"routes": {
"192.168.6.0/24": ["XXXX@outlook.com", "tag:docker"],
},
// 设置自动开启 exitnode 功能,可选
"exitNode": ["tag:docker"],
},
}
生成密钥的页面:

这个密钥就是用在docker-compose中的密钥
原来这个密钥已写明了有效截止日期, 定期要手动更新的(每次新建最长90天, 三个月), 原来是这样的设计….
Android客户端
下载安卓客户端文件安装, 比如: tailscale-android-universal-1.84.0.apk
下载地址: https://pkgs.tailscale.com/stable/#macos
安装后登录;
然后自动就连接上了(会要求在本机 新建一个文件夹)
开启连接成功后, V*P*N显示建立成功
MAC OS客户端
被这个卡死: Change security settings on the startup disk of a Mac with Apple silicon
Change security settings on the startup disk of a Mac with Apple silicon
显示应用场景/背景
本地用Windows笔记本或者游戏的主机
用一台淘汰的Windows主机, 安装双网口的网卡, 一个做LAN, 另一个做WAN;
然后这台Windows用作软路由, 用Hyper安装OpenWrt的虚拟机, 用来把WAN口拨号, Lan口转接到交换机或者旁路由
故障排除troubleshooting tailscale
手机安卓客户端打开app后, 可以正常登录但是图标处显示, 有可用更新, 然后‘ EXIT NODE’显示为None, 导致服务不可用; 如何排查?
-
打开检查账号
-
终于使用outlook的oAuth2.0登录的https://login.tailscale.com/admin/machines
-
查看到machines中只有手机, 那么就是docker的没有在线了?
-
查看docker状态
-
默认是了117的服务器
-
docker ps 检查到tailscale没有运行
-
启动报错:
ailscale | 2026/02/09 12:54:32 Start
tailscale | 2026/02/09 12:54:32 ipnext: active extensions: relayserver, taildrop
tailscale | 2026/02/09 12:54:32 Backend: logs: be:a4ce375033a842278b8c3192b6f707c3f2033d23a87fa7d1a1fbc9531b33d378 fe:
tailscale | 2026/02/09 12:54:32 control: client.Login(0)
tailscale | 2026/02/09 12:54:32 health(warnable=warming-up): error: Tailscale is starting. Please wait.
tailscale | 2026/02/09 12:54:32 control: doLogin(regen=false, hasUrl=false)
tailscale | boot: 2026/02/09 12:54:33 [warning] failed to symlink socket: file exists
tailscale | To interact with the Tailscale CLI please use `tailscale --socket="/tmp/tailscaled.sock"`
tailscale | boot: 2026/02/09 12:54:33 Running 'tailscale up'
tailscale | 2026/02/09 12:54:33 Start
tailscale | 2026/02/09 12:54:33 Backend: logs: be:a4ce375033a842278b8c3192b6f707c3f2033d23a87fa7d1a1fbc9531b33d378 fe:
tailscale | 2026/02/09 12:54:33 control: client.Login(0)
tailscale | 2026/02/09 12:54:33 control: client.Shutdown ...
tailscale | 2026/02/09 12:54:33 control: mapRoutine: exiting
tailscale | 2026/02/09 12:54:33 control: authRoutine: exiting
tailscale | 2026/02/09 12:54:33 health(warnable=login-state): error: You are logged out. The last login error was: fetc
h control key: Get "https://controlplane.tailscale.com/key?v=116": context canceled
tailscale | 2026/02/09 12:54:33 control: updateRoutine: exiting
tailscale | 2026/02/09 12:54:33 control: Client.Shutdown done.
tailscale | 2026/02/09 12:54:33 control: doLogin(regen=false, hasUrl=false)
tailscale | 2026/02/09 12:54:33 control: control server key from https://controlplane.tailscale.com: ts2021=[fSeS+], le
gacy=[nlFWp]
tailscale | 2026/02/09 12:54:33 control: RegisterReq: onode= node=[tDr/a] fup=false nks=false
tailscale | 2026/02/09 12:54:34 control: RegisterReq: got response; nodeKeyExpired=false, machineAuthorized=false; auth
URL=false
tailscale | 2026/02/09 12:54:34 health(warnable=login-state): error: You are logged out. The last login error was: inva
lid key: API key does not exist -
观察到docker日志, 应该说login失败, API key的故障
-
核对网站上的信息 和 Keys, 发现之前的auth key已经被删除(应该是过期自动清理了)

尝试生成一个超过3个月的key, Pending valification
Generated new key

Be sure to copy your new key below. It won’t be shown in full again.
tskey-auth-kqQbFMa*******
This key will expire on May 10, 2026. If youʼll then want to continue using an auth key, youʼll need to generate a new one.
- 更新了key以后, nano docker-compose.yaml 把新的key更新到TS_AUTH_KEY中
- 重启当前Tailscale的docker-compose, 日志显示正常无错误, 再打开手机客户端可以看到另外的一个节点docker和手机客户端,
- 这时手机端可以设置EXIT NODE为docker, 完成数据流量流转
灵感来源
https://www.ioiox.com/archives/143.html
https://github.com/wg-easy/wg-easy
https://www.wireguard.com/install/

发表回复