用 nginx stream 把一台机器挤干净

2026-09-14 · ~6 min

家里这台机器上跑着博客、订阅面板、还有一些只给自己用的服务。端口一个个开出去太难看,防火墙规则也越堆越长。后来全部收进 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;
    }
}

坑:default 分支

不带 SNI 或 SNI 不匹配的流量全走 default。我最初的 default 指回了自己,直接回环打满 CPU。default 要么指一个明确的兜底服务,要么 return(stream 里用 proxy_timeout 1s 快速掐掉)。

另一个坑:改 nginx.conf 如果是 Docker 单文件 bind mount,sed -i 换 inode 之后容器里看到的还是旧文件,reload 也没用,必须重启容器。

← 返回