使用VPN组建局域网打通工作和家庭网络

本教程已经失效,只能作为参考,关于我最新的组网方法请参考这篇文章:Tailscale Intro

写在前面

没错,我又开始写教程了。非常排斥写教程的原因是:

  1. 之前写太多了
  2. 多数教程都是对Google来的内容的提纯和综合,拼凑而成的四不像而已
  3. 这种劳动并不会创造实质性的价值(只有可能会给别人减少一定找到正确答案的时间成本吧) 但是最近开始重新思考,发现可能问题并不是在写教程这件事情上,或者换句话说其实写教程没什么错的,但是不能只把眼光放在解决一个问题上面,转而应该对一类问题/事务进行总结,这样可能才能把多个零散的事情串联起来。

正文

最近结束了长达6个月的WFH以及1个多月的感染新冠居家,正式开始去外面打工了。公司的IT设施并没有很完善,权限管理也比较松,并没有提供一个公网能够访问公司内网的VPN,但我个人有一台常用的电脑(出门都带着),公司电脑我会放在公司做远程紧急解决问题使用,因此出于这个需求我得自己搭建一套内网穿透的方案。

其实这个问题之前以及解决过很多次了,无外乎frp为代表的内网传统工具、zerotier为代表的异地组网方案或者以team viewer为代表的外部解决方案。这些方案的共通点是都可以解决我远程的需要,以及都是在对端电脑无法获取公网IP或者是无法配置端口转发/DMZ的情况下的无奈之举。 但Frp的问题在于配置麻烦,且端口转发需要单独配置具体的端口还是不方便; zerotier是虚拟组网,但是在国内planet节点都被屏蔽了,UDP也被ISP限制,自己也需要搭建Moon节点才能完成比较舒服的访问速度,虽然支持各种高级的玩法也有界面可以直接管理,各个平台都有支持但我会比较介意:

  1. 商业软件没有开源,也许哪天就收费了或者改免费计划的配额了
  2. 虽然提供了各种NAT打洞的能力和真P2P的网络体验,但是真的太复杂了,很容易在折腾过程中搞坏原先的网络,且不好排查问题 而team viewer的问题就更加明显了,商业化软件,不加鸡腿就限速控制体验,且之前有过安全问题;而同类型的Any Desk、国内也有仿冒的ToDesk的问题基本上要么是访问速度贼慢(两台Mac之间屏幕共享控制明显卡顿),要么就是各种快捷键映射有问题为代表的小问题,且无法得到有效解决。 使用下来会发现还是mac原生的屏幕共享程序互相连接下控制是最为流畅的(虽然使用的是5900端口但其实协议是苹果自研的或者可能基于VNC改良的,虽然比不上微软黑科技RDP但也不遑多让),因此还是考虑直接做组网,这样开放端口可以自己控制,也能保证LAN中设备的安全性。

本来准备尝试Tinc这个老牌的VPN,这边是个不错的教程。但我走到最后发现mac已经废弃了tuntap组件,因此在mac上安装tinc变成了伪命题,于是继续调研的情况下发现了wireguard(早有耳闻,在搞ipv6的时候就有用到cloudflare的warp,就是基于wireguard来实现的),就决定尝一下螃蟹,起码社区非常活跃、代码提交也很频繁,不像tinc最后一次代码更改还是22年6月了。

经过规划之后,我的网段的划分如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
                                     +------------------------------+
                                     |           Work               |
                                     |    +---------------------+   |
                                     |    |     Macbook Air     |   |
                                     |    |                     |   |
                                     |    |    172.30.0.3 wg    |   |
                                     |    |                     |   |
                                     |    |    192.168.1.X eth0 |   |
                                     |    |                     |   |
                                     |    |                     |   |
                                     |    +---------------------+   |
                                     |                              |
                                     |                              |
                                     |                              |
                                     |                              |
                                     +------------+-----------------+
                                                  |
