nginx必须用独立server块分别处理http和https,因协议本质不同:http监听80端口且不可配ssl指令,https监听443 ssl端口并强制要求ssl_certificate等配置,混用会导致报错或tls握手失败。

Nginx 用不同的 server 块区分 HTTP 和 HTTPS 请求,核心在于协议特性不同——HTTP 明文、无加密,HTTPS 需证书验证和 TLS 握手。这种分离不是可选项,而是协议层面对配置的刚性要求。
监听端口与协议标识必须严格对应
HTTP 请求只能由 listen 80(或自定义非加密端口)的 server 块接收;HTTPS 请求必须由带 ssl 标识的 listen 443 ssl 块处理。Nginx 在启动时会校验:没有 ssl 关键字却配置了 ssl_certificate 会报错;反之,有 ssl 却没配证书也会拒绝加载。
-
listen 80;:仅处理未加密请求,不支持 TLS 握手,不能设ssl_certificate -
listen 443 ssl http2;:启用 TLS 层,强制要求提供证书路径,同时可启用 HTTP/2 - IPv6 支持需显式声明:
listen [::]:443 ssl,否则 IPv6 的 HTTPS 请求会被忽略
SSL 配置仅在 HTTPS 块中生效且不可省略
证书、密钥、协议版本、加密套件等全部 SSL 相关指令,只在启用了 ssl 的 server 块内合法。HTTP 块里写这些指令会被 Nginx 忽略或直接报配置错误。
-
ssl_certificate和ssl_certificate_key是 HTTPS 块的必需项,路径必须可读 -
ssl_protocols TLSv1.2 TLSv1.3;控制允许的 TLS 版本,影响浏览器兼容性与安全性 -
ssl_ciphers定义加密算法优先级,避免使用已知弱算法(如!MD5、!aNULL)
请求头与代理行为存在协议感知差异
HTTPS 流量经过 TLS 解密后进入 Nginx,此时 $scheme 变量值为 https,而 HTTP 下是 http。这个变量直接影响反向代理时的请求头设置和重定向逻辑。
- 代理到后端时,
proxy_set_header X-Forwarded-Proto $scheme;能让后端准确识别原始协议 - 混合内容(mixed content)防护需在 HTTPS 块中加:
add_header Content-Security-Policy "upgrade-insecure-requests"; - HTTP 块中常用
return 301 https://$host$request_uri;强制跳转,但该逻辑不能放在 HTTPS 块里,否则形成循环
域名匹配与重定向策略需按协议分别控制
虽然 server_name 可以复用,但重定向目标、安全头、HSTS 等策略必须按协议独立配置。例如 HSTS(HTTP Strict Transport Security)只对 HTTPS 响应生效,且必须通过 add_header Strict-Transport-Security 显式下发。
- HTTP 块适合做纯跳转,不发任何业务响应体,避免暴露敏感信息
- HTTPS 块可启用
add_header X-Frame-Options "DENY"、X-Content-Type-Options "nosniff"等安全头 - 通配符域名如
server_name .example.com;对两个块都有效,但证书必须覆盖对应域名(如泛域名证书)











