条件
域名A: aaa.example.com
域名B: bbb.example.com
域名trojan: trojan.example.com
域名A,域名B和域名trojan的DNS解析均为同一个IP地址。
aaa.example.com
和bbb.example.com
为不同的其他站点,trojan.example.com
为trojan站点。
介绍
HTTPS 已经是互联网服务准入的基本门槛了,同时 443 端口作为 HTTPS 请求的默认端口,在虚拟主机服务的支持下,搭配的天衣无缝。
但是 Trojan 比较特殊,因为它的工作方式导致了其必须直接对接流量入口,否则其协议无法被服务端正常识别,同时为了增加服务的隐蔽性,一般会把它配置在 443 端口。但是 443 端口只有一个,虽然 Trojan 提供了「非标请求」的转发功能,但是毕竟是一个新生事物,所有流量都过它手,在稳定、性能、灵活等等方面都不够好,而且还不支持 TLS 转发。
Nginx安装
若未安装Nginx或没有包含对应模块,教程看这→点此查看Nginx安装教程
执行nginx -V
查看是否包含--with-stream_ssl_preread_module
模块
Trojan-go安装
若未安装Trojan-go,安装教程在这→点此查看Trojan-go安装教程
端口分配
Nginx服务占用端口为80,443,1443
Trojan服务占用端口为10443
端口80用于Nginx正常提供http服务
端口443用于Nginx的stream块基于SNI分流,如果是trojan,分流至10443的trojan服务。否则分流至自身的1443端口对外提供正常的https服务。
端口1443用于Nginx正常提供https服务,所有非trojan站点都可以在nginx中使用这个端口进行配置,无需每个站点一个端口,支持本地静态和动态proxy_pass。
端口10443用于Nginx转发至Trojan服务。
防火墙仅对外开放80
和443
端口即可。
配置
首先得明确,Trojan 是无法通过 Nginx 在 7 层进行代理的,所以它设定必须在流量入口,Nginx 都只能挂在它的后面。Nginx 支持基于 SNI 的 4 层转发。简单说就是:识别 SNI 信息,然后直接转发 TCP/UDP 数据流。
Nginx的stream块在http块前。流量方向为nginx > stream [ > server ] > http [ > server ]
所以同时配置stream块和http块的listen 443
,其中http块会失效。
经过摸索和配置,总结了一套自认为最优雅的nginx和trojan-go的配置方案。
Nginx stream块配置如下
/usr/locol/nginx/conf/nginx.conf1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| stream { map $ssl_preread_server_name $backend_name { trojan.example.com trojan; aaa.example.com web; bbb.example.com web; ; 根据需要选择是否开启默认站点 #default web; # 默认web }
upstream trojan { server 127.0.0.1:10443; }
upstream web { server 127.0.0.1:1443; }
server { listen 443 reuseport; listen [::]:443 reuseport; proxy_pass $backend_name; ssl_preread on; } }
|
Nginx http块配置如下
多站点域名A,域名B,域名trojan共存,注意默认的listen 80
不能删除,因为trojan-go的remote_addr
和remote_port
不支持https。
/usr/locol/nginx/conf/nginx.conf1 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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| http { server { listen 1443 ssl; http2 on; server_name aaa.example.com; client_max_body_size 1000M;
ssl_certificate aaa.example.com.crt; ssl_certificate_key aaa.example.com.key;
ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on;
location / { root html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
server { listen 1443 ssl; http2 on; server_name bbb.example.com; client_max_body_size 1000M;
ssl_certificate bbb.example.com.crt; ssl_certificate_key bbb.example.com.key;
ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on;
location / { root html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
server { listen 1443 ssl; http2 on; server_name trojan.example.com; client_max_body_size 1000M;
ssl_certificate trojan.example.com.crt; ssl_certificate_key trojan.example.com.key;
ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on;
location / { root html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
|
Trojan-go配置如下
server.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
| { "run_type": "server", "local_addr": "0.0.0.0", "local_port": 10443, "remote_addr": "127.0.0.1", "remote_port": 80, "log_level": 2, "password": [ "密码" ], "ssl": { "cert": "trojan.example.com.crt", "key": "trojan.example.com.key", "sni": "trojan.example.com", "fallback_addr": "127.0.0.1", "fallback_port": 1443 }, "router": { "enabled": true, "block": [ "geoip:private" ], "geoip": "/root/trojan-go/geoip.dat", "geosite": "/root/trojan-go/geosite.dat" } }
|
总结
关于端口合理分配,以下仅仅是我的癖好
10000以上端口为各个自有服务或三方服务端口,用于nginx反向代理访问,禁止开放防火墙。类似mysql端口3306,则对应就是13306。redis默认6379则对应16379。
1443为443的下位替代,不是三方服务,保证http块中的server正常服务。
如有多域名多证书多站点配置的需要可以看我的这个文章。Nginx多域名多证书多站点配置最佳实践
感谢大佬的探索,参考链接:Trojan 共用 443 端口方案