Date Modified Tags nginx

1. Introduction

前两天收到letsencrypt的邮件,说https快到期了,抓紧更新一下。我记得用linux的crontab开启自动更新https证书了,怎么还会收到?浏览器看了下证书日期,的确快要到期了,发现是nginx没有重启,证书缓存没有更新。

本文记录了使用LNMP搭建的博客添加https的过程,也可以参看uwsgi的配置

2. HTTPS普及

使用https有哪些好处?

  • 防止运营商劫持,家庭网络宽带运营商经常干这事
  • HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。
  • HTTPS是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本。

缺点是什么?

  • 降低网站速度(尽管现在有很多技术可以提高)
  • 配置可能麻烦

let's encrypt这个项目通过自动化,把ssl证书使用简单化了。本文就以针对个人用户免费的let's encrypt项目作为示范,官方的自动化工具certbot上https的步骤:

  • 在vps上安装certbot
  • 创建配置文件
  • 执行证书自动化命令

3. 配置HTTPS

3.1 下载certbot

不同的浏览器和不同的webserver可以在certbot上看到相应的教程。

我的vps操作系统是 debian 8.0,但是源里并没有certbot工具,因此需要直接下载可执行文件

wget https://dl.eff.org/certbot-auto
chmod a+x certbot-auto

3.2 certbot验证的过程

certbot实际上在你的webroot下建立了.well-known/acme-challenge/目录,在验证的时候,会在此目录下生成一些验证文件,然后通过在外部访问你网站的这个文件,如果正确获得了,那么验证通过,并将生成的文件都删除掉。

因此,.well-known目录的权限很重要,比如lnmp安装的话,在root下执行certbot-auto,那么目录默认www用户是没有权限访问的,会导致验证失败,因此需要在nginx里对这个目录做特殊排除

修改nginx中你的域名的配置文件,比如在lnmp中,默认是/usr/local/nginx/conf/vhost/,而通过apt默认安装的nginx,配置文件则在/etc/nginx/conf.d/,在配置文件中添加如下内容:

location ^~ /.well-known {
    allow all;
}

表示针对这个目录,允许所有人查看,如果配置文件中含有

location ~ /\.
{
    deny all;
}

则需要在此段之前。

注意修改以后,别忘了通过service nginx -s reload重启nginx。

3.3 对域名签发证书

3.3.1 一个网站目录映射多个域名

比如我的findhao.net 和findhao.net 以及www.的都是一个网站目录(webroot),在nginx的配置文件里,是通过

server_name findhao.net www.findhao.net findhao.net;

来实现映射的,那么使用certbot签发,只需要运行:

certbot-auto certonly --webroot -w /home/wwwroot/findhao.net -d findhao.net -d findhao.net -d www.findhao.net -d www.findhao.net

则就会进入自动验证的过程。 -w是webroot,-d是domain的缩写。

3.3.2 多个域名多个webroot

如果有好几个域名需要签发,而且每个域名的webroot(域名的文件存放目录)是不一样的,那就需要运行多次certbot-auto -w a_domain_webroot -d a_domain。我们也可以给多域名多目录生成一个证书,即一次生成多个域名的一个证书。命令其实和3.3.1是一样的,只不过几个域名的验证文件是相同的。

出现

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/www.findhao.net/fullchain.pem. Your cert will
   expire on 2017-09-30. To obtain a new or tweaked version of this
   certificate in the future, simply run certbot-auto again. To
   non-interactively renew *all* of your certificates, run
   "certbot-auto renew"

则表示生成成功!

3.4 修改nginx配置文件

生成好了证书,那么还需要让nginx告诉浏览器你的证书。修改你的域名证书,比如/etc/nginx/conf.d/findhao.net.conf:

# 一开始默认只有一个server来监听80端口,现在将80端口的访问转发到https上。
server {
    listen 80 default_server;
    # 监听了多个域名
    server_name  findhao.net www.findhao.net;
    return 301 https://$host$request_uri;
}


server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
# 你的证书地址
    ssl_certificate /etc/letsencrypt/live/findhao.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/findhao.net/privkey.pem;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
    ssl_prefer_server_ciphers on;
    # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
    add_header Strict-Transport-Security max-age=15768000;
    # OCSP Stapling ---
    # fetch OCSP records from URL in ssl_certificate and cache them
    ssl_stapling on;
    ssl_stapling_verify on;

    server_name findhao.net www.findhao.net ;
    index index.html index.htm index.nginx-debian.html;
