部署 Trojan-Go + WS + Cloudflare 时遇到的坑

前言

在 2022 年 9 月 30 日和 10 月 03 日,某墙发威。大量使用基于 TLS 的翻墙工具的服务器都遭到封锁。相关消息网上能搜到很多,我就不赘述了。

我的服务器不知道啥时候也被封了,但我好几天之后才发现。我本以为只是网络或服务器不稳定,再加上我还有很多机场,平时都是 Clash 无感翻墙。直到一次需要连接服务器 SSH 时才发现服务器连不上了,联系到最近墙发威的消息我尝试翻墙连接,能连上,就确定是被墙了。

之后我就想着给服务器上点高级的技术手段,网上一番查找,最后确定用 Trojan-Go。将搭建过程中遇到的各种问题总结成这篇文章。

本文不面向纯纯的小白,不会教你用啥一键脚本面板之类的。

正文

首先下载 Trojan-Go 可执行文件的位置要注意,放到 /usr/local/bin 方便之后直接套官方的 trojan-go.service Systemd 配置。
然后配置文件放到 /etc/trojan-go/config.json 同理

SSL 证书

Trojan 基于 TLS 加密,需要像部署 HTTPS 网站一样申请一个 SSL 证书

如果你只想用 Cloudflare,这时候就可以先去 Cloudflare 用自己的域名创建站点了,直接生成一个源服务器证书并放到 /etc/trojan-go/cert.pem 之类的位置。但我一开始是没想用 CDN 的,所以先弄个子域 DNS 记录添加你的服务器,一般 A 记录,服务器是 DDNS 就 CNAME。然后用 certbot 生成免费 Let’s Encrypt 的证书。certbot 申请也是 Let’s Encrypt 官方推荐的,设置好后会自动更新。

其实现在申请证书已经很简单了,照着官网装好 certbot 之后直接运行 certbot certonly 就行,certonly 是让 certbot 不去尝试自动修改 nginx 之类的配置文件。

中间提示你选 standalone 还是 webroot,就是让你选验证方式。standalone 是让 certbot 自己开一个 web 服务,webroot 是让你指定一个目录,certbot 会在这个目录下放一个验证文件,然后让 Let’s Encrypt 的服务器去访问这个文件来验证你的域名。

如果失败就看错误提示,可能是端口被占用,或者服务器 80 端口没开。申请时需要一个文件验证你对域名的所有权,所以要开 80。

生成的证书在 /etc/letsencrypt/live/[域名]/[fullchain.pem/privkey.pem] 下。这里有第一个坑,导致后面问题一直排除不出,当时我甚至以为是 Trojan 问题。
/etc 目录默认是需要 root 的,所以直接用就 permission denied。图省事一般就 chmod 755 /etc/letsencrypt,虽然不是很安全,但是我只是自己用,就这样了。

配置文件

配置文件其实反而是最简单的,照着示例改就行了,主要是改密码和证书路径,还有把绕过中国的部分删了。完整文档

remote_addrremote_port 需要你服务器开个 HTTP 的 Web 服务。如果你不想用真的 Nginx,也可以用 Python 的 Flask 之类的搭个简单的站点。

其中 sni 就填你申请了证书的域名,不填默认用 remote_addr。端口就默认的 443,这也是 HTTPS 的端口,不要瞎几把改,除非你知道你在做什么。证书路径就是 cert 的路径,上文有写,后缀/扩展名和示例不一样不用管,pem 就可以的,里面本质就是一串字符串,扩展名改成啥都行。

我一开始先没配置 WebSocket 部分,这边也建议先尝试成功了再改。

Systemd 配置

systemd 是 linux 的一个进程管理工具,能在失去 ssh 连接后仍保持进程运行,还能开机自启查看日志之类的。

你会发现官方的 systemd 配置文件模板有两个,trojan-go.servicetrojan-go@.service,其中带 @ 的把 ExecStart 命令中配置文件的名字换成了 %i。这是 systemd 的特性,可以很方便的管理多个配置文件。如 trojan-go@aaa 即使用 aaa.json 作为配置文件。但一般个人用不上就不用管了,只用不带 @ 的。放到 /etc/systemd/system/trojan-go.service 或者相应位置。

另外这里你还会发现官方模板里可执行文件和配置文件的位置是在 /usr/bin/trojan-go/etc/trojan-go/config.json,注意把文件放到对应位置或者改下。

还有配置文件中 User=nobody 其实是不安全的,现在一般建议改成 DynamicUser=true

添加好就可以 systemctl start trojan-go 了,用 systemctl status trojan-go 查看状态,journalctl -u trojan-go 查看完整日志。如果一切顺利就可以用你喜欢的客户端连了。这里附上 Clash Meta 的文档。日志正常但连不上还是注意看下服务器 443 端口开没开。注意 server 或者其它客户端对应字段要填你的域名,不能是 IP 或 DDNS 域名,除非你后续不想用 Cloudflare。

这里的坑只要你照着上面的步骤一步步来就不会遇到,但我还是讲下。

