本文最后更新于 2024 年 2 月 25 日
本文以 Debian 12 为例,介绍如何搭建 trojan-go + WebSocket 服务端,使用 Nginx 建立 Web,并利用 CloudFlare 隐藏源站 IP,最后说明对应的客户端配置文件的格式。本文同样完全适用于 Ubuntu 22.04 系统。
注:请先参照 Debian & Ubuntu 服务器的初始化配置 一文对服务器进行各种必要的配置。本文以 sammy
用户为例,进行 trojan-go 的部署,并默认已按初始化配置文章对服务器进行了配置。
准备工作
服务器与域名
- 可用的公网 IP 服务器(例如在 BandwagonHost、Vultr 等处购买的 VPS)
- 注册一个域名,本文以
example.com
为例
内容准备
- 起一个随机的路径名,本文使用
/random
- 准备自定义的 Web 页面,用于浏览器正常访问
example.com
显示的网页 - 准备自定义的 404 页面(可选)
CloudFlare 设置
- 将域名的 Namesever 指向 CloudFlare 所提供的地址,等待生效
- NS 记录更新后,将 CloudFlare 中域名的 A 记录指向服务器 IP,确保云朵为橙色(Proxied)
- 在
SSL/TLS
版块中的 Overview
里,将加密模式调整为 Full (strict)
- 在
SSL/TLS
版块中的 Edge Certificates
里,将 Minimum TLS Version
调整为 TLS 1.3
,并在下方确保开启对 TLS 1.3 的支持 - 在
Firewall
版块中的 Firewall Rules
里,添加一个规则,允许 /random
路径的访问(Allow URI path) - 在 CloudFlare 上获取域名的
Zone ID
,记录之 - 在 CloudFlare 的
My Profile
中生成一个 API Token
,权限为 Zone DNS Edit
,Zone Resources
特指区域为 example.com
,完成后记下 Token
- 根据自己的需要在 CloudFlare 上进行其他设置(可选),例如配置
Always Use HTTPS
、HSTS
、Automatic HTTPS Rewrites
、Auto Minify
等等,主要影响浏览器访问网站的效果
安装所需基本工具
1
| sudo apt update && sudo apt install curl unzip vim wget -y
|
服务器防火墙配置
此处限制服务器只允许 CloudFlare 的 IP 访问 443
端口。
1 2
| sudo mkdir -p /root/scripts/ufw sudo vim /root/scripts/ufw/add.sh
|
/root/scripts/ufw/add.sh1 2 3 4 5 6 7 8 9 10 11 12 13
| #!/bin/bash
cd /root/scripts/ufw
for ipv4 in `curl -sL https://www.cloudflare.com/ips-v4/ | tee ips-v4` do ufw allow from $ipv4 to any port 443 done
for ipv6 in `curl -sL https://www.cloudflare.com/ips-v4/ | tee ips-v6` do ufw allow from $ipv6 to any port 443 done
|
1
| sudo vim /root/scripts/ufw/remove.sh
|
/root/scripts/ufw/remove.sh1 2 3 4 5 6 7 8 9 10 11 12 13
| #!/bin/bash
cd /root/scripts/ufw
for ipv4 in `cat ips-v4` do ufw delete allow from $ipv4 to any port 443 done
for ipv6 in `cat ips-v6` do ufw delete allow from $ipv6 to any port 443 done
|
1
| sudo vim /root/scripts/ufw/update.sh
|
/root/scripts/ufw/update.sh1 2 3 4 5 6 7 8 9 10 11 12 13
| #!/bin/bash
cd /root/scripts/ufw
curl -sL https://www.cloudflare.com/ips-v4/ -o ips-v4.new curl -sL https://www.cloudflare.com/ips-v6/ -o ips-v6.new
if ! cmp -s ips-v4 ips-v4.new || ! cmp -s ips-v6 ips-v6.new || [ ! -f ips-v4 ] || [ ! -f ips-v6 ]; then bash remove.sh bash add.sh fi
rm -f ips-v4.new ips-v6.new
|
添加规则:
1
| sudo bash /root/scripts/ufw/add.sh
|
设置 cron 定时任务:
首行开始,添加如下内容,代表每日服务器时间 03:05
自动更新 ip 列表:
1 2
| MAILTO="" 5 3 * * * /bin/bash /root/scripts/ufw/update.sh
|
查看 nobody 的用户组
执行命令:
输出的结果可能是:
1
| uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
|
输出的结果也可能是:
1
| uid=65534(nobody) gid=65534(nobody) groups=65534(nobody)
|
请记住输出的用户组是 nobody
还是 nogroup
,接下来会用到这个信息,这决定了我们是使用 nobody:nogroup
还是 nobody:nobody
。
添加用户脚本
执行以下命令:
1 2
| mkdir -p ~/scripts vim ~/scripts/acme.sh
|
添加如下内容,注意替换其中的 sammy
和 nobody:nogroup
(如有必要):
~/scripts/acme.sh1 2 3 4 5 6
| #!/bin/bash
sudo chown -R sammy:sammy ~/certs "/home/sammy/.acme.sh"/acme.sh --cron --home "/home/sammy/.acme.sh" > /dev/null sudo chown -R nobody:nogroup ~/certs sudo systemctl restart trojan-go
|
执行以下命令:
添加如下内容:
~/scripts/cert.sh1 2 3
| #!/bin/bash
/usr/bin/openssl req -newkey rsa:4096 -nodes -keyout ~/certs/default.key -x509 -days 365 -out ~/certs/default.crt -subj "/C=US"
|
至此,准备工作已完成。
安装并配置 trojan-go
安装
设置一个本地安装脚本:
添加如下内容:
~/scripts/trojan.sh1 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
| #!/bin/bash
NOCOLOR="\033[0m" GREEN="\033[0;32m"
echo -e "\n${GREEN}Installing trojan-go...${NOCOLOR}\n"
if [ $# -eq 1 ];then echo -e "${GREEN}Do not add parameters! Exiting...${NOCOLOR}\n" exit fi
read -p "Fill the version: " version
cd ~/scripts proxychains wget https://github.com/p4gefau1t/trojan-go/releases/download/v$version/trojan-go-linux-amd64.zip
if [ -f "trojan-go-linux-amd64.zip" ]; then sudo unzip -o trojan-go-linux-amd64.zip -d /usr/local/bin/trojan-go else echo -e "\n\033[0;31mDownloading trojan-go v$version failed!${NOCOLOR}\n" exit fi
rm -f trojan-go-linux-amd64.zip
sudo systemctl restart trojan-go
echo -e "\n${GREEN}Installed trojan-go v$version!${NOCOLOR}\n"
|
此处以 trojan-go v0.8.2
为例,最新版本可见此处,请根据实际最新版本号调整下方输入:
1 2
| sudo chmod -R 400 ~/scripts && chmod 700 ~/scripts bash ~/scripts/trojan.sh
|
将要求输入版本号,此例中输入 0.8.2
,回车继续。
设置自启
新建服务文件:
1
| sudo vim /etc/systemd/system/trojan-go.service
|
添加如下内容:
/etc/systemd/system/trojan-go.service1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| [Unit] Description=Trojan-Go Documentation=https://github.com/p4gefau1t/trojan-go After=network.target nss-lookup.target
[Service] User=nobody CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE NoNewPrivileges=true ExecStart=/usr/local/bin/trojan-go/trojan-go -config /usr/local/etc/trojan-go/config.json Restart=on-failure RestartSec=10
[Install] WantedBy=multi-user.target
|
启用服务:
1
| sudo systemctl enable trojan-go
|
配置
编辑配置文件,注意替换其中的 sammy
为当前用户名,替换其中的 随机的密码
、sammy
、example.com
、/random
、加密所用密码
:
1 2
| sudo mkdir -p /usr/local/etc/trojan-go sudo vim /usr/local/etc/trojan-go/config.json
|
/usr/local/etc/trojan-go/config.json1 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
| { "run_type": "server", "local_addr": "0.0.0.0", "local_port": 443, "remote_addr": "127.0.0.1", "remote_port": 80, "password": [ "随机的密码" ], "ssl": { "cert": "/home/sammy/certs/example.com.crt", "key": "/home/sammy/certs/example.com.key", "sni": "example.com", "fallback_addr": "127.0.0.1", "fallback_port": 11443 }, "router":{ "enabled": true, "block": [ "geoip:private" ] }, "websocket": { "enabled": true, "path": "/random", "host": "example.com" }, "shadowsocks": { "enabled": true, "method": "AES-256-GCM", "password": "加密所用密码" } }
|
注:随机的密码
和 加密所用密码
应该使用不同密码。
安装并配置 Nginx
安装 nginx
1
| sudo apt update && sudo apt install nginx -y
|
配置
生成一个默认自签证书:
1 2 3
| sudo apt update && sudo apt install openssl -y mkdir -p ~/certs bash ~/scripts/cert.sh
|
配置 ngnix,设置默认的 catch-all:
1 2 3
| cd /etc/nginx/sites-enabled sudo rm -f default sudo vim default
|
添加如下内容,注意替换其中的 sammy
为当前用户名:
/etc/nginx/sites-enabled/default1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| server { listen 80 default_server; listen [::]:80 default_server;
server_name _;
return 400; }
server { listen 11443 ssl default_server; listen [::]:11443 ssl default_server; server_name _; ssl_certificate /home/sammy/certs/default.crt; ssl_certificate_key /home/sammy/certs/default.key; return 400; }
|
创建文件夹,注意提供换其中的 example.com
:
1 2 3
| sudo mkdir -p /var/www/example.com/html sudo chown -R $USER:$USER /var/www/example.com/html sudo chmod -R 755 /var/www/example.com/html
|
编辑 example.com
站点配置文件:
1
| sudo vim /etc/nginx/sites-available/example.com
|
注意替换其中的 example.com
为实际域名:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| server { listen 80; listen [::]:80;
server_name example.com;
root /var/www/example.com/html; index index.html; error_page 404 /404/index.html;
location / { try_files $uri $uri/ =404; } }
|
注意,如果不需要设置自定义 404 页面,则删去:
1
| error_page 404 /404/index.html;
|
接着,通过 scp
或 rsync
上传之前在本地准备好的 Web 页面文件、资源文件夹到 /var/www/example.com/html
中去。例如:
1
| rsync -ruhP --delete public/ sammy_host:/var/www/example.com/html/
|
其中,网页文件都存放在本地 public
文件夹中,服务器别名为 sammy_host
。public
文件夹结构为:
启用配置
1
| sudo ln -s /etc/nginx/sites-available/exmaple.com /etc/nginx/sites-enabled/
|
至此,Nginx 部分已经配置完毕。
准备工作
安装依赖:
1
| sudo apt update && sudo apt install socat -y
|
安装 acme.sh:
1
| wget -O - https://get.acme.sh | sh
|
修改 sudoer
文件:
最后一行新增,注意替换其中的 sammy
为当前的真实用户名,并注意此示例采用的是 nobody:nogroup
:
1 2 3 4
| sammy ALL=(ALL) NOPASSWD: /usr/sbin/service nginx force-reload sammy ALL=(ALL) NOPASSWD: /bin/systemctl restart trojan-go sammy ALL=(ALL) NOPASSWD: /bin/chown -R sammy\:sammy /home/sammy/certs sammy ALL=(ALL) NOPASSWD: /bin/chown -R nobody\:nogroup /home/sammy/certs
|
生成证书
设置环境变量:
1 2
| export CF_Token="此处填写之前创建的 CloudFlare API Token" export CF_Zone_ID="此处填写 CloudFlare 中域名的 Zone ID"
|
生成证书:
1
| acme.sh --issue --dns dns_cf -d example.com
|
安装证书
注意替换其中的 example.com
为实际域名:
1 2 3 4
| acme.sh --install-cert -d example.com \ --key-file ~/certs/example.com.key \ --fullchain-file ~/certs/example.com.crt \ --reloadcmd "bash ~/scripts/cert.sh && sudo service nginx force-reload"
|
设置读取权限
下面以 nobody:nogroup
为例:
1
| sudo chown -R nobody:nogroup ~/certs
|
设置定时任务
编辑定时任务:
删除掉其中 acme.sh
自动生成的定时任务行。
添加如下内容,保存并退出:
1
| 9 0 * * * /bin/bash ~/scripts/acme.sh
|
启动服务
1
| sudo systemctl restart trojan-go
|
至此,服务端已部署完成。
客户端配置文件
注意替换下方的 example.com
、服务端所设置的随机密码
、/random
、服务端所设置的混淆密码
:
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
| { "run_type": "client", "local_addr": "127.0.0.1", "local_port": 1085, "remote_addr": "example.com", "remote_port": 443, "password": [ "服务端所设置的随机密码" ], "ssl": { "sni": "example.com" }, "router":{ "enabled": true, "bypass": [ "geoip:cn", "geoip:private", "geosite:cn", "geosite:geolocation-cn" ], "block": [ "geosite:category-ads" ], "proxy": [ "geosite:geolocation-!cn" ], "default_policy": "proxy" }, "websocket": { "enabled": true, "path": "/random", "host": "example.com" }, "shadowsocks": { "enabled": true, "method": "AES-256-GCM", "password": "服务端所设置的加密密码" } }
|
此设置的代理监听在 socks5://127.0.0.1:1085
上。
而如果是利用了 socat 来中转流量,那么客户端的配置则可见下方,注意替换下方的 中转服务器 IP
、中转服务器端口
、服务端所设置的随机密码
、/random
、example.com
、服务端所设置的混淆密码
:
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
| { "run_type": "client", "local_addr": "127.0.0.1", "local_port": 1085, "remote_addr": "中转服务器 IP", "remote_port": 中转服务器端口, "password": [ "服务端所设置的随机密码" ], "ssl": { "sni": "example.com" }, "router":{ "enabled": true, "bypass": [ "geoip:cn", "geoip:private", "geosite:cn", "geosite:geolocation-cn" ], "block": [ "geosite:category-ads" ], "proxy": [ "geosite:geolocation-!cn" ], "default_policy": "proxy" }, "websocket": { "enabled": true, "path": "/random", "host": "example.com" }, "shadowsocks": { "enabled": true, "method": "AES-256-GCM", "password": "服务端所设置的加密密码" } }
|
此设置的代理监听在 socks5://127.0.0.1:1085
上。
References
Trojan-Go Docs
自建梯子教程 – Trojan 版本
Trojan 手动安装教程
trojan 教程
Insufficient permissions when using certificates