关键是在同一server块中用多个listen指令分别声明HTTP和HTTPS(含HTTP/2)入口,统一配置安全策略;listen 80用于重定向,listen 443 ssl http2启用TLS与HTTP/2,SSL参数及安全响应头集中定义于server顶层。

要让一个 server 块同时支持 HTTP、HTTPS(含 HTTP/2)并统一做安全控制,关键不是“多协议共存于同一 listen”,而是用多个 listen 指令明确声明不同协议入口,并在同一个 server 块内复用安全策略——这样既能共享 root、location、headers 等配置,又能避免重复定义。
同一 server 块中声明多个 listen,区分协议语义
HTTP 和 HTTPS 是不同协议栈,Nginx 不允许混用(比如 listen 443; 不加 ssl 就无法处理 TLS 握手)。但你可以把它们放在同一个 server 块里:
-
listen 80;:纯 HTTP 入口,用于重定向或降级服务 -
listen 443 ssl http2;:启用 TLS + HTTP/2,必须配ssl_certificate和ssl_certificate_key -
listen [::]:80;和listen [::]:443 ssl http2;:显式支持 IPv6,方括号不可省略
安全策略集中定义,避免跨块重复
所有与安全相关的指令(如 HSTS、CSP、X-Frame-Options、SSL 参数)都写在 server 块顶层,对所有 listen 生效:
- 用
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;强制 HTTPS,且always确保响应头不被 location 覆盖 - SSL 参数如
ssl_protocols TLSv1.2 TLSv1.3;、ssl_ciphers、ssl_prefer_server_ciphers off;统一配置一次即可 - 若需对 HTTP 请求强制跳转 HTTPS,用
return 301 https://$host$request_uri;放在listen 80对应的 server 块里(注意:这不是同一 server 块,而是另一个仅监听 80 的 server)
通过 server_name 实现域名级策略隔离
当多个域名共用同一组端口+协议时,可借助 server_name 匹配后差异化启用安全能力:
- 对内部管理域名(如
admin.example.com),在对应location /中加auth_basic "Restricted"; auth_basic_user_file /etc/nginx/.htpasswd; - 对 API 域名(如
api.example.com),加limit_req zone=api burst=10 nodelay;防刷 - 所有域名共用的 CSP、Referrer-Policy 等 header,仍写在 server 块顶层
验证与防冲突要点
配置完成后务必执行两步检查:
- 运行
nginx -t:确保无语法错误,且没有两个server块监听相同 IP+端口组合(例如不能有两个listen 443 ssl;) - 用
curl -I http://example.com和curl -I https://example.com分别测试响应头,确认 HSTS、CSP、X-Content-Type-Options 等已生效 - 检查日志是否记录了 SSL handshake 成功,以及是否有 “no suitable protocol” 类错误


















