Nginx Stream 基于SNI分流处理TLS流量实现443端口多后端复用
这是我博客迁移的一个基础收尾工作,因为我需要让web服务启用SSL后和trojan-go共用443端口。
使用Nginx Stream分流
Nginx关键配置
stream {
# 这里就是 SNI 识别,将域名映射成一个配置名
map $ssl_preread_server_name $backend_name {
xfox.fun web;
trojan.example.com proxy_trojan;
# 域名都不匹配情况下的默认值
default web;
}
# web,配置转发详情
upstream web {
server 127.0.0.1:10240;
}
# trojan,配置转发详情
upstream trojan-go {
server 127.0.0.1:10241;
}
#Proxy 中间层,先转发到中间层在下方由Nginx继续做处理以便交付给trojan前卸载流量的proxy protocol (因为trojan不支持proxy protocol特性)
upstream proxy_trojan {
server 127.0.0.1:10249;
}
# 监听 443 并开启 ssl_preread
# proxy_protocol用于解决真实IP获取问题,后端服务也必须同时在 listen 规则里面配置接受
server {
listen 443 reuseport;
listen [::]:443 reuseport;
proxy_pass $backend_name;
proxy_protocol on;
ssl_preread on;
}
# 这里的 server 就是用来帮 Trojan 卸载proxy_protocol协议的中间层处理场所
# 原来的 upstream trojan-go 配置不需要改动
server {
listen 10249 proxy_protocol;
proxy_pass trojan-go;
}
}
Troajn配置:
注意local_addr和local_port与SNI分流时转发的目的地对应。
Web配置
关于Real IP,参见官方文档Changing the Load Balancer’s IP Address To the Client IP Address和set_real_ip_from
这里感谢陈姓大佬提供指导,我自己看文档的时候也看到了这部分,但是作为业余人士对set_real_ip_from应当适用的Nginx区块未知理解不到位导致自己配置没配好。
后端Web服务配置SSL时应当注意调整至分流相应端口并启用proxy_protocol,特别是避免再占443。
listen 10240 http2 ssl proxy_protocol;
#Real IP 非常重要,指定了接受ip传递的地址和方式(还有用X-Forwarded-For等二次传递的其他写法,但是最初的数据获取还是离不开proxy_protocol,我测试的时候差点就写出来另一个可行方案了🤣,这里用的还是陈大佬教的也最简洁。)
set_real_ip_from 127.0.0.1;
real_ip_header proxy_protocol;
#
#ssl证书的pem文件路径
ssl_certificate /www/cert/xfox.fun.fullchain.pem;
#ssl证书的key文件路径
ssl_certificate_key /www/key/xfox.fun.key.pem;
申请SSL
使用acme.sh,请见官方仓库:https://github.com/acmesh-official/acme.sh/wiki
acme.sh --issue -d xfox.fun -d www.xfox.fun --nginx
此过程中使用普通用户存在报错:nginx command is not found
最终解决方案:先 sudo -
切到root并保持大部份环境变数(HOME SHELL USER等等)都是以root为主,并且工作目录也会改变。
申请后安装证书到指定路径。
acme.sh --install-cert -d xfox.fun \
--key-file /www/key/xfox.fun.key.pem \
--fullchain-file /www/cert/xfox.fun.fullchain.pem \
--reloadcmd "service nginx force-reload"
一个小bug
80端口启用http2的时候会导致http访问异常,https无此问题。
curl http://xfox.fun显示
curl: (1) Received HTTP/0.9 when not allowed