Debian & Ubuntu 搭建部署 trojan-go + Nginx + Websocket 并使用 Cloudflare

Contents
  1. 1. 准备工作
    1. 1.1. 服务器与域名
    2. 1.2. 内容准备
    3. 1.3. Cloudflare 设置
    4. 1.4. 安装所需基本工具
    5. 1.5. 服务器防火墙配置
  2. 2. 安装并配置 trojan-go
    1. 2.1. 安装
    2. 2.2. 设置自启
    3. 2.3. 配置
  3. 3. 安装并配置 Nginx
    1. 3.1. 安装 nginx
    2. 3.2. 配置
    3. 3.3. 启用配置
  4. 4. 利用 acme.sh 生成证书
    1. 4.1. 准备工作
    2. 4.2. 生成证书
    3. 4.3. 安装证书
    4. 4.4. 设置读取权限
  5. 5. 启动服务
  6. 6. 客户端配置文件
  7. 7. References

本文最后更新于 2020 年 10 月 11 日


本文以 Debian 10 为例,介绍如何搭建 trojan-go + Websocket 服务端,使用 Nginx 建立 Web,并利用 Cloudflare 隐藏源站 IP,最后说明对应的客户端配置文件的格式。本文同样完全适用于 Ubuntu 20.04 系统。

注:请先参照 Debian & Ubuntu 服务器的初始化配置 一文对服务器进行各种必要的配置。本文以 sammy 用户为例,进行 trojan-go 的部署,并默认已按初始化配置文章对服务器进行了配置。


准备工作

服务器与域名

  1. 可用的公网 IP 服务器(例如在 BandwagonHostVultr 等处购买的 VPS)
  2. 注册一个域名,本文以 example.com 为例

内容准备

  1. 起一个随机的路径名,本文使用 /random
  2. 准备自定义的 Web 页面,用于浏览器正常访问 example.com 显示的网页
  3. 准备自定义的 404 页面(可选)

Cloudflare 设置

  1. 将域名的 Namesever 指向 Cloudflare 所提供的地址,等待生效
  2. NS 记录更新后,将 Cloudflare 中域名的 A 记录指向服务器 IP,确保云朵为橙色(Proxied)
  3. SSL/TLS 版块中的 Overview 里,将加密模式调整为 Full (strict)
  4. SSL/TLS 版块中的 Edge Certificates 里,将 Minimum TLS Version 调整为 TLS 1.3,并在下方确保开启对 TLS 1.3 的支持
  5. Firewall 版块中的 Firewall Rules 里,添加一个规则,允许 /random 路径的访问(Allow URI path)
  6. 在 Cloudflare 上获取域名的 Zone ID,记录之
  7. 在 Cloudflare 的 My Profile 中生成一个 API Token,权限为 Zone Zone ReadZone DNS EditZone Resources 特指区域为 example.com,完成后记下 Token
  8. 根据自己的需要在 Cloudflare 上进行其他设置(可选),例如配置 Always Use HTTPSHSTSAutomatic HTTPS RewritesAuto 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.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash

cd /root/scripts/ufw

for ipv4 in `curl -s https://www.cloudflare.com/ips-v4 | tee ips-v4`
do
ufw allow from $ipv4 to any port 443
done

for ipv6 in `curl -s https://www.cloudflare.com/ips-v6 | 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.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/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

rm -f ips-v4 ips-v6
1
sudo vim /root/scripts/ufw/update.sh
/root/scripts/ufw/update.sh
1
2
3
4
5
6
#!/bin/bash

cd /root/scripts/ufw

bash remove.sh
bash add.sh

添加规则:

1
sudo bash /root/scripts/ufw/add.sh

设置 cron 定时任务:

1
sudo crontab -e

首行开始,添加如下内容,代表每日服务器时间 03:05 自动更新 ip 列表:

1
2
MAILTO=""
5 3 * * * /bin/bash /root/scripts/ufw/update.sh

至此,准备工作已完成。


安装并配置 trojan-go

安装

此处以 trojan-go v0.8.2 为例,最新版本可见此处,请根据实际最新版本号调整下方 wget 所用网址:

1
2
3
4
cd ~
wget https://github.com/p4gefau1t/trojan-go/releases/download/v0.8.2/trojan-go-linux-amd64.zip
sudo unzip -o trojan-go-linux-amd64.zip -d /usr/local/bin/trojan-go
rm trojan-go-linux-amd64.zip

设置自启

新建服务文件:

1
sudo vim /etc/systemd/system/trojan-go.service

添加如下内容:

/etc/systemd/system/trojan-go.service
1
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 为当前用户名,替换其中的 随机的密码sammyexample.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.json
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
{
"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
openssl req -newkey rsa:4096 -nodes -keyout ~/certs/default.key -x509 -days 365 -out ~/certs/default.crt -subj "/C=US"

设置定时更新自签证书:

1
crontab -e

添加如下内容,注意替换其中的 sammy 为实际用户名,保存并退出:

1
0 0 1 * * /usr/bin/openssl req -newkey rsa:4096 -nodes -keyout /home/sammy/certs/default.key -x509 -days 365 -out /home/sammy/certs/default.crt -subj "/C=US"

配置 ngnix,设置默认的 catch-all:

1
2
3
cd /etc/nginx/sites-enabled
sudo rm -f default
sudo vim default

添加如下内容,注意替换其中的 sammy 为当前用户名:

/etc/nginx/sites-enabled/default
1
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;

接着,通过 scprsync 上传之前在本地准备好的 Web 页面文件、资源文件夹到 /var/www/example.com/html 中去。例如:

1
rsync -ruhP --delete public/ sammy_host:/var/www/example.com/html/

其中,网页文件都存放在本地 public 文件夹中,服务器别名为 sammy_hostpublic 文件夹结构为:

  • public/
    • 404/
      • ...
      • index.html
    • ...
    • index.html

启用配置

1
sudo ln -s /etc/nginx/sites-available/exmaple.com /etc/nginx/sites-enabled/

至此,Nginx 部分已经配置完毕。


利用 acme.sh 生成证书

准备工作

安装依赖:

1
sudo apt update && sudo apt install socat -y

安装 acme.sh

1
wget -O - https://get.acme.sh | sh

修改 sudoer 文件:

1
sudo visudo

最后一行新增,注意替换其中的 sammy 为当前的真实用户名:

1
2
sammy ALL=(ALL) NOPASSWD: /usr/sbin/service nginx force-reload
sammy ALL=(ALL) NOPASSWD: /bin/systemctl restart trojan-go

生成证书

设置环境变量:

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 "sudo service nginx force-reload && sudo systemctl restart trojan-go"

设置读取权限

执行命令:

1
id nobody

以查看是 nobody:nogroup 还是 nobody:nobody

下面以 nobody:nogroup 为例:

1
sudo chown -R nobody:nogroup ~/certs

启动服务

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中转服务器端口服务端所设置的随机密码/randomexample.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 教程