克拉米斯遐想

Clamis的流水日记簿

CentOS6下通过Certbot自动部署Let’s encrypt的SSL证书

| 一条评论 | 111,433次浏览

Clamis的这个站点之前就已经用上了Let’s encrypt的免费SSL证书,当时是使用的acme_tiny进行脚本部署和更新。最近在VPS重装后再次上Let’s encrypt官网的时候发现官网已经提供了一个叫做Cerbot的部署程序,因此本次采用Cerbot进行SSL证书生成和更新。但是由于RHEL/CentOS系统下没有预编译好的包直接安装,因此只能手动来进行安装和更新。特记录下本教程留以日后查看。

本教程基于CentOS/RHEL 6系统,Web服务器是Nginx。其他服务器教程可以参考Certbot官网

安装Certbot

环境准备

因为Certbot的很多依赖并不在系统默认Repo中,需要先安装EPEL Repo。
同时为了防止组件过旧导致的报错,建议运行一次 yum update 。

yum install epel-release
yum update

Python升级(可选)

CentOS6默认安装的Python是2.6版本,这个在Certbot运行的时候会有一个警告。

DeprecationWarning: Python 2.6 is no longer supported by the Python core team, please upgrade your Python.

其实这不影响Certbot的运行,但是如果觉得看到这个警告不爽的,可以将Python升级到2.7来解决。

yum install python27 python27-devel python27-virtualenv -y
rm -rf /usr/bin/python
ln -s /usr/local/bin/python2.7 /usr/bin/python #建立软连接,使系统默认的 python指向 python2.7

python -V #重新检验Python 版本

解决系统 Python 软链接指向 Python2.7 版本后,因为yum是不兼容Python 2.7的,所以yum不能正常工作,我们需要指定yum的Python版本

vi /usr/bin/yum

将文件头部的 #!/usr/bin/python 改成 #!/usr/bin/python2.6

下载安装Certbot

因为并没有针对CentOS6的预编译安装包,因此需要通过certbot-auto脚本来获得Certbot。

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

cerbot-auto的运行参数同certbot完全相同,运行后会自动安装certbot相关依赖并自动更新:

./path/to/certbot-auto certonly

注意:cerbot-auto会自动下载最新版并进行安装,如果你希望使用某一特定版本并禁止自动更新的话,请在运行时加上–no-self-upgrade 参数。
另外,如果你对脚本自动从网上下载内容更新有安全顾虑的话,请参考官方关于这个问题的建议

生成证书

Certbot本身支持通过plugin插件的方式进行安装部署证书,但是由于CentOS下目前还不支持自动安装,我们需要手动生成证书。

./path/to/certbot-auto certonly

这个命令可以让你以交互的方式来自己选择插件及选项生成证书。
如果你已经有自己的Web服务器了,建议选择 webroot  插件。

特别注意:
目前版本(0.8.0)的Cerbot交互式生成证书方式有一个bug,当通过交互方式选择webroot 生成证书的时候,webroot-path 不会保存在renewal的config文件中,导致证书更新的时候会因为config配置文件不全而发生错误无法更新。针对这种情况应该使用命令行指定参数的方式来进行证书生成:

#这个示例演示了3个域名使用了两个不同的web-root是如何生成证书的
./path/to/certbot-auto certonly --webroot -w /path/to/webroot1 -d domain.com -d www.domain.com -w /path/to/webroot2 -d test.clamis.net -n

如果一切顺利,生成的证书将会保存在 /etc/letsencrypt/live/domain.com/  下。

自动更新证书

因为Let’s Encrypt证书的有效期只有90天,因此让其自动更新证书就变得势在必行了。
我们先通过下面的命令来验证自动更新:

./path/to/certbot-auto renew --dry-run

如果结果显示更新正常,那就可以将下列命令加入到cron或systemd中自动运行。

./path/to/certbot-auto renew --quiet

注意:如果选择通过cron或者systemd来自动续期,官方建议让其每两天运行一次。
官方解释说这么做是为了防止因为种种原因导致的证书失效问题。不用担心证书频繁更新的问题,因为除非你的证书快到期或者失效了,否则脚本并不会做任何事情。运行的时刻随机制定一个即可。

vim /etc/crontab

11 23 */2 * * ./path/to/certbot-auto renew --quiet

配置 Nginx 加入证书

到这里已经成功一大半了,接下来只需要配置 Nginx 支持刚刚生成的证书。而且这个配置有最佳实践可以参考,访问:Mozilla SSL Configuration Generator,这是 Mozilla 搞得一个 HTTPS 配置文件自动生成器,支持 Apache,Nginx 等多种服务器。

按照这个配置文件,选择 Intermediate  的兼容性。这里生成的配置文件是业界最佳实践和结果,让 Nginx 打开了各种增加安全性和性能的参数。

请根据自己的服务配置修改和添加内容,重点只需要关注5行 ssl_  部分:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
    ssl_certificate /path/to/signed_cert_plus_intermediates;
    ssl_certificate_key /path/to/private_key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
    ssl_dhparam /path/to/dhparam.pem;

    # intermediate configuration. tweak to your needs.
    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;

    ## verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;

    resolver <IP DNS resolver>;

    ....
}

这5行中,部分文件还不存在,逐个说明如下。

ssl_certificate 和 ssl_certificate_key ,分别对应 fullchain.pem  和 privkey.pem ,这2个文件是之前就生成好的证书和密钥。

ssl_dhparam  通过下面命令生成:

sudo mkdir /etc/nginx/ssl
sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048

ssl_trusted_certificate  需要下载 Let’s Encrypt 的 Root Certificates

cd /etc/letsencrypt/live/example.com
sudo wget https://letsencrypt.org/certs/isrgrootx1.pem
sudo mv isrgrootx1.pem root.pem
sudo cat root.pem chain.pem > root_ca_cert_plus_intermediates

resolver 后面,你需要找到域名服务器的提供商,填写域名解析服务器地址,例如我的域名放在 DNSPod 上,域名服务器填写:resolver f1g1ns1.dnspod.net f1g1ns2.dnspod.net;

Nginx 配置完成后重启,用浏览器测试是否一切正常。

至此应该就可以看到URL旁的小绿锁了。

作者:Clamis

我微笑着走向地狱,身后是正在毁灭的天堂

1 评论

  1. Pingback引用通告: 博客开启全站HTTPS(centos7.2 and nginx1.13.1) | konfans的个人站点

发表评论

*为必填字段!