nginx无需手动开启sni,只要openssl≥0.9.8j、编译启用--with-http_ssl_module且各server块独立配置专属证书,sni即自动生效;90%失败源于openssl不支持或版本过低,需用nginx -v | grep -i openssl验证版本,禁用boringssl及老旧openssl。

不需要“开启”SNI,Nginx 本身不提供 sni on 这类配置指令;只要底层 OpenSSL 支持(≥0.9.8j)、编译时启用了 --with-http_ssl_module,且每个 server 块正确绑定专属证书,SNI 就自动生效。
验证 OpenSSL 是否真正支持 SNI
这是 90% 配置失败的根源,不是 Nginx 写错了,而是底层不认 SNI。
- 运行
nginx -V 2>&1 | grep -i openssl,必须看到类似OpenSSL 1.1.1w的明确版本号;若输出为空、显示BoringSSL或OpenSSL 0.9.8e,说明不支持 - 若输出含
TLS SNI support disabled,说明 Nginx 编译时未链接支持 SNI 的 OpenSSL,或 configure 参数漏了--with-http_ssl_module - 在 CentOS 5 或某些精简镜像中,系统自带 OpenSSL 往往太旧,必须手动升级并重编译 Nginx;Ubuntu/Debian 官方包通常没问题,但 nginx.org 提供的 .deb 若链接 BoringSSL,则 SNI 必然失效
每个 server 块必须独立配置证书路径
Nginx 允许你在多个 server 块里写相同的 ssl_certificate 路径,启动也不报错,但运行时只加载第一个块的证书——其余全 fallback,表现就是所有域名都显示同一张证书。
宝塔Linux面板11.8.1为官网当前正式版,新增AI建站能力并经过宝塔网站工程师深度调教,开放自定义AI功能API,同时对WAF进行界面重构和深度优化,提升拦截能力与运维效率。
- 用
certbot时,必须分开执行:certbot --nginx -d site-a.com和certbot --nginx -d site-b.net;不要写成certbot --nginx -d site-a.com -d site-b.net,否则生成的是多域名证书,无法实现按域名选证隔离 -
ssl_certificate和ssl_certificate_key必须指向该域名专属路径,例如/etc/letsencrypt/live/site-a.com/fullchain.pem,不能共用/etc/letsencrypt/live/common.pem -
server_name必须精确匹配证书的 SAN(Subject Alternative Name)或 CN,比如证书只含site-a.com,就写server_name site-a.com;;若要同时支持www.site-a.com,证书也得覆盖它
处理无 SNI 请求的兜底逻辑
老旧设备(如 Windows XP + IE6)、某些 IoT 设备、或直接用 curl https://ip 不加 -servername 时,不会发送 SNI 字段,Nginx 会把请求交给监听 443 端口的第一个 server 块处理,无论 server_name 是什么。
- 建议把最常用或默认站点放在配置文件最前面,或显式标记为
listen 443 ssl http2 default_server; - 可配一张通用兜底证书(如 Let’s Encrypt 的泛域名证书或专用 fallback 证书),避免这类请求触发浏览器证书警告
- 用
openssl s_client -connect your.ip:443 -servername site-a.com -showcerts 2>/dev/null | openssl x509 -noout -subject验证:换不同-servername应返回对应域名的证书主体
反向代理场景下必须透传 SNI
当 Nginx 作为 HTTPS 反向代理(比如转发到后端网关或另一台 HTTPS 服务)时,仅配置前端证书不够;后端也需要根据原始域名选择证书,否则握手失败,报 SSL_do_handshaking failed 或 502。
- 在
location块中启用:proxy_ssl_server_name on;,并紧接设置:proxy_ssl_name $host;(推荐)或proxy_ssl_name $http_x_forwarded_host;(CDN 场景) - 避免写死静态值,如
proxy_ssl_name "api.example.com";,除非所有流量都指向同一后端域名 - 若用
upstream块定义后端,$host在 SSL 握手阶段不可解析,此时必须写死字符串:proxy_ssl_name "bucket-a.example.com";,且该值需与后端证书 SAN 完全一致
最容易被忽略的是:配置写对 ≠ 实际生效。SNI 行为发生在 TLS 握手最开始,浏览器缓存、中间 CDN、甚至本地 hosts 修改都可能干扰验证结果;务必用 openssl s_client 直连 IP 测试,绕过所有中间层。










