Nginx实现www到非www全路径重定向(无需SSL检查)问题排查
问题
我希望在Nginx中无需检查SSL证书即可实现从www到非www的全路径重定向,但当前配置存在异常。
我的Nginx配置如下:
server { listen 80; listen [::]:80; server_name domain.com www.example.com; location /.well-known/acme-challenge/ { root /var/www/certbot/; } location / { if ($host ~ "^www\.(.*)$") { return 301 $https://$1$request_uri; } return 301 https://$host$request_uri; } } server { listen 443 default_server ssl http2; listen [::]:443 ssl http2; server_name example.com www.example.com; if ($host ~ "^www\.(.*)$") { return 301 https://$1$request_uri; } ssl_certificate /etc/nginx/ssl/live/example.com/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/live/example.com/privkey.pem; location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://nodeserver:3333/; rewrite ^(/static/media/)(.+)$ https://some$1$2 last; } }
我预期实现以下重定向行为:
a) http://example.com => https://example.com b) http://example.com?abc => https://example.com?abc c) http://example.com/test => https://example.com/test d) http://www.example.com => https://example.com e) https://www.example.com?abc => https://example.com?abc f) https://www.example.com/test => https://example.com/test
但最后一项f)无法正常工作,请求停留在https://www.example.com/test并显示Cannot establish a secure connection错误。请问我的配置哪里存在问题?
解决方案
问题出在两个核心点:
80端口server块的域名配置错误
你当前server_name domain.com www.example.com;里把主域名写成了domain.com,应该改为example.com,否则HTTP请求的重定向逻辑会出现匹配异常。SSL证书不包含www子域名,导致握手失败
当用户访问https://www.example.com/test时,Nginx会先执行SSL握手,这一步在重定向规则之前。你的证书仅针对example.com,没有覆盖www.example.com,浏览器会因为证书域名不匹配直接拒绝建立连接,根本轮不到执行重定向规则,这就是Cannot establish a secure connection错误的根源。
解决步骤:
- 更新SSL证书:确保证书同时包含
example.com和www.example.com(SAN证书)。如果用Certbot申请,可重新执行命令:certbot certonly -d example.com -d www.example.com获取双域名证书。 - 修正80端口server_name:将
server_name domain.com www.example.com;改为server_name example.com www.example.com;。 - 优化重定向规则(推荐):避免用
if判断,拆分出单独的server块处理www的HTTPS请求,逻辑更清晰高效。
优化后的完整配置示例:
# 处理所有HTTP请求,统一转HTTPS server { listen 80; listen [::]:80; server_name example.com www.example.com; location /.well-known/acme-challenge/ { root /var/www/certbot/; } return 301 https://$host$request_uri; } # 专门处理www.example.com的HTTPS请求,直接重定向到非www server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name www.example.com; ssl_certificate /etc/nginx/ssl/live/example.com/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/live/example.com/privkey.pem; return 301 https://example.com$request_uri; } # 处理非www的HTTPS请求,反向代理到后端服务 server { listen 443 default_server ssl http2; listen [::]:443 ssl http2; server_name example.com; ssl_certificate /etc/nginx/ssl/live/example.com/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/live/example.com/privkey.pem; location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://nodeserver:3333/; rewrite ^(/static/media/)(.+)$ https://some$1$2 last; } }
调整后,所有HTTPS请求的SSL握手会先正常完成(证书覆盖双域名),www请求会被正确重定向到非www,彻底解决f)的问题。
内容的提问来源于stack exchange,提问作者Tgnc
相关产品推荐
相关产品推荐

