Let’s Encrypt使用

post thumb
Ops
作者 Louis 发表于 2018年11月8日

Let’s Encrypt 及 Certbot 简介

Let’s Encrypt 是 一个叫 ISRG ( Internet Security Research Group ,互联网安全研究小组)的组织推出的免费安全证书计划。参与这个计划的组织和公司可以说是互联网顶顶重要的先驱,除了前文提到的三个牛气哄哄的发起单位外,后来又有思科(全球网络设备制造商执牛耳者)、 Akamai 加入,甚至连 Linux 基金会也加入了合作,这些大牌组织的加入保证了这个项目的可信度和可持续性。

lets-encrypt

尽管项目本身以及有该项目签发的证书很可信,但一开始 Let’s Encrypt 的安全证书配置起来比较麻烦,需要手动获取及部署。存在一定的门槛,没有一些技术底子可能比较难搞定。然后有一些网友就自己做了一些脚本来优化和简化部署过程。 1. 获取 Certbot 客户端

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

2. 配置 nginx 、验证域名所有权

在虚拟主机配置文件/usr/local/nginx/conf/vhost/fenghong.tech.conf中添加如下内容,这一步是为了通过 Let’s Encrypt 的验证,验证 fenghong.tech 这个域名是属于我的管理之下。(具体解释可见下一章“一些补充说明”的“ certbot 的两种工作方式”)


location ^~ /.well-known/acme-challenge/ {  
default_type "text/plain";   
root     /www;
} 
location = /.well-known/acme-challenge/ {   
return 404;
} 

3. 重载 nginx

配置好 Nginx 配置文件,重载使修改生效(如果是其他系统 nginx 重载方法可能不同)

 sudo nginx -s reload 

4. 生成证书

./certbot-auto certonly --webroot -w /www -d  fenghong.tech 

中间会有一些自动运行及安装的软件,不用管,让其自动运行就好,有一步要求输入邮箱地址的提示,照着输入自己的邮箱即可,顺利完成的话,屏幕上会有提示信息。

此处有坑!如果顺利执行请直接跳到第五步,我在自己的服务器上执行多次都提示

connection :: The server could not connect to the client for DV :: DNS query timed out 

发现问题出在 DNS 服务器上,我用的是 DNSpod ,无法通过验证,最后是将域名的 DNS 服务器临时换成 Godaddy 的才解决问题,通过验证,然后再换回原来的 DNSpod 。 证书生成成功后,会有 Congratulations 的提示,并告诉我们证书放在 /etc/letsencrypt/live 这个位置

IMPORTANT NOTES:
 - The following errors were reported by the server:

   Domain: fenghong.tech
   Type:   unauthorized
   Detail: Invalid response from
   http://fenghong.tech/.well-known/acme-challenge/kx-juv4XwQFz1TkhL1xGNda5Nm8_fwa8rQoRUfvS01c:
   "<!DOCTYPE html>\n<html>\n  <head>\n    <meta
   http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\">\n
   <meta http-equiv=\"Co"

   Domain: www.fenghong.tech
   Type:   unauthorized
   Detail: Invalid response from
   http://www.fenghong.tech/.well-known/acme-challenge/B0jELU0RmyeEt9xA9FKi6NTxj4m5PjJlvx4iCXNR4d8:
   "<!DOCTYPE html>\n<html>\n  <head>\n    <meta
   http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\">\n
   <meta http-equiv=\"Co"

   To fix these errors, please make sure that your domain name was
   entered correctly and the DNS A/AAAA record(s) for that domain
   contain(s) the right IP address.

这个问题是因为自己的A记录是指向了github.io,导致配置文件根本读取不到,取消gitub的A记录即可,保持自己的A记录指向自己的IP哦!

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at   /etc/letsencrypt/live/fenghong.tech/fullchain.pem. Your cert   will expire on 2019-02-0. To obtain a new version of the   certificate in the future, simply run Let's Encrypt again.

5. 配置 Nginx(修改 /usr/local/nginx/conf/vhost/fenghong.tech.conf),使用 SSL 证书

listen 443 ssl;
server_name fenghong.tech www.fenghong.tech;
index index.html index.htm index.php;
root  /www; 
ssl_certificate      /etc/letsencrypt/live/fenghong.tech/fullchain.pem;
ssl_certificate_key  /etc/letsencrypt/live/fenghong.tech/privkey.pem;

上面那一段是配置了 https 的访问,我们再添加一段 http 的自动访问跳转,将所有通过 http://www.fenghong.tech 的访问请求自动重定向到 https://fenghong.tech

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

