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 (8) on "微型 VPN"

  1. Google Chrome 133.0.0.0 Windows 10 x64 Edition

    用gost更方便点
    另外问一句日本的家宽会对udp qos吗,就像墙内那样,wg一跑大流量就给限速

  2. Google Chrome 134.0.0.0 Android 10

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

      1. Google Chrome 136.0.0.0 Windows 10 x64 Edition

        您好
        刚刚看到您的邮件,很抱歉这么久才回复您.
        由于工作变动和网站迁移的原因,已经弃用原先的wordpress架构.当前网站主要存储静态文件,也许有时间会再次恢复博客.
        原有博客内容在https://web.archive.org/web/20241101000000*/gouuuu.com有部分存储,对此深感遗憾.
        如果有必要,您或其他有兴趣的人士也可以通过邮件[email protected],获取之前的网页文件(markdown格式).
        祝您生活愉快.

发表回复

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