家里这台机器上跑着博客、订阅面板、还有一些只给自己用的服务。端口一个个开出去太难看,防火墙规则也越堆越长。后来全部收进 443,靠的是 nginx 的 stream 模块加 ssl_preread。
四层预读 TLS ClientHello 里的 SNI 字段,按域名把 TCP 连接丢给不同的后端,nginx 全程不碰加密内容。
stream {
ssl_preread on;
map $ssl_preread_server_name $backend {
blog.example.com web;
panel.example.com panel;
default catchall;
}
server {
listen 443;
proxy_pass $backend;
}
}
不带 SNI 或 SNI 不匹配的流量全走 default。我最初的 default 指回了自己,直接回环打满 CPU。default 要么指一个明确的兜底服务,要么 return(stream 里用 proxy_timeout 1s 快速掐掉)。
另一个坑:改 nginx.conf 如果是 Docker 单文件 bind mount,sed -i 换 inode 之后容器里看到的还是旧文件,reload 也没用,必须重启容器。