扔台 VPS 给 AI,让它帮我搭梯子
开发者深夜配置代理服务器
我用了好几年商业 VPN,越用越觉得别扭。别扭的点很简单:你所有流量都过别人的服务器,对方是谁、数据怎么处理,你完全不知道,全凭信任。反正做了这么多服务端的活,自己搭一套按道理不难,就一直想找机会自己弄。
具体做法大概是这样的:先租一台 VPS,我用的 Atlas Networks,洛杉矶,9929 线路,静态住宅 IP。然后把 SSH 凭据直接扔给 claude code,跟它说:帮我搭一套完整的代理服务,我自己用,也能分享给朋友用。
后面的过程有几个地方挺出乎我意料的。
shadowsocks 四个小时就被封了
claude code 第一步部署的是 shadowsocks。很好理解,成熟方案,默认选择。
结果四个小时之后 IP 就被封了。不是限速那种,是整个 IP 直接封掉,流量全断。我去问服务商,确认了是主动封锁。
这里可以顺便讲一下 GFW 到底是怎么检测的,大家好像都以为它就是个黑名单吧?其实早就不是了,它现在是一套主动探测系统。它看到你的流量特征不符合任何已知协议,就会主动去探你的服务器——发一些异常报文过去,看你怎么响应,测你的响应模式。shadowsocks 早年确实很难被识别,但 GFW 对着它已经训练了很多年了。2025 年你拿一个新 IP 去部署 shadowsocks,基本等于举个牌子告诉它「来探我」。
而且问题不在加密本身,GFW 到今天也读不了你的内容。问题在流量指纹:高熵的密文、非标准的握手、响应模式一看就是代理行为,这几条 shadowsocks 全中。也就是说它不需要知道你在传什么,光看你的流量长什么样就够了。
GFW 不靠黑名单,而是看到可疑流量指纹后主动探测你的服务器,模式吻合就封 IP
行吧,换台 VPS,换个思路。
换成 reality
新方案是 sing-box + VLESS-Reality。
claude code 给我解释 reality 原理的时候,我觉得这个设计是真的聪明。它不是让你的流量看起来像什么都没有——前面说了,「看起来像什么都没有」这件事本身就是特征。它是让你的流量看起来像在访问一个真实的大网站,直接借用那个网站的 TLS 指纹,你的握手和一个普通浏览器访问 microsoft.com 一模一样。这样一来 GFW 想封你,就得连 microsoft.com 一起封了,它不会为了你去封微软,你的流量就跟着放过去了。
伪装成空白反而暴露被封;Reality 借用大网站的 TLS 指纹伪装成访问 microsoft.com,GFW 不敢连微软一起封,只能放行
reality 之外还部署了三个备用协议。Hysteria2 和 TUIC-v5 都是基于 QUIC 的 UDP 协议,速度快,但比较吃网络质量;Vmess-WS 走 WebSocket,最弱,纯兜底。四个协议四个端口,防火墙只开这几个口,其他全关。
Clash Verge 的配置里,自动选择分组只放了 reality 一个,其他三个协议在底层备着,不参与日常路由。reality 能用就永远走 reality。
证书踩的坑
协议定下来之后,claude code 基本就是一路往下推了。
SSL 证书用的 acme.sh + Cloudflare DNS API 验证。这个方式的好处是不用开 80 端口:给 acme.sh 一个只有 DNS 编辑权限的 Cloudflare API token,它去创建一条 TXT 记录验证域名所有权,验完自动清掉。很干净,服务器不用为了验证暴露额外端口。
中间踩了一个坑。sing-box 的一键脚本在内部跑过一次 acme.sh,把域名存进了邮箱字段的缓存里。后来单独给订阅服务器申请证书的时候,acme.sh 把那份缓存复用了,Let's Encrypt 收到的请求里邮箱字段是个域名格式,直接拒绝。错误信息还挺绕的,来回三次才定位到,最后是删掉 CA 缓存目录,带上 --accountemail 重新跑,才过。
剩下的防火墙、BBR 加速、服务开机自启这些,claude code 一并处理掉了,基本不用我介入。
订阅服务器
这部分我自己是比较满意的。
很多自建代理方案到这一步,就是给你生成一个 base64 字符串,或者一个 QR code,你手动导进客户端完事。我想要更完整一点的东西:一个真正的订阅 URL,客户端能读到流量统计。Clash Verge 支持一个叫 Subscription-Userinfo 的响应头,读到之后会渲染一个流量条——已用多少、剩余多少、什么时候到期。就这么一个细节,整套服务看起来就是完整的,不像拼凑出来的。
claude code 搭了一个 Python 服务跑在 nginx 后面:nginx 处理 443 端口的 TLS,把请求代理到本机 8089。Python 服务读订阅配置文件,同时调 vnstat --json 拿 VPS 真实的上下行数据,动态生成响应头,格式是 upload=X; download=Y; total=Z; expire=T。Clash Verge 拿到就自动渲染,客户端什么都不用配。token 是一段随机十六位 hex,存在服务器上,订阅 URL 就是 https://your.domain.com/{token}。
订阅请求经 nginx 443 转到本机 Python 服务,Python 调 vnstat 拿真实上下行数据,动态写进响应头,客户端据此渲染流量条
中间有个小插曲:最开始 Python 服务没处理 HEAD 请求,Clash Verge 恰好就是用 HEAD 去拿 header 的,服务直接报错。加上 do_HEAD 方法就好了。这种问题不真跑一遍是碰不上的。
最后朋友那边看到的就是一个流量条:已用多少、3TB 月限额还剩多少、哪天到期,跟商业服务没什么区别。Clash Verge 是粘贴 URL、点导入、激活配置、开 TUN 模式;iOS 上 Shadowrocket 直接把 URL 添加成订阅,或者扫 QR code 也行。
它是怎么处理失败的
这套东西怎么处理失败,我想单独讲一下。
证书因为缓存问题连着申请失败三次,它没有反复执行同一条命令,而是去查 acme.sh 的状态,找到那份坏缓存,清掉,重跑。nginx 的 proxy 配置有时候传 header 有时候不传,它就把整个链路走一遍,逐层确认每个环节在传什么、缺了什么。每次失败大概花十到十五分钟,它不绕开,一直查到找出真正的原因。
Clash Verge 本身的行为算一个例外。它重启的时候会删掉手动编辑的配置文件,只保留通过订阅 URL 导入的。这是客户端特有的行为,claude code 不知道,最后是我们一起测试测出来的。
所以这里的界限大概是这样:有明确验证标准的任务——比如「这个 URL 应该返回包含 proxies: 字段的 YAML」——它自己调试起来很干净,可以一直循环到通为止。客户端那种比较特殊、没法自动验证的行为,就得人去看去判断。这个分工分清楚了,效率就挺高的。
反正一个下午,一套自己托管的代理服务就出来了,朋友发个链接就能用。