6. 重载 nginx,大功告成,此时打开网站就可以显示绿色小锁了

 sudo nginx -s reload 

♦后续工作

出于安全策略, Let’s Encrypt 签发的证书有效期只有 90 天,所以需要每隔三个月就要更新一次安全证书,虽然有点麻烦,但是为了网络安全,这是值得的也是应该的。好在 Certbot 也提供了很方便的更新方法。

  1. 测试一下更新,这一步没有在真的更新,只是在调用 Certbot 进行测试
./certbot-auto renew --dry-run 

如果出现类似的结果,就说明测试成功了(总之有 Congratulations 的字眼)

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/wiki.fenghong.tech/fullchain.pem (success)
  /etc/letsencrypt/live/fenghong.tech/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)
  1. 手动更新的方法
./certbot-auto renew -v 
  1. 自动更新的方法
./certbot-auto renew --quiet --no-self-upgrade 

♦一些补充说明解释

1、certbot-auto 和 certbot

certbot-auto 和 certbot 本质上是完全一样的;不同之处在于运行 certbot-auto 会自动安装它自己所需要的一些依赖,并且自动更新客户端工具。因此在你使用 certbot-auto 情况下,只需运行在当前目录执行即可

./certbot-auto 

2、certbot的两种工作方式

certbot (实际上是 certbot-auto ) 有两种方式生成证书:

  • standalone 方式: certbot 会自己运行一个 web server 来进行验证。如果我们自己的服务器上已经有 web server 正在运行 (比如 Nginx 或 Apache ),用 standalone 方式的话需要先关掉它,以免冲突。
  • webroot 方式: certbot 会利用既有的 web server,在其 web root目录下创建隐藏文件, Let’s Encrypt 服务端会通过域名来访问这些隐藏文件,以确认你的确拥有对应域名的控制权。

本文用的是 webroot 方式,也只推荐 webroot 方式,这也是前文第二步验证域名所有权在 nginx 虚拟主机配置文件中添加 location 段落内容的原因。

试了下这个脚本,在它的基础上改了一些,签发/更新比较方便(其实就是重新签发)。核心是使用diafygi/acme-tiny,相对于certbot复杂以及各种环境检查,安装一堆东西,这个Python写的工具我感觉好用多了,在傻瓜式和使用上选择了一个折中合适的点。

一个快速获取/更新 Let’s encrypt 证书的 shell script


调用 acme_tiny.py 认证、获取、更新证书,不需要额外的依赖。

下载到本地

wget https://raw.githubusercontent.com/oldthreefeng/scripts/master/lets-encrypt/letsencrypt.conf
wget https://raw.githubusercontent.com/oldthreefeng/scripts/master/lets-encrypt/letsencrypt.sh
chmod +x letsencrypt.sh

配置文件

只需要修改 DOMAIN_KEY DOMAIN_DIR DOMAINS 为你自己的信息

ACCOUNT_KEY="letsencrypt-account.key"
DOMAIN_KEY="example.com.key"
DOMAIN_DIR="/var/www/example.com"
DOMAINS="DNS:example.com,DNS:whatever.example.com"
#ECC=TRUE
#LIGHTTPD=TRUE

执行过程中会自动生成需要的 key 文件。其中 ACCOUNT_KEY 为账户密钥, DOMAIN_KEY 为域名私钥, DOMAIN_DIR 为域名指向的目录,DOMAINS 为要签的域名列表, 需要 ECC 证书时取消 #ECC=TRUE 的注释,需要为 lighttpd 生成 pem 文件时,取消 #LIGHTTPD=TRUE 的注释。

运行

./letsencrypt.sh letsencrypt.conf

注意

需要已经绑定域名到 /var/www/example.com 目录,即通过 http://example.com http://whatever.example.com 可以访问到 /var/www/example.com 目录,用于域名的验证

将会生成如下几个文件

lets-encrypt-x1-cross-signed.pem
example.chained.crt          # 即网上搜索教程里常见的 fullchain.pem
example.com.key              # 即网上搜索教程里常见的 privkey.pem 
example.crt
example.csr

在 nginx 里添加 ssl 相关的配置

ssl_certificate     /path/to/cert/example.chained.crt;
ssl_certificate_key /path/to/cert/example.com.key;

cron 定时任务

每个月自动更新一次证书,可以在脚本最后加入 service nginx reload等重新加载服务。

0 0 1 * * /etc/nginx/certs/letsencrypt.sh /etc/nginx/certs/letsencrypt.conf >> /var/log/lets-encrypt.log 2>&1  && nginx -s reload

