nginx 同时支持 http、https 和 tcp 需编译启用对应模块:http/https 配置置于 http {} 块,tcp 代理必须用独立 stream {} 块;443 端口可借 ssl_preread 实现 http 与 https 智能分流。

Nginx 要同时支持 HTTP、HTTPS 和 TCP 三种协议,关键不在“写对配置”,而在于编译时启用对应模块 + 配置放在正确上下文 + 协议逻辑不混用。下面分三块讲清楚怎么做。
HTTP 和 HTTPS 配置必须放在 http {} 块内
这是最常见也最容易出错的地方。HTTP 和 HTTPS 都属于应用层(七层)协议,Nginx 用 http 上下文处理它们。
- HTTP 服务监听 80 端口,不需要证书,配置简单:
server { listen 80; server_name example.com; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } - HTTPS 服务监听 443 端口,必须开启
ssl参数并指定证书路径:server { listen 443 ssl http2; server_name example.com; ssl_certificate /etc/nginx/ssl/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; location / { proxy_pass https://127.0.0.1:8443; } }⚠️ 注意:不能把
ssl on;写在listen 443;后面单独一行——这会引发 400 错误;必须写成listen 443 ssl;,且证书路径要真实存在、权限可读。
TCP 代理必须用 stream {} 块,且不能和 http 混在一起
TCP 是四层协议,比如数据库、邮件、SSH 等原始流转发,Nginx 不解析内容,只做字节转发。它完全独立于 http 块,必须写在 nginx.conf 顶层(和 http、events 同级)。
- 编译时必须加
--with-stream,否则启动报错:unknown directive "stream" - 示例:将公网 3306 流量转给内网 MySQL:
stream { upstream mysql_backend { server 192.168.1.100:3306; } server { listen 3306; proxy_pass mysql_backend; proxy_timeout 1h; } }✅ 支持多端口共存(如同时代理 SMTP 25、IMAP 143、Redis 6379),每个
server块监听一个端口即可。
❌ 不支持 TLS 卸载(即不能在 Nginx 终止 MySQL 的 SSL 连接),证书由后端自己管。
让一个端口(如 443)同时响应 HTTP 和 HTTPS 请求
标准 Nginx 不允许 listen 443; 同时处理明文和加密流量,但可通过 stream + ssl_preread 实现智能分流:
- 编译需额外加
--with-stream_ssl_preread_module - 利用 TLS 握手特征自动识别协议类型:
stream { map $ssl_preread_protocol $backend { "" http_server; # 无 TLS → HTTP default https_server; # 有 TLS → HTTPS } upstream http_server { server 127.0.0.1:8080; } upstream https_server { server 127.0.0.1:8443; } server { listen 443; ssl_preread on; proxy_pass $backend; } }这样访问
http://example.com:443和https://example.com:443都能通,后端分别跑在 8080 和 8443。适合受限端口场景(如某些云厂商只开放 443 入口)。
不复杂但容易忽略