+-------------------------------+       +---------+---------+      +----------------------------+
|            Home               |       |                   |      |        Portable            |
|     172.30.0.0/24             |       |  tencent cloud    |      |                            |
|                               |       |                   |      |   +---------------------+  |
|    +-----------------+        |       |       wg          |      |   |   Macbook pro       |  |
|    |    Jumper       |        |       |                   |      |   |                     |  |
|    |                 |        +-------+                   +------+   |  172.30.0.2 wg      |  |
|    |  172.30.0.4 wg  |        |       |     172.30.0.1    |      |   |                     |  |
|    |                 |        |       |                   |      |   |  192.168.2.X/24     |  |
|    |                 |        |       +---------+---------+      |   |                     |  |
|    |                 |        |                 |                |   |  10.0.0.X/24        |  |
|    |                 |        |                 |                |   +---------------------+  |
|    +--------+--------+        |                 |                |                            |
|             |                 |                 |                |   +---------------------+  |
|             |                 |       +---------+----------+     |   |     Other           |  |
|    +--------+---------+       |       |                    |     |   |                     |  |
|    |    Other         |       |       |      VPN           |     |   |  172.30.0.X wg      |  |
|    |                  |       |       |                    |     |   |                     |  |
|    |   192.168.2.X    |       |       |     172.30.0.0/24  |     |   |                     |  |
|    |                  |       |       |                    |     |   |                     |  |
|    |   LAN            |       |       |                    |     |   |                     |  |
|    +------------------+       |       |                    |     |   +---------------------+  |
|                               |       |                    |     |                            |
+-------------------------------+       +--------------------+     +----------------------------+

其实结构很简单,所有的机器流量都通过腾讯云的轻量云服务器(有公网IP)进行转发,以此来联通工作、家庭、携带设备的网络。满足这个需求的配置可以参考下面的教程: 使用 WireGuard 无缝接入内网

关于具体的步骤不进行赘述,只是需要注意一下公网的服务器检查一下云厂商的防火墙是否放行(wireguard是UDP),服务器、局域网转发服务器(如果有和我同样的需求)的iptables是否放行,服务器是否开启iv4的转发。 这边仅贴出我的配置:

公网服务器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
[Interface]
# Name = qcloud
Address = 172.30.0.1/24
ListenPort = 31820
PrivateKey = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789

[Peer]
#Name = macbookpro
PublicKey = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
AllowedIPs = 172.30.0.2/32

[Peer]
#Name = macbookair
PublicKey = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
AllowedIPs = 172.30.0.3/32

[Peer]
#Name = debian.lan
PublicKey = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
AllowedIPs = 172.30.0.4/32
AllowedIPs = 192.168.2.1/24

内网转发机

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[Interface]
PrivateKey = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
Address = 172.30.0.4/32
ListenPort = 31820

PostUp = iptables -t nat -A POSTROUTING -s 172.30.0.0/24 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 172.30.0.0/24 -j MASQUERADE

[Peer]
PublicKey = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
AllowedIPs = 172.30.0.0/24
Endpoint = 101.43.1.1:31820
PersistentKeepalive = 25

其他机器,以携带行型设备为例

1
2
3
4
5
6
7
8
9
[Interface]
PrivateKey = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
Address = 172.30.0.2/32

[Peer]
PublicKey = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
AllowedIPs = 172.30.0.0/24
AllowedIPs = 192.168.2.0/24
Endpoint = 101.43.1.1:31820

值得一提的是在Jumper机上需要添加两条iptables的规则:

1
2
PostUp = iptables -t nat -A POSTROUTING -s 172.30.0.0/24 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 172.30.0.0/24 -j MASQUERADE

