使用wireguard组虚拟局域网

本文最后更新于:2024年11月4日 下午

版权归作者所有, 转载请保留该部分声明。
本文作者:EtcFly
原文地址:https://etcfly.top


概述

  有时候在公司或者在家里需要访问对方的私有网络, 这时候是无法访问的,通常在这种情况下我们会安装frp等软件来进行代理, 但是这有两个问题:

  • 只能点对点访问, 也就是说只能访问固定内网的特定主机
  • 安全性较低,暴露内网的服务端口会引发安全问题

因此基于这类考虑,最终选择部署wireguard服务, wireguard服务是新一代vpn技术, 目前已经合入linux内核, 因此其具有极高的稳定性。

wireguard服务需要满足所有节点中必须有一个节点具有公网ip(需要通过它进行流量转发), 通常情况下部署wireguard有三种方案:

  • 家里有公网ip的宽带, 在有公网ip的路由上部署wireguard服务, 其他节点连接该节点
  • 没有公网ip, 但是路由器是拨号路由, 可以通过ddns映射到一个固定域名, 然后域名来访问服务
  • 有公网的云服务器, 在其上部署代理节点, 其他节点连接到服务器节点

这些方案大家自己权衡, 由于客观环境因素, 我这里采用方案三。


部署环境

  先简要说明一下我这里的环境

  • 云服务器一台(公网ip)
  • 公司n级路由器(已经刷了openwrt, 子网网段192.168.115.x)
  • 家庭n级路由器(已经刷了openwrt, 子网网段192.168.125.x)

网络拓扑如下:
家庭网络拓扑.png

这里需要打通192.168.115.0/24192.168.125.0/24两个网段。


服务端部署

  服务端这里采用docker部署, 网路上原本存在一个wg-easy的方案, 地址见后面参考资料, 但是由于其不能指定AallowIP地址, 因此这里没有采用, 而是自己手动构建docker方案。Dockerfile, 内容较简单如下:

1
2
3
4
5
6
7
8
FROM ubuntu

WORKDIR /

RUN apt update && apt install -y iproute2 iptables wireguard
#RUN npm build

CMD wg-quick up wg0 ; /bin/bash

然后执行如下命令:

1
docker build -t wireguard-server .

成功构建后, 使用docker部署:

1
2
3
4
5
6
7
8
9
docker run -d -it \
--name=wg-server \
-v ~/.wg-easy:/etc/wireguard \
-p 51820:51820/udp \
--cap-add=NET_ADMIN \
--cap-add=SYS_MODULE \
--sysctl="net.ipv4.conf.all.src_valid_mark=1" \
--sysctl="net.ipv4.ip_forward=1" \
--restart=always wireguard-server

注意, 这里将宿主机~/.wg-easy目录挂载到wireguard默认配置目录下, 避免后期容器删除导致配置丢失。

由于我们是连通两个网段, 加上服务端代理节点一共需要三个节点, 因此在服务端生成三个密钥对用于后面加密传输(需要每个节点一个):

1
wg genkey | tee /etc/wireguard/server.private.key | wg pubkey > /etc/wireguard/server.public.key

这样就生成了服务端密钥对, 如果这里报command not found: wg, 需要安装如下工具:

1
apt install wireguard-tools

类似的方法生成home.private.key, home.public.key, company.private.key, company.public.key, 然后创建一个wg0.conf文件, 这个文件就是wireguard全局配置文件, 写入如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Note: Do not edit this file directly.
# Your changes will be overwritten!

# Server
[Interface]
PrivateKey = 服务端私钥
Address = 10.8.0.1/24
ListenPort = 51820
PreUp =
PostUp = iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE; iptables -A INPUT -p udp -m udp --dport 51820 -j ACCEPT; iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT;
PreDown =
PostDown = iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE; iptables -D INPUT -p udp -m udp --dport 51820 -j ACCEPT; iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT;

# Client: home
[Peer]
PublicKey = 家庭网络的公钥
PresharedKey = 家庭网络的预共享密钥
AllowedIPs = 192.168.125.0/24,10.8.0.2/32

# Client: company
[Peer]
PublicKey = 公司网络的公钥
PresharedKey =公司网络的预共享密钥
AllowedIPs = 192.168.115.0/24,10.8.0.3/32

这样就可以了, 然后重启一下docker

1
docker restart wg-server

这样服务端就配好了。这里需要说明一下, AllowedIPs表示服务器中继节点要不要向该端口转发这个ip网段的流量, 如果你需要采用内网ip访问需要加上。