多个域名处理

我有aaa.com和bbb.com,在同一个主机里进行https证书生成,这时,我们生成两个比如aaa.conf和bbb.conf.生成两个文件后,脚本运行两次即可。当然配置文件内容请看上面的信息,按需更改。 利用crontab 进行每月更新,具体如上,就不赘述了。

./letsencrypt.sh aaa.conf
./letsencrypt.sh bbb.conf

lets-dns

下载

wget https://github.com/xdtianyu/scripts/raw/master/le-dns/le-dnspod.sh
wget https://github.com/xdtianyu/scripts/raw/master/le-dns/dnspod.conf
chmod +x le-dnspod.sh

配置

dnspod.conf 文件内容

TOKEN="YOUR_TOKEN_ID,YOUR_API_TOKEN"
RECORD_LINE="默认"
DOMAIN="example.com"
CERT_DOMAINS="example.com www.example.com im.example.com"
#ECC=TRUE

修改其中的 TOKEN 为您的 dnspod api token ,注意格式为123456,556cxxxx。 修改 DOMAIN 为你的根域名,修改 CERT_DOMAINS 为您要签的域名列表,需要 ECC 证书时请取消 #ECC=TRUE 的注释。

运行

[root@aliyun_file nginx]# ./le-dnspod.sh dnspod.conf 
# INFO: Using main config file dnspod.conf
+ Account already registered!
# INFO: Using main config file dnspod.conf
Processing www.fenghong.tech with alternative names: wiki.fenghong.tech cloud.fenghong.tech
 + Creating new directory ./certs/www.fenghong.tech ...
 + Signing domains...
 + Generating private key...
 + Generating signing request...
 + Requesting new certificate order from CA...
 + Received 3 authorizations URLs from the CA
 + Handling authorization for cloud.fenghong.tech
 + Handling authorization for www.fenghong.tech
 + Handling authorization for wiki.fenghong.tech
 + 3 pending challenge(s)
 + Deploying challenge tokens...
cloud.fenghong.tech MszO0HsThuxa2OD5JOggj3xodgCjwhRybBpKaDUjarM gpxslsY3Hl9croCAQBHYUOveXZpuwoPaZlvqtzOMtBg
_acme-challenge.cloud.fenghong.tech
fenghong.tech 69699373
_acme-challenge.cloud:391234194
UPDATE RECORD
DNS UPDATE SUCCESS
www.fenghong.tech rGUqFsbLKL8ygoZSjn-6iMrP6LriMaaMwqcD5iI0MLc jxbDA17eWGgxq1gydYyh1mZ0Y-1UxP3KmASkg5vV4oA
_acme-challenge.www.fenghong.tech
fenghong.tech 69699373
_acme-challenge.www:391234826
UPDATE RECORD
DNS UPDATE SUCCESS
wiki.fenghong.tech Tpx0U3AJxgC3k7jfr2kUPTPcRVYV4hyaH6uWhikfFDo Hs7rqkI5sDhLjAPe7Q8gpYt6PW2Ov6eV1U4-sKurwaU
_acme-challenge.wiki.fenghong.tech
fenghong.tech 69699373
_acme-challenge.wiki:391218779
UPDATE RECORD
DNS UPDATE SUCCESS
 + Responding to challenge for cloud.fenghong.tech authorization...
 + Challenge is valid!
 + Responding to challenge for www.fenghong.tech authorization...
 + Challenge is valid!
 + Responding to challenge for wiki.fenghong.tech authorization...
 + Challenge is valid!
 + Cleaning challenge tokens...
 + Requesting certificate...
 + Checking certificate...
 + Done!
 + Creating fullchain.pem...
 + Done!

最后生成的文件在当前目录的 certs 目录下

cron 定时任务

如果证书过期时间不少于30天, letsencrypt.sh 脚本会自动忽略更新,所以至少需要29天运行一次更新。

每隔20天(每个月的5号和25号)自动更新一次证书,可以在 le-dnspod.sh 脚本最后加入 service nginx reload等重新加载服务。

0 0 5/20 * * /etc/nginx/le-dnspod.sh /etc/nginx/le-dnspod.conf >> /var/log/le-dnspod.log 2>&1

注意 ubuntu 16.04 不能定义 day of month 含有开始天数的 step values,可以替换命令中的 5/205,25

更详细的 crontab 参数请参考 crontab.guru 进行自定义 下载文件

其它参考

上一篇
程序员的知识管理