# 这部分是表示将原来的域名,重定向到现在新的域名,如果一台vps
    if ($host = 'findhao.net' ) {
        rewrite ^/(.*)$ https://www.findhao.net/$1 permanent;
    }
# 由于使用的是uwsgi,所以需要将数据转发过去。如果是lnmp之类安装,则这里默认没有下面特殊的规则
    location / {
        include      uwsgi_params;
        uwsgi_pass   127.0.0.1:5001; 
        uwsgi_param UWSGI_CHDIR  /root/DownloadYoutube;
        uwsgi_param UWSGI_SCRIPT manage:app; 
      }
}

80端口的监听部分,不建议此时修改,最好在单独测试https可以访问以后,再修改301跳转。

3.5 重启服务

重启nginx服务之前,一定要先用nginx -t检查配置文件是否有语法错误!!

通过service nginx restart 或者nginx -s reload或者systemctl nginx restart

3.6 nginx 支持HTTP2

如果你按照上面的配置文件添加了http2的关键字,那么在进行配置文件检查错误时,会出现:

nginx: [emerg] invalid parameter "http2" in /etc/nginx/conf.d/ssl.conf:2
nginx: configuration file /etc/nginx/nginx.conf test failed

HTTP2最低要求nginx 1.9.5,但是我vps的debian系统,nginx才1.6,因此需要手动升级nginx。

添加nginx的官方源:

#建立/etc/apt/sources.list.d/nginx.list 文件,内容如下
deb http://nginx.org/packages/mainline/debian/ jessie nginx
deb-src http://nginx.org/packages/mainline/debian/ jessie nginx

然后apt update && apt upgrade即可发现nginx要求更新。注意,在upgrade时,可能会出现错误提示,说依赖问题。这是因为新版本的nginx已经没有nginx-commen包了。所以需要先卸载原来的版本:

apt-get remove nginx nginx-common

然后再install nginx即可。

3.7 设置开机启动项

手动更新nginx,那原来的nginx开机启动项就没有了,需要手动编写,现在systemd几乎已经统治了常见的linux发行版,因此/etc/rc.local文件很可能已经没有了。简单学习下systemd的写法即可,你也可以直接用下面官方给的配置文件/lib/systemd/system/nginx.service:

[Unit]
Description=A high performance web server and a reverse proxy server
After=network.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed

[Install]
WantedBy=multi-user.target

添加完成后,

# 重载所有修改过的配置文件
systemctl daemon-reload
# 先杀掉原来的nginx
pkill nginx
# 立即启动一个服务
systemctl start nginx.service
# 如果提示nginx service is masked,那么先解锁
systemctl unmask nginx.service
# 添加开机启动
systemctl enable nginx.servce

去访问下你的网站看是不是已经可以访问https啦

3.8 设置自动更新证书

由于let's encrypt的证书有效期只有三个月,每隔三个月需要更新一次,官方提供的certbot-auto 即可更新。结合linux的crontab工具即可实现,通过crontab -e来编辑定时任务列表:

5 2 10 * * /usr/bin/certbot-auto renew --post-hook "lnmp nginx restart"

每个月的10号2点5分执行后面的命令,在执行/usr/bin/certbot renew之后执行--post-hook的参数,即重启nginx,这里的lnmp是一键安装工具,如果是普通方式安装nginx,直接使用3.5的重启命令即可。注意一定要重启nginx,不然证书更新以后,nginx还是用的原来的缓存。

Reference

Let's Encrypt 给网站加 HTTPS 完全指南

使用 Certbot 自动签发 Let's Encrypt 证书

免费SSL证书Let's Encrypt(certbot)安装使用教程

设置 Nginx 使用 HTTP/2 协议

debian8 编译安装的 nginx 开机自启

Systemd 入门教程:命令篇-阮一峰


文章版权归 FindHao 所有丨本站默认采用CC-BY-NC-SA 4.0协议进行授权|
转载必须包含本声明,并以超链接形式注明作者 FindHao 和本文原始地址:
https://findhao.net/easycoding/2029.html

Comments