1
2
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE

配置文件里上面这些东西是在给进程授予 CAP_NET_ADMINCAP_NET_BIND_SERVICE 特权,并剔除掉除了这两个之外的其它特权。

但我一开始看到这篇文章,因为他表达的不是很清楚,以为一个是给予一个是拒绝互相冲突,所以就把 CapabilityBoundingSet 删了。结果发现真启动了,我就认定了CapabilityBoundingSet 是剔除掉设置的特权。但实际上这里因为 CapabilityBoundingSet 把 root 访问前述 /etc/letsencrypt 目录的权限给剔除了,即使你设了 User=root 也没法访问。我把这个删了,自然也就允许 root 访问了。我之后尝试不把用户设成 root,结果失败了,我当时也没仔细看过日志。

总之,记住 CapabilityBoundingSet剔除除了设置之外的特权,AmbientCapabilities 是给予设置的特权。

WebSocket

是时候加上 WebSocket 了,然后才能用 CDN 转发。配置文件也参考文档加。

其中 host 就填你的域名,不是 IP 什么的,同前文也不能是 DDNS 域名。其它的都没什么问题。

加完 systemctl restart trojan-go 重启,然后在客户端里也加上相应配置,host 部分也填对应域名。检查一下,没问题就能上 CDN 了。

Cloudflare

你不想用 Cloudflare 其实可以跳过这一步的,不受任何影响。如果你的服务器网络非常非常垃圾或者想要安全一点可以用。

CDN 是内容分发网络,具体可以 Bing 或看我之前的文章

实际上这里也可以选用其它国内的 CDN,还能起到一定中转加速作用,只要注意加密,CDN 服务商也是没法分析流量的。比如百度云加速,但百度云加速前几年因为政策已经不支持 WebSocket 了,其它国内的 CDN 支持 WebSocket 的都收费。还有一点国内 CDN 都要求备案的域名,不过我博客域名已经备案了

打开 Cloudflare 用域名创建站点,然后导入之前的 DNS 记录。注意 Cloudflare 自动扫的很可能不全或根本没有,可以自己从之前的 DNS 服务商导出 zone 文件或者自己手动改过去。还有服务器的子域要勾上小云朵,其它如果有之前的记录就看情况随意。勾上小云朵就是开启 CDN 中转,否则只用 Cloudflare 的 DNS 服务。之前添加时把域名的 NS 解析交给 Cloudflare 你就已经在用 Cloudflare 的 DNS 了,Cloudflare 一般不能只用 CDN 而不用 DNS。(也有办法但不在这篇文章的讨论范围内了)各种设置都看情况开关,强制 HTTPS 之类的一般都不影响 Trojan 正常使用。

添加完站点注意把 SSL/TLS 设置成 完全(严格),这样才能让 Cloudflare 请求源站时也采用 443 端口,从而把 Trojan 的流量转发。

然后只要确保你客户端所有域名都没问题就行了。要验证可以 ping 一下你的域名,看是不是 Cloudflare 的 IP。

Cloudflare 的 CDN 虽然很不错,但有个缺点它虽然在国外都快的飞起,但它没有国内节点(或者要 Enterprise Plan),而且国内连它特别特别慢,许多人称 Cloudflare 为减速 CDN,事实也确实如此。但 Cloudflare 的 IP 真的非常非常多,总有那么几个快的 IP,有一些项目比如 CloudflareSpeedTest,可以自动测对你来讲你最快的 IP,然后就可以在客户端里把主机改成这个 IP,这样就能快很多。

另外这里要注意,不用在意 IP 的地区,因为 Cloudflare 的 IP 并不是确定的某一台节点或数据中心,每个 IP 的节点都是会根据情况自动调整的,这个过程你改变不了。你可以访问 https://[IP]/cdn-cgi/trace 查看这个 IP 当前的位置。

然后该干什么

Cloudflare 部分是可选的,你的网络环境差 Cloudflare 可能会让节点更慢,上文的 CloudflareSpeedTest 也只能是缓解。你可以尝试对比直接连服务器 IP 和连 Cloudflare 的速度,看看慢的能不能接受,还有稳定程度等。如果你确定要用 Cloudflare,那么你可以申请一个十五年的免费 Cloudflare 源服务器证书,然后 Trojan-Go 的证书改成这个。当然这个证书是有限制的,只能用于 Cloudflare 连你服务器,如果你不要用 Cloudflare 就还是要用 Let’s Encrypt 的。

或者如果你不想用 Cloudflare。那么要注意如果你服务器的伪装 Web 服务开在 80 端口,那么会导致 certbot 没法自动续签,因为如上文,certbot 的 standalone 模式就是开设一个临时的验证 HTTP Web 服务,如果你的服务开在 80 就会占用。可以把服务改在 8080 之类的。

想要再进阶一点可以参考 Trojan-Go 高级配置文档

严正声明:本人并不知道 Trojan 之类的是什么东西,以上内容都是在一个地上捡的 U 盘里找到的