Deploy WireGuard with Docker
WireGuard 是一个快速、现代、安全的 VPN 协议,我将搭建一个贯穿 Home,Office,Cloud 的 WireGuard 网络。
Installation
公网 v4 减少,公网 v6 迟迟不能普及。如何实现远程开发?
- 向日葵,蒲公英 等软件解决方案服务商(不安全且慢(2022 年还是 1Mbps))
- frp, nps 等开源 C/S 内网穿透(配置繁琐且慢(Go 语言编写))
- 华为,思科等 VPN 硬件解决方案提供商(一个字 贵。当然这是我的原因)
- OpenVPN 等组网利器配置超级繁琐。慢
- Tailscale 和 ZeroTier(配置简单 需要付费,免费版有设备数量限制。中继服务器在国外。自建节点则不支持 iOS iPadOS 如果打洞不成功则可能失联。TailScale 是基于 WireGuard 的所以嘛 嘿嘿嘿)
- WireGuard(不过配置简单而且快。也可以 NAT to NAT. 没有数量限制。全平台,支持自定 IP)
WireGuard 是什么
WireGuard 是一个易于配置、快速且安全的开源 VPN,它利用了最新的加密技术。目的是提供一种更 快、更简单、更精简的通用 VPN,它可以轻松地在树莓派这类低端设备到高端服务器上部署。 linux.cn
有什么好处?
- 跨平台
- 配置简单,可以直接使用默认值
- 能够在网络故障恢复之后自动重连
- 以 Linux 内核模块的形式运行,资源占用小
- WireGuard 已被并入 Linux 5.6+ 内核 意味着非常容易安装
- 安全,使用了更先进的加密技术,具有前向加密和抗降级攻击的能力。WireGuard 使用 Chacha20 进行对称加密,使用 Poly1305 进行数据验证。利用 Curve25519 进行密钥交换。使用 BLAKE2 作为哈希函数。使用 HKDF 进行解密。WireGuard 对外只暴露了一个 UDP 端口
如何配置
首先看一下我的网络拓扑图
公司网络和家庭网络都通过 ISP(网络服务提供商) 接入互联网,实现访问百度等日常生活所需,所有的终端设备 (PC, mac, Phone) 都通过路由器 DHCP 下发 IP 来上网。Note: 公司局域网和家庭局域网的 IP 网段必须不同 (这在接下来的步骤非常重要)
开始配置 WireGuard
-
安装 WireGuard
如果你的 Linux 内核 5.6, 则可以使用如下方式
sudo apt update sudo apt install wireguard # 本文是以 Ubuntu 22.04 为例,各个发行版大同小异。如 ArchLinux 可以使用 pacman 或者 AUR, centos 可以使用 yum
-
开启服务器端口转发
# 查看转发情况 如果返回 1,说明 IP 转发已经开启 sudo sysctl net.ipv4.ip_forward # 开发 IP 转发 sudo sysctl -w net.ipv4.ip_forward=1 # 如果是 IPV6 地址可以使用 sudo sysctl net.ipv6.conf.all.forwarding
-
编辑服务端配置文件
WireGuard 其实不分 Client/Server,在 WireGuard 中统称为 Peer. 所有的节点都是 Peer. 但本 文为了方便理解还是区分 Client/Server.
-
首先生成一对密钥
wg genkey | tee server-priv-key | wg pubkey > server-pub-key # wg genkey 是官方提供的密钥生成工具
-
编辑配置
WireGuard 安装好之后会默认创建一个/etc/wireguard 文件夹,该文件夹所有人为 root
# vim /etc/wireguard/wg0/conf [Interface] PrivateKey = 上一步生成的私钥 (server-priv-key) Address = 10.0.0.1/24 PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE ListenPort = 51820 DNS = 223.5.5.5 MTU = 1420 # Address 为 wg 内网的 IP 网段 # ListenPort 为 UDP 监听端口。接入 WireGuard 虚拟局域网需要通过此端口,如果使用云服务器需要在管理面板中放行 # PostUp 和 PostDown 为在启动之前需要做什么 以及 在关闭之后需要做什么 这里为一些 iptables 规则 (需要将 eth0 更换为实际网络出口名称)
这样一份 Server 端的配置就可以启动 WireGuard 了
-
启动
使用
wg-quick up wg0
命令,WireGuard 会自动去/etc/wireguard
目录下找以 wg0 开头的.conf 文件 (说明我们可以同时设置多个 WireGuard) -
验证
使用 wg 会显示当前所有已启动 WireGuard 接口下 Peer 的连接信息,包含流量信息
当然我们上面的配置文件中没有添加 Peer, 所以你使用 wg 看不到相关的设备
-
我们稍微更改一下配置
# 为Peer生成一对密钥
wg genkey | tee home-ubuntu-priv-key | wg pubkey > home-ubuntu-pub-key
# vim /etc/wireguard/wg0.conf
[Interface]
PrivateKey = 上一步生成的私钥(server-priv-key)
Address = 10.0.0.1/24
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 51820
DNS = 223.5.5.5
MTU = 1420
# Home Ubuntu
[Peer]
PublicKey = 生成的密钥(home-ubuntu-pub-key)
AllowedIPs = 10.0.0.2/32, 192.168.0.0/24
这样就给服务端配置了第一个客户端 Peer
了
接下来需要在客户端 Peer
进行配置,是的 WireGuard 连通
# vim /etc/wireguard/ubuntu.conf
[Interface]
PrivateKey = 客户端私钥(home_ubuntu_priv_key)
Address = 10.0.0.2/32
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o wlp1s0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o wlp1s0 -j MASQUERADE
DNS = 223.5.5.5
MTU = 1420
[Peer]
PublicKey = 服务端公钥(server-pub-key)
Endpoint = 服务器的IP地址:51820(可以是域名)
AllowedIPs = 10.0.0.0/24, 192.168.0.0/32
PersistentKeepalive = 25
# AllowedIPs 为可以经过的IP地址. 简单理解为分流 如0.0.0.0/0 则所有IP都会经过WireGuard. 这里配置了WireGuard的网段和家中网段
# 如果需要访问内网中的其他设备则需要打开ip转发. 参考安装第2步. 注意Postup和PostDown中wlp1s0更换为出口网卡名称
客户端就配置好了,接下来先将服务端重启 (修改配置后需要重启 WireGuard) wg-quick down wg0
服务端:wg-quick up wg0
客户端:wg-quick up ubuntu
这样就可以组成一个虚拟局域网,此时可以在 Server 中 ping 10.0.0.2
(Home-Ubuntu) 也可以 ping 192.168.0.104
(Home-Windows). 当然都是可以 ping 通的。如果不通可以检查 IP 转发有没有打开或者使用 tcpdump -i wg0
抓包看看
最后再增加一个两个 Peer. 服务端的配置就是这样:
[Interface]
PrivateKey = 上一步生成的私钥(server-priv-key)
Address = 10.0.0.1/24
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 51820
DNS = 223.5.5.5
MTU = 1420
# Home Ubuntu
[Peer]
PublicKey = 生成的密钥(home-ubuntu-pub-key)
AllowedIPs = 10.0.0.2/32, 192.168.0.0/24
# Office-Windows
[Peer]
PublicKey = 生成的密钥(office-windows-pub-key)
AllowedIPs = 10.0.0.4/32
# Office-Linux
[Peer]
PublicKey = 生成的密钥(office-linux-pub-key)
AllowedIPs = 10.0.0.5/32, 192.168.1.0/24
# 注意 Office-Windows 这台设备的 AllowedIPs 没有公司的内网网段(192.168.1.0/24)原因是因为最好不要再 WireGuard 中存在两个相同的网段. 否则 WireGuard 则不知道该将 IP 打向哪台设备
最后也可以使用 Home-Ubuntu 访问位于公司的 192.168.1.0/24
网段。可以试试 ping 192.168.1.2
最终的网络拓扑如下 使用虚线表示 WireGuard
一些建议
- 服务器防火墙只放开 UDP 的 WireGuard 端口 x
- 建议不要使用默认的 51820 端口
- 不要再 WireGuard 中出现相同的网段
- 建议再路由器上使用 WireGuard, 这样路由器下其他设备不需要安装 WireGuard 也可以访问所有的内网(WireGuard 还比较年轻,一些路由器还不支持 WireGuard. 可以自己编译 OpenWRT 路由系统)
- WireGuard 使用 UDP 协议,可能遭遇 UDP QOS 情况。可以使用 udp2raw 进行 UDP 伪装(在山东联通 - 腾讯云北京机房没有遭遇过 UDP QOS 的情况 即使是大流量看视频的情况下)
Reference
My WireGuard config : WireGuard Conf Example
procustodibus blog : WIREGUARD POINT TO SITE CONFIGURATION