avatar1 avatar
@{[{user.name}]}
希腊·圣域
since February 1500

Ghost、Nginx设置Lets Encrypt SSL第二弹

先吐个槽୧(˶‾᷄ ⁻̫ ‾᷅˵)୨

LetsEncrypt是由ISRG互联网安全研究小组发起的一个免费、开发、自动化的证书颁发机构,所以安全性毋庸置疑,不像某些毫无节操的证书签发机构或者服务商通公然发放伪造证书,给某些原本毫无信用的垃圾机构的无耻行径添贡献厚厚的一笔,有句话怎么说来着,貌似叫弄巧成拙...

LetsEncrypt现在提供了SSL证书自动授权和管理的一个客户端,并且提供的详细的步骤等等是可以非常容易的安装和管理,不过我用的是Nginx做反向代理服务器,按照官网的nginx配置方法怎么都不成功,在阅读了大量相关文章后终于成功配置成功,一下是详细的配置步骤。

环境信息

服务器:   ubuntu 14.04/16.04
反向代理: Nginx 
Ghost:   0.11.8  

安装certbot

可以参考certbot的官方网站

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update
$ sudo apt-get install certbot 

第一次配置nginx

通过certbot自动授权证书的时候certbot服务器需要验证服务器的有效性,该步骤即为配置nginx以便certbot服务器可以通过验证。

首先备份你nginx的配置文件

cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default_backup

编辑default文件,添加如下信息, 把yourdomain.com/www.yourdomain.com换成你自己的域名。

server {  
    listen 80;
    server_name yourdomain.com www.yourdomain.com;

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

重启nginx

service nginx restart

certbot自动验证和签发SSL数字签名

确保你的服务器可以通过80端口访问。同样yourdomain.com和www.yourdomain.com换成你自己的域名。

如果第一次使用certbot命令时推荐在模拟环境模式运行,certbot现在加入了请求频率限制,一个小时内最多重试5次,如果5次全部失败则要等一个小时后才可以进行下一次请求,在模拟环境下测试通过后再取消模拟模式。启用模拟模式非常简单在certbot后添加 --staging 例如:certbot certonly --staging

运行 certbot certonly --webroot -d yourdomain.com -d www.yourdomain.com

第一次运行会要求填写邮件等一些信息,按照向导填写即可。

运行完成会有一个隐藏的.well-known在/usr/share/nginx/html下创建,这个文件就说certbot用来验证时自动创建的。 并且授权的文件会被储存到一下两个位置:

/etc/letsencrypt/live/yourdomain.com/fullchain.pem

/etc/letsencrypt/live/yourdomain.com/privkey.pem

第二次配置nginx

certbot验证完后,现在可以删除第一次的配置,或者注解掉。

然后改为下面的配置, 注意要把yourdomain.com改为你自己的域名

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

server {  
        listen 443 ssl;
        server_name www.yourdomain.com;
        return 301 $scheme://yourdomain.com$request_uri;

        ssl on;
        ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

        ssl_prefer_server_ciphers On;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;
}

server {  
        listen 443 ssl;

        server_name yourdomain.com;

        root /var/www/ghost;
        client_max_body_size 500M;

        location / {
                proxy_pass http://localhost:2368;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_buffering off;
        }

        ssl on;
        ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

        ssl_prefer_server_ciphers On;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;

        location ~ ^/.well-known {
               root /var/www;
        }
}

重启nginx

到这里SSL证书算基本上完成了,重启ngix service nginx restart,如果没有错误现在你可以通过https访问你的网站了.

自动更新SSL证书

LetsEncrypt的免费SSL的证书有效期为90天,过期不续期则证书即被废弃,所以我们需要在90天之前进行证书的更新,好在现在有certbot的客户端,让自动更新SSL证书变成一个非常简单的事情。

ubuntu有一个自动任务运行的服务器cron,运行 sudo crontab -e 然后 添加一下配置:

18 3 * * 1,5 /usr/bin/certbot renew --quiet --renew-hook "/usr/sbin/service nginx reload"

重新加载cron (这一步也可以省略,cron会自动重新处理,为确保这里手动添加)

service cron reload

上面是的任务会周1周5凌晨3:18检测和自动更新你的SSL证书。

更安全的https服务器

完成以上步骤后就可以通过https信道访问你的网站,不过我们可以通过更安全的密钥交换协议--迪菲-赫尔曼密钥交换(Diffie–Hellman key exchange,缩写为D-H)

运行以下命令:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

该命令可能需要1-2分钟完成运行,完成后密钥会存储在/etc/ssl/certs/dhparam.pem

修改nginx的SSL配置信息改成以下

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;  
        ssl_prefer_server_ciphers on;
        ssl_dhparam /etc/ssl/certs/dhparam.pem;
        ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
        ssl_session_timeout 1d;
        ssl_session_cache shared:SSL:50m;
        ssl_stapling on;
        ssl_stapling_verify on;
        add_header Strict-Transport-Security max-age=15768000;

保存退出然后重启nginx

写在最后的( •̀ .̫ •́ )✧

上面的内容主要借鉴了以下三片文章,再结合我自己的实际情况总结下来的。

https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-14-04

https://robertnealan.com/setting-up-ssl-for-ghost-on-digitalocean-with-lets-encrypt/

https://certbot.eff.org/#ubuntutrusty-nginx