Files
trojanZ/部署架构建议.md
T
2026-07-26 00:09:57 +08:00

191 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Trojan、Nginx 与 Caddy 共用 80/443 的部署方案
> 适用对象:已按项目 README 的 Docker 方式运行 Trojan 管理程序,希望同一台服务器继续部署多个 HTTPS 网站或 Web 服务。
>
> 本文只给出架构和操作建议,不直接修改已经运行的服务器。
## 已确认的现状
- Trojan 对外域名:`www.hk.chermack.top`
- 容器 `trojan`:镜像 `jrohy/trojan`,已运行约两年,当前已连续运行七周;`docker ps` 没有显示端口映射。这与项目 README 的 `--net=host` 启动方式一致,意味着它很可能直接使用宿主机网络,并占用 Trojan 的 `443` 与管理 Web 的 `80`
- 容器 `trojan-mariadb`:镜像 `mariadb:10.2`,当前映射 `0.0.0.0:3306->3306``[::]:3306->3306`;即 MySQL/MariaDB 已对全网开放。
本文后续均直接使用该真实 Trojan 域名:**`www.hk.chermack.top`**。
## 1. 结论
不能让 Trojan、Nginx 或 Caddy 同时直接监听宿主机的 `80``443`:同一 IP:端口只能被一个进程绑定。
由于 Trojan 使用的并非 HTTP/HTTPS Web 请求,而是基于 TLS 的代理协议,普通的 `reverse_proxy` 规则无法把 `/``/api` 一类路径转发给它。要同时使用 Trojan 和多个网站,应按 TLS 握手中的 **SNI(访问域名)** 在四层分流:
```mermaid
flowchart TB
Internet["Internet"] --> N80["Nginx :80\nHTTP 转发"]
Internet --> N443["Nginx stream :443\n按 TLS SNI 分流"]
N80 --> Caddy["Caddy :8080 / :9443\n自动申请、续期证书\n托管网站"]
N443 -->|"www.hk.chermack.top"| Trojan["Trojan 容器 :8443\nTLS 直通"]
N443 -->|"app.example.com\nwww.example.com"| Caddy
Caddy --> App1["网站 / 应用 1"]
Caddy --> App2["网站 / 应用 2"]
```
推荐职责划分:
- **Nginx**:唯一占用公网 `80``443``443` 使用 `stream + ssl_preread` 按域名转发 TLS 流量,自己不终止 TLS。
- **Caddy**:监听本机 `8080`/`9443`,为普通网站自动申请和续期 Let's Encrypt/ZeroSSL 证书,并反向代理到各个 Web 应用。
- **Trojan**:改为仅监听宿主机本地端口(示例使用 `8443`),由 Nginx 按 `www.hk.chermack.top` 的 SNI 转发。它仍使用自己的 Trojan TLS 证书。
## 2. 域名规划
应使用不同的子域名,不要让 Trojan 和网站共用同一个域名:
|用途|示例域名|TLS 终止位置|
|---|---|---|
|Trojan 服务|`www.hk.chermack.top`|Trojan|
|Trojan 管理后台|建议新增 `panel.hk.chermack.top`|Caddy|
|普通网站|例如 `site.hk.chermack.top`|Caddy|
|其他应用|例如 `app.hk.chermack.top`|Caddy|
所有域名的 A/AAAA 记录都指向这台服务器。Trojan 客户端应继续使用 `www.hk.chermack.top` 作为 SNI 和服务器地址。
## 3. 前置条件与注意事项
1. 所有服务应只向 Docker 内网或 `127.0.0.1` 发布端口;不要把 Trojan 的新端口、Caddy 的 `8080/9443` 直接暴露到公网。
2. Nginx 需要带有 `stream``ssl_preread` 模块。Ubuntu/Debian 通常需要安装 `libnginx-mod-stream`;确认方式:`nginx -V 2>&1 | grep stream`
3. 防火墙、安全组只开放公网 TCP `80``443`(以及 SSH 管理端口);关闭原先直接暴露的 Trojan 端口。
4. 当前 `trojan-mariadb``3306` 正暴露于 IPv4/IPv6 公网。除非确有远程数据库访问需求,切换时应改为仅容器网络或 `127.0.0.1:3306`,并从安全组和防火墙移除公网 3306。
5. Trojan 的 TLS 证书仍应有效且包含 `www.hk.chermack.top`。Caddy 的自动 HTTPS 只负责它所托管的网站,**不会自动替 Trojan 申请或安装证书**。
5. Caddy 使用 HTTP-01 验证时,Nginx 的 `80` 必须完整转发到 Caddy。Caddy 成功续期不需要人工定时执行证书申请命令。
## 4. 修改现有 Trojan Docker 端口
README 示例使用 `--net=host`,因此 Trojan 和管理 Web 服务会直接占用宿主机端口。建议改为显式端口映射,或在仍使用 host 网络时把 Trojan 和 Web 的监听端口改为非公网端口。
### 建议的目标端口
|服务|容器/程序内端口|宿主机绑定|公网暴露|
|---|---:|---|---|
|Trojan|改为 `8443`|`127.0.0.1:8443`|否,由 Nginx 443 转发|
|Trojan Web 管理后台|改为 `8081`|`127.0.0.1:8081`|否,由 Caddy 代理|
|Caddy HTTP|`8080`|`127.0.0.1:8080`|否,由 Nginx 80 转发|
|Caddy HTTPS|`8443`|`127.0.0.1:9443`(避免与 Trojan 冲突)|否,由 Nginx 443 转发|
上表特意将 Caddy 的宿主机 HTTPS 端口设为 `9443`,避免和 Trojan 的 `8443` 冲突。实际端口可以调整,但必须保证唯一。
### Trojan 配置原则
在 Trojan 的 `/usr/local/etc/trojan/config.json` 中,把 `local_port``443` 改为 `8443`;管理程序的 Web 服务以类似方式改为 `8081`(例如 systemd 服务执行 `trojan web -p 8081`)。
如果容器仍采用 `--net=host`,以上端口是宿主机端口。若改为 Docker bridge 网络,推荐使用仅回环地址的映射,例如:
```bash
-p 127.0.0.1:8443:8443
-p 127.0.0.1:8081:8081
```
重建容器前,应先备份:
```bash
docker inspect trojan > trojan.inspect.backup.json
docker cp trojan:/usr/local/etc/trojan/config.json ./trojan-config.backup.json
```
不要在未确认持久化目录和数据库位置前删除旧容器。README 所用方案还会单独运行 MariaDB,必须保留其数据卷。
## 5. Nginx 四层 SNI 分流示例
以下配置应放在 Nginx 主配置可加载的位置;`stream` 块通常不能放入普通的 `server {}` HTTP 配置文件。域名和端口必须替换为实际值。
```nginx
# /etc/nginx/nginx.conf(顶层 stream 块)
stream {
map $ssl_preread_server_name $tls_upstream {
www.hk.chermack.top trojan_backend;
default caddy_https_backend;
}
upstream trojan_backend {
server 127.0.0.1:8443;
}
upstream caddy_https_backend {
server 127.0.0.1:9443;
}
server {
listen 443 reuseport;
proxy_pass $tls_upstream;
ssl_preread on;
proxy_timeout 1h;
proxy_connect_timeout 5s;
}
}
http {
server {
listen 80;
server_name _;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto http;
}
}
}
```
此配置的关键是:Nginx 在 `443` 上只读取 ClientHello 的 SNI,不解密 TLS;因此 Trojan 和 Caddy 都能拿到自己完整的 TLS 握手和证书。
若客户端未发送 SNI,会被送到默认的 Caddy 后端;Trojan 客户端必须明确配置 SNI 为 `www.hk.chermack.top`
## 6. Caddy 自动 HTTPS 示例
在 Caddyfile 设置内部监听端口。Caddy 仍会使用域名来签发和管理证书,只是外部 `80/443` 由 Nginx 转发到它。
```caddyfile
{
http_port 8080
https_port 9443
email ops@example.com
}
panel.hk.chermack.top {
reverse_proxy 127.0.0.1:8081
}
site.hk.chermack.top {
reverse_proxy 127.0.0.1:3000
}
app.hk.chermack.top {
reverse_proxy 127.0.0.1:9000
}
```
其中 `panel.hk.chermack.top` 反向代理 Trojan 管理后台;其他站点各自指向对应容器或本机应用。Caddy 会保存证书与续期状态,容器部署时必须挂载其数据目录,例如 `/data``/config`,否则重建容器会丢失 ACME 账户和证书缓存。
## 7. 建议实施顺序
1. 记录现有容器、端口、配置、数据库卷和证书路径,并完成备份。尤其保存 `docker inspect trojan``docker inspect trojan-mariadb` 和 MariaDB 数据卷信息;`trojan` 没有端口映射,变更前必须确认其是否为 `--network host`
2.`trojan``panel`、网站分别创建 DNS 记录。
3. 安装并验证 Nginx 的 `stream` 模块,但暂不切走 80/443。
4. 启动 Caddy 于 `127.0.0.1:8080``127.0.0.1:9443`,先验证内部反向代理可用。
5. 将 Trojan 改至 `127.0.0.1:8443`,将管理后台改至 `127.0.0.1:8081`,确认直连本机端口均正常。
6. 配置 Nginx `80` 转 Caddy、`443` SNI 分流,执行 `nginx -t`
7. 在维护窗口切换 Nginx 到公网 `80/443`,验证网站 HTTPS、Caddy 证书签发、Trojan 客户端连接、管理后台登录和订阅链接。
8. 最后收紧 Docker 端口映射与防火墙,只留 `80/443` 公开;将当前 MariaDB 的公网 `3306` 映射关闭或至少限制为 `127.0.0.1`
## 8. 不建议的方案
- 让 Caddy 或 Nginx 直接以 HTTP `reverse_proxy` 转发 Trojan:协议不匹配,不能工作。
- Trojan 与网站共用同一个域名且共用 443:SNI 无法区分目标,除非引入更复杂的协议伪装/回落设计;不适合当前项目的常规部署。
- 将 Trojan 改端口后直接对公网开放该端口:虽能运行,但无法达到只使用 80/443 的目标,也增加暴露面。
- 认为 Caddy 能替 Trojan 自动处理证书:Caddy 只能为它实际终止 TLS 的连接管理证书;本方案中 Trojan 的 TLS 是端到端直通。
## 9. 后续执行前需要确认的信息
实施时需要根据真实状态补全:当前 Trojan 容器的 `docker inspect` 输出、实际 `config.json`、MariaDB 容器/卷、当前占用 80/443 的进程、服务器系统发行版、可用域名及 DNS 提供商。