Nginx配置HTTPS踩坑全记录,差点把网站搞挂

无双博客 技术教程 1
Nginx配置HTTPS踩坑全记录,差点把网站搞挂

Nginx配置HTTPS踩坑全记录,差点把网站搞挂

上周给我的博客加HTTPS,本以为半小时搞定,结果折腾了一整个下午。写下来给同样折腾的人提个醒。

申请证书

我用的是Let's Encrypt,certbot一键申请嘛,能有什么问题?

问题出在我之前把80端口关了。certbot验证域名的时候需要通过80端口放一个验证文件,端口关了自然验证不过。报错信息还特别不明确,就说什么"connection refused",我一开始还以为是防火墙的问题。

开80端口之后证书申请很顺利。但这时候我犯了个蠢——没看certbot的输出就以为它会自动配置Nginx。实际上certbot只生成了证书文件,Nginx配置还是得自己改。

配置Nginx

改配置的时候我参考了一篇2022年的教程,里面推荐了这个配置:

server {
    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ...
}

看着没问题对吧?我改完之后 nginx -t 测试通过,reload。然后网站就打不开了。

原因是我把原来的 listen 80 那个server块删了!以为有了443就不需要80了。但实际上很多用户访问的时候还是输入 http:// 开头的URL,80端口不监听的话这些请求直接被拒绝了。

正确的做法是保留80端口的server块,加一个301跳转到443:

server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

这一步解决之后网站能通过HTTPS访问了,我松了口气。结果发现CSS全炸了。

混合内容问题

浏览器在你用HTTPS访问的时候,如果页面里有HTTP的资源(图片、脚本、CSS),它会拦截。这就是所谓的"混合内容"。

我博客里有一堆旧的图片链接还是 http:// 开头的……还有一个百度统计的JS也是http的。改起来倒是不难,但烦的是你要一个一个找。

后来发现一个技巧:在head里加 <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> 可以自动把HTTP请求升级为HTTPS。但这个只是临时方案,正经还是要改源文件里的链接。

HSTS

最后加上了HSTS头,告诉浏览器"以后都用HTTPS访问我":

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

但注意!加上这个之后如果你想回退到HTTP,浏览器在一年内都会强制用HTTPS访问。所以先小max-age试几天,确认没问题了再加大。

最终配置

我最后的Nginx配置大概长这样(简化版):

server {
    listen 80;
    server_name blog.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name blog.example.com;
    
    ssl_certificate /etc/letsencrypt/live/blog.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/blog.example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    
    add_header Strict-Transport-Security "max-age=31536000" always;
    
    root /var/www/blog;
    index index.html;
}

整个过程大概4个小时,其中3个半小时在排查问题。但弄完之后看着地址栏那个小锁头,还是挺有成就感的。

对了,别忘了设置证书自动续期!certbot renew --dry-run 跑一下确认cron任务正常就行。忘了这步的话3个月后证书过期,你就又得折腾一遍了……

上一篇网站设计避坑指南:简约不等于简陋

下一篇当前分类已是最新一篇

发布评论 0条评论)

  • Refresh code

还木有评论哦,快来抢沙发吧~