外地访问家里的服务,比起使用frp等内网穿透工具,组建虚拟局域网更为省心。当设备数量增多时,组网的优势更加明显。
WireGuard作为现代VPN技术,优势不再赘述。用几个关键词来形容:简单 高效 内核级 跨平台
网络拓扑设计
异地组网需一台具备公网IP的服务器作网关。中心服务器模式如下:
graph TB GW[中心服务器<br/>公网IP: x.x.x.x<br/>内网IP: 10.8.0.1] subgraph 家庭网络 PC[家用电脑<br/>10.8.0.2] NAS[NAS存储<br/>10.8.0.3] TV[智能电视<br/>10.8.0.4] end subgraph 移动设备 Phone[手机<br/>10.8.0.5] Laptop[笔记本<br/>10.8.0.6] end PC --> |WireGuard| GW NAS --> |WireGuard| GW TV --> |WireGuard| GW Phone -.-> |WireGuard| GW Laptop -.-> |WireGuard| GW classDef local fill:#lightgreen class PC,NAS,TV local
设备类型 | IP范围 | 示例IP |
---|---|---|
服务器 | 10.8.0.1 | 10.8.0.1 |
其他设备 | 10.8.0.0/24 | 10.8.0.2 |
服务端
要求:
- 境内公网IP服务器。境外IP大概率封端口甚至封IP
- 合适的服务器带宽。推荐阿里云/腾讯云200M机器,如果没有视频等大流量需求,4~8M也可
- 可访问的UDP端口
替代方案:WG-Easy
服务器配置比较好的可以用wg-easy方案,直接在Web管理界面操作。
本文专注于低配服务器(内存<512M)方案。Docker额外占用系统资源,这里不做展开。
手动方案
WireGuard已进入Linux内核,安装起来非常简单。参考官方安装文档
sudo apt update
sudo apt install wireguard -y
安装后提供wg
和wg-quick
两个主要命令。
生成密钥对
每个WireGuard节点需要一对公私钥:
cd /etc/wireguard
wg genkey | tee privatekey | wg pubkey > publickey
创建服务端配置 /etc/wireguard/wg0.conf
:
[Interface]
Address = 10.8.0.1/24
ListenPort = 10012
PrivateKey = <服务器私钥>
[Peer]
PublicKey = <客户端1公钥>
AllowedIPs = 10.8.0.2/32
[Peer]
PublicKey = <客户端2公钥>
AllowedIPs = 10.8.0.3/32
参数说明:
Address
:服务器在VPN中的IP地址和子网掩码ListenPort
:监听的UDP端口PrivateKey
:服务器私钥PostUp/PostDown
:启动/关闭时执行的命令,用于设置IP转发eth0
:替换为外网网卡名称(用ip a
查看)- 每个客户端对应一个
[Peer]
块
启用IPv4转发
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
配置防火墙
在云服务厂商后台添加UDP端口流量放行,本文的例子是10012
启动 systemd 服务
# 启动服务
sudo systemctl start wg-quick@wg0
# 开机自启
sudo systemctl enable wg-quick@wg0
查看状态以及热重载
# 查看状态
sudo wg show
# 热重载配置
sudo bash -c 'wg addconf wg0 <(wg-quick strip wg0)'
GUI客户端配置
根据平台下载GUI客户端,编辑配置
[Interface]
PrivateKey = <自动生成客户端私钥>
Address = 10.8.0.9/32
[Peer]
PublicKey = <服务端公钥>
AllowedIPs = 10.8.0.0/24
Endpoint = <服务端IP:端口>
PersistentKeepalive = 25
MacOS效果如图
CLI客户端配置
与服务端安装所有操作相同,只是配置文件替换成上面的客户端配置文件
一个便捷脚本:
#!/bin/bash
# 检查参数
if [ -z "$1" ]; then
echo "用法: $0 <client_last_octet>"
echo "例如: $0 9"
exit 1
fi
OCTET="$1"
# 检查OCTET是否为1-254的数字
if ! [[ "$OCTET" =~ ^[0-9]+$ ]] || [ "$OCTET" -lt 1 ] || [ "$OCTET" -gt 254 ]; then
echo "错误:client_last_octet 必须是1-254之间的整数"
exit 1
fi
CLIENT_ADDRESS="10.8.0.${OCTET}/32"
# 请将以下两项替换为实际信息
SERVER_PUBLIC_KEY="<服务端公钥>"
SERVER_ENDPOINT="<服务器IP:端口>" # 例:1.2.3.4:10012
# 检查 WireGuard 是否已安装
if ! command -v wg > /dev/null 2>&1; then
echo "WireGuard 未安装,正在安装..."
apt update
apt install -y wireguard
else
echo "WireGuard 已安装,跳过安装步骤。"
fi
# 切换到配置目录
cd /etc/wireguard || exit 1
# 生成密钥对(如果不存在)
if [ ! -f privatekey ] || [ ! -f publickey ]; then
echo "密钥不存在,正在生成新的密钥对..."
umask 077
wg genkey | tee privatekey | wg pubkey > publickey
else
echo "发现已存在的密钥对,将继续使用现有密钥。"
fi
# 读取密钥
PRIVATE_KEY=$(cat privatekey)
# 备份旧配置(如果存在)
if [ -f wg0.conf ]; then
BACKUP_FILE="wg0.conf.bak.$(date +%Y%m%d%H%M%S)"
echo "检测到已存在的 wg0.conf,备份到 $BACKUP_FILE"
cp wg0.conf "$BACKUP_FILE"
fi
# 生成客户端配置文件
cat > wg0.conf <<EOF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = $CLIENT_ADDRESS
[Peer]
PublicKey = $SERVER_PUBLIC_KEY
AllowedIPs = 10.8.0.0/24
Endpoint = $SERVER_ENDPOINT
PersistentKeepalive = 25
EOF
# 修改权限
chmod 600 wg0.conf privatekey publickey
# 启动 WireGuard
systemctl restart wg-quick@wg0
systemctl enable wg-quick@wg0
# 查看状态
wg show
# 读取客户端 PublicKey
CLIENT_PUBLIC_KEY=$(cat publickey)
echo
echo "================ 服务端需要添加的 Peer 配置 ================"
echo "[Peer]"
echo "PublicKey = $CLIENT_PUBLIC_KEY"
echo "AllowedIPs = 10.8.0.$OCTET/32"
echo "==========================================================="
echo
一些常见问题
运营商UDP QoS问题
使用udp2raw将UDP封装为TCP。
性能测试
- iperf3:带宽测试
- ping:延迟测试
NAT穿透
客户端在严格NAT后,添加PersistentKeepalive参数(25秒)一般就能解决