引言

当我们需要异地访问家庭/公司内网时,最简单粗暴的方案就是公网IP + 端口转发,然而,这表面看似简单的背后却潜藏着很大风险,公网IP + 端口转发本质上是:

1
公网 → 路由器 → 内网

黑客会 7*24 小时对公网IP进行端口扫描,很多 IoT / NAS / 管理界面根本没安全设计,再加上弱口令 / 0day / Web 漏洞,一旦某个内网设备被攻破,黑客就可以通过该设备入侵局域网的其他设备,看一眼你家监控、访问开放的RD端口对计算机投放病毒、入侵NAS……这些操作都是轻而易举的事。因此,安全地从异地访问内网,WireGuard是更好的选择,本文将以最符合安全规范的方式,完成WireGuard的部署与组网。

WireGuard简介

WireGuard是一种实现加密虚拟专用网络(VPN) 的通信协议和免费开源软件,其设计目标是易于使用、高速性能和低攻击面。WireGuard 通过 UDP 安全地封装 IP 数据包。你添加一个WireGuard接口,配置你的私钥和节点的公钥,然后通过它直接与内网进行数据传输。相比于上面提到的公网IP + 端口转发的方案,你只需要在路由器映射WireGuard的端口到WAN IP,而不再像之前把需要通过公网访问的内网服务分别映射到公网,保证安全的同时又便于管理。

快速开始

前期准备

如果在外网的情况下使用wireguard,安装之前需要满足以下条件:

  • 需要有公网IP地址(动态IP可配置DDNS绑定域名)
  • 路由器开启端口转发,将公网UDP 51820端口映射到内网Linux主机的IP
  • Linux内核版本 > 5.6

本教程安装环境如下:

  • Linux发行版本:Debian GNU/Linux 13
  • 内核版本:6.12.90+deb13.1-amd64

安装

执行命令:

1
sudo apt install wireguard

生成公私密钥对

WireGuard 基于非对称加密体系进行身份验证。我们需要为服务端和未来的客户端分别生成密钥对。

切换到 root 并在 wireguard 目录下操作

1
2
3
sudo -i
cd /etc/wireguard
umask 077

生成服务端的私钥和公钥

1
wg genkey | tee server_private.key | wg pubkey > server_public.key

生成客户端的私钥和公钥

1
wg genkey | tee client1_private.key | wg pubkey > client1_public.key

这里可以用 cat 命令分别查看生成的公钥私钥内容,复制到记事本备用,比如

1
2
# 输出服务器私钥字符串内容:
cat server_private.key

确认物理网卡名称

1
ip a

如图,通常IP为192.168.x.x的就是物理网卡

配置文件

创建并编辑主配置文件 wg0.conf

1
nano /etc/wireguard/wg0.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[Interface]
# 设定 WireGuard 虚拟局域网的 IP 地址,10.0.0.1 是服务端自己
Address = 10.0.0.1/24
# 监听端口,需与路由器映射的端口一致
ListenPort = 51820
# 填入前面生成的 server_private.key 的内容
PrivateKey = <服务端的私钥>

# 这两行是在启动时添加 NAT 转发规则,关闭时删除
# 把 enp1s0 换成主机的实际网卡名
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -m state --state RELATED,ESTABLISHED -j ACCEPT; iptables -t nat -A POSTROUTING -o enp1s0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -m state --state RELATED,ESTABLISHED -j ACCEPT; iptables -t nat -D POSTROUTING -o enp1s0 -j MASQUERADE

[Peer]
# 允许连接的客户端 1 配置
# 填入前面生成的 client1_public.key 的内容
PublicKey = <客户端1的公钥>
# 分配给客户端 1 的固定虚拟 IP
AllowedIPs = 10.0.0.2/32

开启内核 IP 转发

1
2
3
4
5
# 修改 sysctl 配置文件
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf

# 使其立即生效
sudo sysctl -p

启动并设置开机自启

启动 wg0 接口

1
sudo wg-quick up wg0

查看运行状态

1
sudo wg

设置开机自启

1
sudo systemctl enable wg-quick@wg0

至此,Linux 服务端已经配置完毕并开始监听。

外网客户端配置

在外网设备(Windows、macOS、Android 或 iOS)上下载官方的 WireGuard 客户端。新建一个空白隧道配置,填入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Interface]
# 刚才给客户端分配的虚拟 IP
Address = 10.0.0.2/24
# 填入前面生成的 client1_private.key 的内容
PrivateKey = <客户端1的私钥>

[Peer]
# 填入前面生成的 server_public.key 的内容
PublicKey = <服务端的公钥>
# 10.0.0.0/24 是 VPN 虚拟网段,192.168.1.0/24 改成真实局域网网段
AllowedIPs = 10.0.0.0/24, 192.168.1.0/24
# DDNS 域名和映射的端口
Endpoint = home.example.com:51820
# 保持 NAT 映射活跃,对于动态 IP 很有帮助
PersistentKeepalive = 25

💡提示:推荐直接在服务器执行nano /etc/wireguard/client1.conf,写入客户端配置,然后安装qrencode,qrencode是个非常实用的轻量级工具,可以直接在终端屏幕输出配置文件的二维码,然后在手机上打开WireGuard 客户端扫码导入配置。

1
2
3
4
5
# 安装qrencode
sudo apt install qrencode

# 生成二维码
qrencode -t ansiutf8 < /etc/wireguard/client1.conf

连接测试

激活客户端隧道后, 就可以直接像在内网一样在浏览器里输入路由器的 IP 访问后台了,这样就只需要连接WireGuard服务端访问局域网内的设备。整个结构跑通后,日常维护非常省心。

参考资料

WireGuard官网