openwrt 客户端配置

openwrt中默认是没有wireguard插件的, 需要手动安装如下:

  • luci-proto-wireguard: 用于支持 WireGuard 的核心包
  • qrencode: 生成展示客户端的二维码。

安装可以通过命令行或者软件包中安装, 这里就不详述。安装完成后需要重启路由器, 不然无法进一步操作。重启完成后, 进入 网络 -> 接口, 添加新接口:
添加接口.png

接下来设置如下:
wireguard常规设置.png
wireguard高级设置.png
wireguard防火墙区域.png
wireguard转发节点添加.png
wireguard中继节点设置.png

注意:

  • 对端设置中的允许ip新增后会新建一条代理路由, 如果没有包含相关网段,中继可能会出问题。新增的路由表如下:
1
2
3
4
5
6
[root@KWrt:03:42 PM ~] # route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.16.208.1 0.0.0.0 UG 0 0 0 wan
10.8.0.0 0.0.0.0 255.255.255.0 U 0 0 0 wg0
192.168.125.0 0.0.0.0 255.255.255.0 U 0 0 0 wg0

当然以上是通过手动添加客户端配置的方式, 还可以通过自动导入配置的方式来进行, 配置格式如下:

1
2
3
4
5
6
7
8
9
10
11
[Interface]
PrivateKey = wJ7fCp6+oHruJk4XVg0cTD7YauLza0Bmc46cDOE6nFg=
Address = 10.8.0.x #设置客户端在虚拟网段的ip
# DNS not defined

[Peer]
PublicKey = 服务端公钥
PresharedKey = 预共享密钥
AllowedIPs = 192.168.125.0/24, 10.8.0.0/24
Endpoint = 服务器代理地址:端口
PersistentKeepAlive = 25

保存并应用, 通过以上设置, 新建的接口就配置好了, 然后进入网络 - 防火墙,这里会自动新建一个vpn区域。点击编辑:
wireguard防火墙常规设置.png
wireguard防火墙高级设置.png

保存,然后设置lan区域:
wireguard防火墙lan区域设置.png
wireguard防火墙lan基本设置.png

保存并应用, 设置好以后记得重启路由器,否则可能异常。至此, 192.168.125.0/24网段的部署就完成了。这时候可以使用电脑连接到路由器, 然后ping一下中继节点, 这里是10.8.0.1, 如下:

1
2
3
4
5
6
7
8
9
10
11
C:\Users\EtcFly>ping 10.8.0.1

正在 Ping 10.8.0.1 具有 32 字节的数据:
来自 10.8.0.1 的回复: 字节=32 时间=30ms TTL=63
来自 10.8.0.1 的回复: 字节=32 时间=30ms TTL=63
来自 10.8.0.1 的回复: 字节=32 时间=30ms TTL=63

10.8.0.1 的 Ping 统计信息:
数据包: 已发送 = 3,已接收 = 3,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 30ms,最长 = 30ms,平均 = 30ms

说明这两个节点已经打通了, 进入服务端dockerping一下该网络的私有网段:

1
2
3
4
5
6
7
8
9
root@4c48dccf0de6:/# ping 192.168.125.1 -c 3
PING 192.168.125.1 (192.168.125.1) 56(84) bytes of data.
64 bytes from 192.168.125.1: icmp_seq=1 ttl=64 time=32.3 ms
64 bytes from 192.168.125.1: icmp_seq=2 ttl=64 time=31.3 ms
64 bytes from 192.168.125.1: icmp_seq=3 ttl=64 time=31.7 ms

--- 192.168.125.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 31.276/31.747/32.255/0.400 ms

如果通常表示该节点部署完全ok, 如果发现客户端ping不通服务端代理节点的虚拟ip, 那么可能有如下原因:

  • wg0接口中对端允许ip没有配对
  • 配置修改了但是没有重启路由器,配置未生效
  • 云端代理节点中虚拟ip和本地没有对应上
    具体按照上述操作自行检查

如果客户端节点可以ping通服务端代理节点, 但是反之不行, 那么请检查服务端代理节点中关于客户端节点的Allowip是否正确。如果互通都是ok,在windown下可以使用tracert工具, linux下使用traceroute工具跟踪一下转发是否按照预期,如果全部ok,那么恭喜你,该节点已经完全部署ok了,可以进行下一个节点的部署。


参考资料


使用wireguard组虚拟局域网
http://116.205.174.47/2024/09/08/openwrt/wireguard/213000/
作者
EtcFly
发布于
2024年9月8日
更新于
2024年11月4日
许可协议