用Certbot申请免费Let's Encrypt泛域名证书+自动续期

Updated on with 2,981 views and 0 comments

Let’s Encrypt是一个免费的CA证书颁发机构,从v2版本协议开始支持泛域名证书申请。

什么是通配符证书

在没有出现通配符证书之前,Let’s Encrypt 支持两种证书。

  1. 单域名证书:证书仅仅包含一个主机。
  2. SAN 证书:一张证书可以包括多个主机(Let’s Encrypt 限制是 20),也就是证书可以包含下列的主机:www.example.com、www.example.cn、blog.example.com等等。

证书包含的主机可以不是同一个注册域,不要问我注册域是什么?注册域就是向域名注册商购买的域名。

对于个人用户来说,由于主机并不是太多,所以使用 SAN 证书完全没有问题,但是对于大公司来说有一些问题:

  • 子域名非常多,而且过一段时间可能就要使用一个新的主机。
  • 注册域也非常多。

读者可以思考下,对于大企业来说,SAN 证书可能并不能满足需求,类似于 sina 这样的网站,所有的主机全部包含在一张证书中,而使用 Let’s Encrypt 证书是无法满足的。

Let’s Encrypt 通配符证书

通配符证书就是证书中可以包含一个通配符,比如 .example.com、.example.cn,读者很快明白,大型企业也可以使用通配符证书了,一张证书可以防止更多的主机了。

下载

我们通过 certbot-auto 自动生成工具来操作。

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

生成证书

./certbot-auto certonly --email 邮箱 -d 域名 -d 域名2 --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory  

`certonly` 表示安装模式,Certbot 有安装模式和验证模式两种类型的插件。

--manual 表示手动交互模式,Certbot 有很多插件,不同的插件都可以申请证书,用户可以根据需要自行选择

-d 为那些主机申请证书,如果是通配符,输入 *.xxxx.com (可以替换为你自己的域名)

--preferred-challenges 使用 DNS 方式校验域名所有权

--server Let's Encrypt ACME v2 版本使用的服务器不同于 v1 版本,需要显示指定。

操作交互流程

  1. 是否同意 Let's Encrypt 协议要求,按y同意确认

  2. 询问是否对域名和机器(IP)进行绑定按y绑定

  3. 域名验证 dns 解析增加 TXT 配置,对申请域名添加TXT解析,名称为_achme-challenge,值为交互模式所给出的值,具体如下图

    sslpng

    创建成功 /etc/letsencrypt/live/xxxx.com/ 下会生成 4 个文件,请勿更改 ssl 文件位置,这样可以减少自动续期时的操作

    ssl_certpng

    cert.pem - Apache服务器端证书
    chain.pem - Apache根证书和中继证书
    fullchain.pem - Nginx所需要ssl_certificate文件
    privkey.pem - 安全证书KEY文件
    Nginx环境,就只需要用到fullchain.pem和privkey.pem两个证书文件

测试证书

openssl x509 -in /etc/letsencrypt/live/xxxx.com/fullchain.pem -noout -text

nginx 配置

增加 443 端口监听

listen 443 ssl; 

增加 ssl 配置

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_session_cache builtin:1000 shared:SSL:10m;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
ssl_prefer_server_ciphers on;
ssl_certificate /etc/letsencrypt/live/xxxx.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xxxx.com/privkey.pem;
ssl_session_timeout 5m;
ssl_session_tickets on;
ssl_stapling on;
ssl_stapling_verify on; `ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_session_cache builtin:1000 shared:SSL:10m;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
ssl_prefer_server_ciphers on;
ssl_certificate /etc/letsencrypt/live/xxxx.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xxxx.com/privkey.pem;
ssl_session_timeout 5m;
ssl_session_tickets on;
ssl_stapling on;
ssl_stapling_verify on;` 

#### http 强制跳转 https

server
    {
        listen 80 ;
        server_name www.xxxx.com;
        rewrite ^(.*)$  https://$host$1 permanent; 
    } 

nginx 重新加载配置

service nginx reload

续期

因为有效期只有 3 个月我们需要自动续期来延长有效期。

通配证书只能通过 dns 的方式验证域名归属,我们需要通过脚本自动完成验证 --manual-auth-hook 设定验证脚本,否则无法自动更新

./certbot-auto renew --cert-name willh.cn --manual-auth-hook /home/certbot-sh/au.sh --dry-run

重要提示:为避免遇到操作次数的限制,加入 dry-run 参数,可以避免操作限制,等执行无误后,再进行真实的 renew 操作。

au.sh脚本具体参考https://github.com/ywdblog/certbot-letencrypt-wildcardcertificates-alydns-au

有了这两个脚本,我们就可以通过 crontab 每月定时执行一次续期,并重新加载 nginx 配置。

crontab -e

添加定时任务

0 0,12 * * * python -c 'import random; import time; time.sleep(random.random() * 3600)' && 脚本路径/certbot-auto renew --manual --preferred-challenges dns --manual-auth-hook 脚本路径/au.sh --renew-hook "/usr/local/nginx/sbin/nginx -s reload"