Posted in: PC/macOS

微型 VPN

起源

作为一个(贫穷的)润人,生活在没有墙的地区,为什么还要用 VPN 呢?这才是 VPN 的本意:虚拟局域网,目标一定是少数网址。例如第一种情况:远程访问家里的 NAS 资源,则目标就是家庭的局域网 IP。此时需要在家庭的设备上搭建服务。

第二种情况是远程访问单位的内网资源,此时需要在单位的设备上搭建服务。由于单位的设备管控比家庭更加严格一些,所以就需要动动脑筋。

无论是哪种模式,因为目标网址都很少,所以在规则判断上比较简单,这与东方某大陆把物理因特网变成物理局域网,迫使程序员把虚拟局域网改造成虚拟因特网的情况截然不同。

现状

单位提供官方的 VPN 客户端,但使用起来不太方便。单位还有一台性能不错的服务器仅供我一人使用,但是只能暴露80、443 端口和一个 SSH 端口。除此之外不能暴露别的端口。

放弃 WireGuard

开始的设想是:因为访问家庭资源用 WireGuard,那么在单位的服务器上也搭建一个 WireGuard 服务器,然后自己设备上用 WireGuard 客户端就能一举两用了。但是仅有的三个端口已经全部使用完毕,不能暴露别的端口,就无法直接搭建 WireGuard 服务。另外也不能使用 cloudflared 来曲线救国,因为 WireGuard 是使用 UDP 的,与 cloudflared 的 TCP 不太合得来,而且 QUIC 流量通过单位的防火墙时有问题。

SOCKS 5 代理

因为访问单位内网仅仅是一些很轻量的数据浏览,ChatGPT 给出的方案是 SOCKS 5 代理(没错,在润之前也经常听过这个词)。

首先在自己电脑上(以我的 macOS 为例)的终端运行:

ssh -D 1080 -C -q -N [email protected]

这时就创建了一个微型 VPN:地址是 localhost 即 127.0.0.1,端口号是 1080。

由于我平时使用 Safari 浏览器,没有专门的扩展来给浏览器自己设置代理,而是需要在系统网络里面设置。首先我设置了全局代理,如右图所示。设置之后测试成功。

但因为并不需要全局代理,只是针对少数几个网址进行代理,ChatGPT 给出了 PAC 方案。即写一个名字叫做 proxy.pac 的文件,代码如下:

macOS 设置全局代理的方法
function FindProxyForURL(url, host) {
    if (shExpMatch(host, "*.example.com") || shExpMatch(host, "another-site.com")) {
        return "SOCKS5 127.0.0.1:1080";
    }
    return "DIRECT";
}

然后把文件地址 file:///path/to/proxy.pac 填入设置区域即可。(当然需要把之前测试用的全局代理取消)

以上是 ChatGPT 宣称的。然而填入之后发现完全没有任何效果,说明要么是 PAC 文件有问题,要么是 URL 填写有问题。

到此为止 ChatGPT 就无法进一步解释了,开始胡说八道了。最后是自己去网上搜到的两个坑。

macOS 设置 PAC 的方法

小坑:macOS 已经不再支持填写本地的 PAC 文件

这个在好几年前就是这样了(file:/// 无效),ChatGPT 却不知道。于是我用

python3 -m http.server 8000

搞一个本地 HTTP 服务器。但还是不行。

大坑:macOS/Safari 不认 SOCKS5 语法

要把 SOCKS5 127.0.0.1:1080 这句话里面的 5 去掉,变成 SOCKS 127.0.0.1:1080。这时就可以用了。

转移二线

这么一搞问题变复杂了,这意味着电脑上需要跑两个背景进程,一个是 ssh 的 SOCKS 服务器进程,一个是 python 的微型 http 服务器进程。可是我的是 macbook 笔记本电脑平时用完就合上盖子,此时系统进入睡眠状态,这些网络进程一定会断掉。每次都要重新开启太麻烦了。于是我就想把两个进程转移到 VPS 上。

在 VPS 上设置好这两个进程之后,首先仍然在电脑上测试一下全局代理(把所有 127.0.0.1 换成 VPS 的 IP)。傻眼了,所有的网站都上不去了,说明 SOCKS 服务设置不对。

再次询问 ChatGPT,这回没有胡说八道:ssh -D 默认只认本地的 SOCKS,想要让它侦听远程来源的 SOCKS 访问请求,需要给 SOCKS 命令加上 0.0.0.0,即 ssh -D 0.0.0.0:1080,此时就可以侦听远程来源的 SOCKS 访问请求。

设置之后,再测试全局代理成功。然后 VPS 本身有标准的 HTTP 服务,托管 proxy.pac 文件,把 URL 填入系统设置里面。测试成功。

转移三线

VPS 对外是公网 IPv4 的地址,如果被黑客扫到 SOCKS5 代理的端口号,那问题会非常严重,他们只需要用 IP + 端口号就可以无限制利用我的微型 VPN,不需要任何验证。

虽然 SOCKS5 代理也有用户名和密码验证机制,但是比较麻烦。所以我决定转移三线:把 VPS 换成我的 OpenWRT 路由器!

在 OpenWRT 上运行 ssh -D 0.0.0.0:1080 ….. 之类的命令,PAC文件则使用 OpenWRT 内置的 uhttpd 来进行托管。由于路由器在内网,虽然也写成了 0.0.0.0,但实际上只有自己能够访问,外面的人无法访问。如果自己不在家里而是在外面,则用 WireGuard 翻回家里即可。

黑客攻破 WireGuard 密钥的概率基本为0,这下子应该安全了。

二线 + 三线

虽然 PAC 文件是在当前某个 Wi-Fi 的菜单里面点进去设置的,但是它对所有 Wi-Fi 都是默认生效的,和我预期的不同。因此在外面网络环境下,需要一直连着 WireGuard 才行,否则系统无法从内网 IP 获取 PAC 文件,就不能正常上网。这也太浪费了吧!我只是偶尔用到这个 VPN 而已,就要一直开着 WireGuard?

于是就想出了 二线 + 三线的策略:PAC 文件放在 VPS 上,采用 https://mydomain.com/proxy.pac 的 URL,填入 macOS 系统的网络设置里面。而 proxy.pac 的文件的 SOCKS 代理地址则写路由器的内网地址。这样子就算是即方便又安全了。无论是在家里还是在外面,PAC 文件都能访问到,因此不影响正常上网。需要访问 VPN 时,就连上 WireGuard 进入家庭局域网,即可连接 SOCKS 代理。

Comments (2) on "微型 VPN"

  1. Google Chrome 134.0.0.0 Android 10

    我比较懒,一般用clash,tun模式接管系统所有流量,使用规则覆写,对指定ip段和域名使用代理。 😀 😆
    性能也降低不了多少,基本无感。但是省去劳心费神的时间。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注