PostUp表示为在wg0的虚拟网卡上线、添加完路由之后会自动执行的hook,PostDown则是wg0虚拟网卡下线移除完路由的时候自动执行的hook,这台机器的主要作用是对于172.30.0.0/24的网段的流量(转发到了这台机器),把流量转发到这台机器的网卡上,然后转交到对应的dest上。如果没有这个规则的化流量转发到目标机器上之后无法找到回程的IP(比如网关192.168.2.1并不知道172.30.0.0/24具体是在什么位置,所以在包从Jumper机发出之前需要通过SNAT把source IP转换成本机的局域网IP。MASQUERADE等于-j SNAT --to-source 192.168.2.5,也就是会自动获取网卡的IP然后设置,也比较适合只有动态IP或者做了DDNS的机器。如果有多个网卡也可以用 -o eth0 指定出口网卡。关于SNAT和DNAT可以看这个文章。同时也强烈推荐这个系列的教程1,对于会有全新的理解。

但这样的方案也是有缺陷的,如果这样一台电脑进入到了我的局域网,192.168.2.0/24的流量还会去公网上绕一圈回来在jumper上再转发一次,其实并不是很好的做法(因此这个规则其实比较适合公司的电脑(因为大多数情况下不会带回家)),而公司想要访问例如openwrt进行管理(http://192.168.2.1,例如远程帮家人调整翻墙的节点)就可以通过网址直接访问即可。

思考和改进

可以发现,wireguard并不适合大规模的组网,因为配置起来太过于麻烦(尤其是不做公网IP的服务器作为流量中转的情况下,每新增一个peer之前的服务器都得再配置一次),也不支持NAT打洞,更加不支持自适应的流量转发、多节点作为流量中转的场景,要实现这些能力还是得看zerotier(可能tailscale也可以做到,但是我并没有做调研)。不过考虑到自己的需求也非常有限,就继续保持这套方案跑着了,结构简单也好维护。

而我的家庭网络是有公网IP的,所以也有在思考也许可以携带区的电脑、工作区的电脑可以直接和Jumper P2P相连(Jumper的Endpoint通过openwrt的端口转发暴露在公网上),以此来实现绕过流量中转服务器(毕竟有上限,比如我的是4M上行),但是这样就意味着Jumper机需要对特定的IP路由到特定的Peer,而网段中其他的IP则维持路由到中转服务器上。从方案上来讲看起来是可以操作的, 不过并没有实际去操作,也许会等实际需求产生的时候会再折腾。

2023.01.26 更新

实际测试下来mac的桌面共享如果走这一套转发打洞方案基本是可行的,偶有卡顿但基本以及可用了。但不折腾会死的我还是选择继续优化看看,能不能更进一步地得到更好的体验。 通过观察我上面提供的配置可以发现之前的解决方案是星型的,也就是qcloud机器上面配置了所有的机器peer,其他端点的机器都只配置一个 AllowedIPs = 172.30.0.0/24 到这台机器上,也就是说不论是172.30.0/24 还是192.168.2/24 的流量都会经过 qcloud 这台机器的中转,然后只是转发到对应的机器上或是再转发到debian.lan机器上再做一次局域网内部的转发。那么很容易想到再做一次网状的网络调整,让macbookair这台机器上配置debian.lan这个机器作为额外的peer,endpoint为家庭公网地址和对应的转发端口,把AllowedIPs = 192.168.2.0/24的配置从qcloud peer的配置移到这边,在debian.lan机器上添加macbookair这台机器作为peer即可完成在中转的同时有一根直连的线路。

实际尝试下来发现会存在一些问题,最大的问题在于如果配置了两个peer却对应了不同的endpoint,wireguard存在一些机制(可能是内置漫游)2,但具体的机制并不能很快的了解到,这边仅做一下提醒,带来的现象就是即便配置文件中两个peer配置的是不同的endpoint,在连接后两个peer会对应到同一个endpoint,且有时是qcloud有时是debian.lan。都变成前面一个之后就会导致192.168.2.0/24的网段无法正常访问;如果是都变成后面一个那么就会导致172.30.0.0/24中只有debian.lan这台机器可以被访问到,但哪种情况都不是我所希望达到的最后的效果。

思考

合理猜测可能是无法在有中继服务器的情况下同时使用这个网段中的两个IP作为P2P连接的两端,在查阅了很多资料却还是无法得到我想要的答案之后,我退了一步选择了再单独配置一个新的网段,也就是说,我新建了一个 wg1.conf 文件,对应了新的网段 172.29.0.0/24debian.lan 作为服务器,macbookair作为客户端,连接家庭网络的公网地址(及对应的转发端口,且配置家庭网段192.168.2.0/24在这套虚拟网络的AllowedIPs中)即可解决两个网段互不影响正常访问的目的。虽然很丑陋,但确实能解决问题。直接连接家庭网络中的机器作为中转后,远程桌面的体验明显得到提升,响应速度肉眼可见的提升了(顺滑了很多,也少了很多卡顿),总算达到了我预期的效果。暂时会先使用这个方案,等到后面对wireguard有了更深的了解或是发现了新的解决办法之后,会再次尝试优化,本次就到这了。

可能有人会问为什么不能直接端口转发到家庭网络的mac上,直接通过公网ip和远程桌面端口进行访问,一样能达到远程访问的效果?没错,这样确实也能解决我的需求,但我考虑三个点:

  1. 不想固定家中的mac的IP地址(不然DHCP变化后就端口转发就失效了,要么固定要么到时候再想办法改端口转发)
  2. 不想暴露VNC/SSH端口到公网上,存在比较明显的特征容易被爆破
  3. 如果我需要访问家里的路由器/NAS,我会希望公司电脑的浏览器上能直接访问,而非再套一层VNC
Built with ❤️ by @d0zingcat
使用 Hugo 构建
主题 StackJimmy 设计