Nginx不支持TCP层用server_name区分域名,因TCP无域名概念;可行方案有三:一是stream模块+ssl_preread提取SNI实现HTTPS域名路由;二是按端口或IP分流纯TCP服务;三是http块中多server块基于server_name做HTTP/HTTPS反向代理。

Nginx 本身不支持在 HTTP 层之外用 server_name 区分域名来实现 TCP 层的多域名代理——因为 TCP 协议没有“域名”概念,HTTP 的 Host 头只存在于应用层。所以严格来说,“多域名共用一个 TCP 端口”不是靠域名路由,而是靠 IP + 端口或协议特征(如 TLS SNI)间接区分。但结合实际场景,有两类主流可行方案:一种是基于 SNI 的 HTTPS/TLS 服务代理,另一种是纯 TCP 层按端口或目标地址分流。下面分情况说明。
HTTPS 域名代理(推荐,真正按域名分发)
当后端服务支持 HTTPS(如 Web 应用、API 服务),且客户端发起的是带 SNI 扩展的 TLS 握手时,Nginx 的 stream 模块可借助 ssl_preread 提取 SNI 域名,再通过 map 指令路由到不同上游。这是目前最接近“多域名共用一个 TCP 端口”的标准做法。
- 启用
ssl_preread模块(编译时需含--with-stream-ssl-preread-module) - 在
stream块外定义域名映射关系,例如:
map $ssl_preread_server_name $upstream {
abc.com backend_abc;
xyz.com backend_xyz;
default backend_default;
} - 配置监听 443 端口的 server,使用
ssl_preread on并 proxy_pass 到对应 upstream
TCP 端口级分流(简单直接,无需域名解析)
若服务本身是纯 TCP(如数据库、邮件、自定义协议),无法携带域名信息,则只能按端口或 IP 分流。此时“多域名”只是 DNS 解析层面的映射,实际由不同端口承载:
- 让 abc.com 和 xyz.com 都解析到同一公网 IP
- 在路由器/NAT 设备上将不同外网端口映射到内网不同服务,例如:
外网 443 → 内网 192.168.1.10:3306(MySQL)
外网 25 → 内网 192.168.1.11:25(SMTP) - Nginx
stream块中为每个端口单独配置server,例如:
server {
listen 443;
proxy_pass 192.168.1.10:3306;
}
server {
listen 25;
proxy_pass 192.168.1.11:25;
}
HTTP/HTTPS 多域名反向代理(最常用,非 TCP 层)
绝大多数 Web 场景其实走的是 HTTP/HTTPS 流量,这时应使用 http 块中的多个 server,而非 stream。每个 server 通过 server_name 匹配域名,再 proxy_pass 到本地或内网不同端口的服务:
- 确保 DNS 已将 abc.com、xyz.com 解析到 Nginx 所在服务器 IP
- 配置两个
server块,均listen 80或listen 443 ssl - 分别设置
server_name abc.com和server_name xyz.com -
location /中用proxy_pass http://127.0.0.1:8080等指向各自后端 - HTTPS 需额外配置证书,每个域名可配独立证书或通配符证书
注意事项与验证要点
无论采用哪种方式,都需注意:
- 防火墙必须放行对应端口(如 80、443、自定义 TCP 端口)
- 检查 Nginx 是否加载了所需模块:
nginx -V 2>&1 | grep -o with-stream - 配置后务必运行
nginx -t测试语法,再nginx -s reload - 对 HTTPS+SNI 方案,客户端需支持 TLS 1.2+ 且发送 SNI(现代浏览器和 curl 默认开启)
- 纯 TCP 代理无法做 URL 或 Header 级过滤,日志也仅记录 IP:Port,不记录域名


















