Let’s Encrypt是一个免费的CA证书颁发机构,从v2版本协议开始支持泛域名证书申请。
什么是通配符证书
在没有出现通配符证书之前,Let’s Encrypt 支持两种证书。
- 单域名证书:证书仅仅包含一个主机。
- 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 版本,需要显示指定。
操作交互流程
- 是否同意 Let’s Encrypt 协议要求,按y同意确认
- 询问是否对域名和机器(IP)进行绑定按y绑定
- 域名验证 dns 解析增加 TXT 配置,对申请域名添加TXT解析,名称为_achme-challenge,值为交互模式所给出的值。
- 创建成功 /etc/letsencrypt/live/xxxx.com/ 下会生成 4 个文件,请勿更改 ssl 文件位置,这样可以减少自动续期时的操作
cert.pem – Apache服务器端证书
chain.pem – Apache根证书和中继证书
fullchain.pem – Nginx所需要ssl_certificate文件
privkey.pem – 安全证书KEY文件
Nginx环境,就只需要用到fullchain.pem和privkey.pem两个证书文件
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
使用脚本生成及续期
以阿里云为例,我们需要建立一个api来进行域名解析等操作,进入阿里云控制台,访问控制,创建用于控制dns的用户,限制变成访问即可,创建自定义权限,下方贴出进具备解析,查询等权限的自定义权限
下面策略是对当前账户下所有的dns具备增删改查dns的权限
{ "Version": "1", "Statement": [ { "Action": [ "alidns:DescribeSiteMonitorIspInfos", "alidns:DescribeSiteMonitorIspCityInfos", "alidns:DescribeSupportLines", "alidns:DescribeDomains", "alidns:DescribeDomainNs", "alidns:GetTxtRecordForVerify", "alidns:AddDomainRecord", "alidns:UpdateDomainRecord", "alidns:DescribeDomainRecordInfo", "alidns:UpdateDomainRecordRemark", "alidns:DeleteSubDomainRecords", "alidns:SetDomainRecordStatus", "alidns:DescribeDomainGroups" ], "Resource": "acs:alidns:*:*:domain/xingensheng.com", "Effect": "Allow" } ] }
执行生成命令
./certbot-auto certonly –no-self-upgrade -d *.willh.cn -d willh.cn –manual –preferred-challenges dns –manual-auth-hook “/home/certbot-sh/au.sh python aly add” –manual-cleanup-hook “/home/certbot-sh/au.sh python aly clean” –dry-run
因为有效期只有 3 个月我们需要自动续期来延长有效期。
通配证书只能通过 dns 的方式验证域名归属,我们需要通过脚本自动完成验证 –manual-auth-hook 设定验证脚本,否则无法自动更新
./certbot-auto renew --no-self-upgrade --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"
openssl 查看证书详情命令
打印证书的过期时间 openssl x509 -in signed.crt -noout -dates 打印出证书的内容: openssl x509 -in cert.pem -noout -text 打印出证书的系列号 openssl x509 -in cert.pem -noout -serial 打印出证书的拥有者名字 openssl x509 -in cert.pem -noout -subject 以RFC2253规定的格式打印出证书的拥有者名字 openssl x509 -in cert.pem -noout -subject -nameopt RFC2253 在支持UTF8的终端一行过打印出证书的拥有者名字 openssl x509 -in cert.pem -noout -subject -nameopt oneline -nameopt -escmsb 打印出证书的MD5特征参数 openssl x509 -in cert.pem -noout -fingerprint 打印出证书的SHA特征参数 openssl x509 -sha1 -in cert.pem -noout -fingerprint 把PEM格式的证书转化成DER格式 openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER 把一个证书转化成CSR openssl x509 -x509toreq -in cert.pem -out req.pem -signkey key.pem 给一个CSR进行处理,颁发字签名证书,增加CA扩展项 openssl x509 -req -in careq.pem -extfile openssl.cnf -extensions v3_ca -signkey key.pem -out cacert.pem 给一个CSR签名,增加用户证书扩展项 openssl x509 -req -in req.pem -extfile openssl.cnf -extensions v3_usr -CA cacert.pem -CAkey key.pem -CAcreateserial 查看csr文件细节: openssl req -in my.csr -noout -text