使用Let's Encrypt创建免费SSL证书

准备工作

  • CentOS/7虚拟机
  • 申请域名,比如www.example.com,并将域名指向该虚拟机80端口(需要ICP备案)
  • 保证80和443端口未被占用,certbot在运行过程中会使用这两个端口,当然如果安装了nginx并且你打算使用certbot-nginx插件,那么certbot会借用nginx,也即虽然nginx占用了80和443端口,也是ok的。

安装软件

  • 安装epel-release: sudo yum install epel-release
  • 安装Nginx:sudo yum install nginx
  • 启动Nginx:sudo systemctl start nginx
  • 安装certbot:sudo yum install certbot
  • 安装certbox的nginx插件:sudo yum install certbot-nginxcertbot在运行时会临时性地通过该nginx插件向nginx的配置文件中添加新的配置(server block),用于向Let's Encrypt提供访问端口以完成ACME协议验证。

Let's Encrypt的两种认证方式

在Let‘s Encrypt签发证书时,它需要确定你要申请证书的域名的确是你拥有的,此时Let's Encrypt将向certbot客户端发起挑战(challenge)以验证你对域名的拥有权,有两种方式:

  • 通过运行certbot的服务器与Let's Encrypt服务器通信,如果你配置域名指向该certbot所在的服务器,Let's Encrypt通过直接访问该域名的方式来验证(URL格式为:http://domain/.well-known/acme-challenge/)。这种方式通常用于单一域名的证书,需要certbot运行与域名所指向的服务器上。
  • 通过DNS,如果你拥有该域名,那么Let's Encrypt会让你在该域名下设置一个TXT记录,记录值设置成Let's Encrypt所要求的(在运行certbot时会提示),做到这一点则可以证明你的确拥有对该域名的拥有权。这种方式通常用于通配符证书,certbot无需运行在域名指向的服务器上。

创建证书(以Nginx为例)

运行:

sudo certbot --nginx certonly

certonly表示仅仅生成证书,而不自动更新nginx.conf配置文件。如果希望certbot在生成证书后自动更新nginx.conf文件,则可以:

sudo certbot --nginx 

本文演示第一个命令,即sudo certbot --nginx certonly,此时命令行显示:
Saving debug log to /var/log/letsencrypt/letsencrypt.log Plugins selected: Authenticator nginx, Installer nginx Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel):

此时输入你邮箱地址,命令行显示:

Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A

回答A,此时命令行显示:

Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N

回答YN无所谓,此时命令行显示:

No names were found in your configuration files. Please enter in your domain
name(s) (comma and/or space separated)  (Enter 'c' to cancel): www.example.com

输入www.example.com(请替换为你自己的域名),特别注意此时LetsEncrypt会尝试与该域名通信,因此请保证该域名可以正常访问。

如果一切正常,命令行将输出:

Obtaining a new certificate
Performing the following challenges:
http-01 challenge for www.example.com
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/www.example.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/www.example.com/privkey.pem
Your cert will expire on 2019-03-10. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
"certbot renew"
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
Donating to EFF:                    https://eff.org/donate-le

生成证书成功,包含以下文件:

  • 证书文件: /etc/letsencrypt/live/www.example.com/fullchain.pem
  • 密钥文件: /etc/letsencrypt/live/www.example.com/privkey.pem

读者也可以参考这篇文章。

命令行参数

如果需要在单台机器上为多个域名申请证书,可以在运行certbot命令时指定域名:

sudo certbot --nginx -d admin.example.com certonly

前文中我们使用了certbot-nginx插件,也可以不使用该插件而使用独立的certbot服务器:

sudo certbot --standalone --preferred-challenges http -d admin.example.com

这里的--standalone告诉certbot使用内建的web服务器与Let's Encrypt完成ACME协议通信。而--preferred-challenges可以取http(使用80端口)或者tls-sni(使用443端口)。

Certbot插件

至此,我们已经了解到了certbot有两种插件可以用于完成ACME协议通信,其实还有另外很多插件,比如apache和webroot:

  • nginx:通过修改Nginx配置完成ACME协议
  • standalone:通过certbot内建服务器完成ACME协议,需要占用80或者443端口,意味着先前运行的监听80/443端口的服务器必须停掉,比如tomcat。
  • apache:通过修改Apache配置完成ACME协议
  • webroot:将制定文件夹通过既有web服务器(比如Nginx)暴露给Let's Encrypt完成ACME协议
  • DNS插件:通过调用DNS域名提供商的API接口自动完成ACME协议,
  • Manual:手动完成

apache插件跟nginx原理相似,通过临时性修改apache的配置来完成ACME通信,而webroot通过制定某个目的路径来完成ACME通信。更多细节请参考这里。

查看所有已安装证书

sudo certbot certificates

更新证书

LetsEncrypt生成的证书有效期只有3个月, 因此在到期只看前你需要自己进行re-newal操作以更新证书。

要手动更新证书,再次运行:

sudo certbot --nginx certonly 

此时命令行显示:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: www.example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):

此时certbot自动探测到已有域名证书www.example.com(?好像即便安装了多个证书,此时也只会出现第一个安装的,其他的不在此列,如果要更新其他的证书可以通过certbot的-d参数在命令行中指定),输入1

What would you like to do?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Keep the existing certificate for now
2: Renew & replace the cert (limit ~5 per 7 days)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1

此时可以选择是否保留原证书(选项1)或者覆盖原证书(选项2),可以根据需要完成余下步骤。

如果有多个证书而只想更新其中某个证书:

sudo certbot renew --cert-name www.example.com

使用cron自动更新证书

先保证certbot能够正常工作:

sudo certbot renew --dry-run

如果能看到以下字样:

...
Congratulations, all renewals succeeded.
...

表示certbot能够正常更新证书。

编写cron脚本:

# cat > /etc/cron.d/certbot <<- EOF
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
 
0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(3600))' && certbot -q renew
EOF

以上脚本每天运行2次,但是只有在证书即将过期的时候才会真正执行renew操作。

创建通配符证书

单域名证书在创建时需要将域名指向certbot运行的机器,而通配符证书由于采用了DNS方式进行挑战,因此没有这项限制,可以在任何机器上完成通配符证书的创建。

当前Let's Encrypt中只有https://acme-v02.api.letsencrypt.org/directory向外提供通配符证书服务,如果要为*.example.com生成证书,输入:

sudo certbot --server https://acme-v02.api.letsencrypt.org/directory -d *.example.com --manual --preferred-challenges dns-01 certonly

此时命令行显示:

NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you're running certbot in manual mode on a machine that is not
your server, please ensure you're okay with that.

Are you OK with your IP being logged?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o:

告诉你你的IP将被记载公开日志中,比如回答Y

Please deploy a DNS TXT record under the name
_acme-challenge.example.com with the following value:

4dererVVTRBqzFp0sW1EHH343432B8-fegegdDFA

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

为了验证你的确拥有该域名,此时需要你为自己的example.com设置一个TXT记录,记录名为_acme-challenge,记录值为4dererVVTRBqzFp0sW1EHH343432B8-fegegdDFA,在笔者的阿里云上设置如下:

使用Let's Encrypt创建免费SSL证书_第1张图片
设置DNS的TXT记录

最后显示生成成功:

- Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/example.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/example.com/privkey.pem
   Your cert will expire on 2019-03-10. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

此时生成的证书包含:

  • 证书文件:/etc/letsencrypt/live/example.com/fullchain.pem
  • 密钥文件:/etc/letsencrypt/live/example.com/privkey.pem

请注意,虽然是通配符证书,但是证书文件目录中不是*.example.com,而是example.com

更新通配符证书

有两种方式更新证书:

  • 执行与创建时相同的命令,然后按照提示完成更新证书
  • 使用certbot renew命令

对于第2中方式:

sudo certbot renew --cert-name example.com

如果执行dry run:

sudo certbot renew --cert-name example.com --dry-run

将报错:

Attempting to renew cert (wanghushengri.com) from /etc/letsencrypt/renewal/example.com.conf produced an unexpected error: The manual plugin is not working; there may be problems with your existing configuration.
The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.',). Skipping.
All renewal attempts failed. The following certs could not be renewed:
  /etc/letsencrypt/live/example.com/fullchain.pem (failure)

表示通配符证书不能自动完成更新,此时有两种方式:

  • 手动更新
  • 提供authentication script(笔者还没有研究过,读者可以自行研究)

重要知识点

  • Certbot有2个命令,certbotcertbot-autocertbot是包管理器(比如yum和apt-get等)安装后的命令,而certbot-auto其实是个封装后的脚本,可以自动帮我们安装certbot
  • 在2016年5月份之前,certbotcertbot-auto命令为letsencryptletsencrypt-auto
  • 第一次运行certbot时需要输入你的邮箱地址(账户)和同意协议,如果不想要这些交互,也可以通过--mail--agree-tos命令行参数完成
  • Cerbot有2种类型的插件完成证书申请,一种为Authenticator方式,表示通过ACME协议获得证书后,将证书保存到本地(/etc/letsencrypt目录下);另一种为Installer方式,表示在获得证书后会将证书安装到指定的服务器中,比如Nginx,此时需要启用相应的插件,比如certbot-nginx
使用Let's Encrypt创建免费SSL证书_第2张图片
certbot支持的插件

在底层所有插件都使用以下方式之一完成ACME要求的挑战:

  • http-01:使用80端口
  • tls-sni-01:使用443端口
  • dns-01:使用53端口修改DNS配置

有些插件可以完成多种挑战方式,比如standalone插件可以使用http-01或者tls-sni-01,另外,可以通过--preferred-challenges指定挑战方式。

  • 可以一次性为多个域名生产证书,但是此时所有域名的证书在同一份文件中,如果不想这样,便只有单独运行了
  • 对于单一域名证书,多数情况下推荐使用webroot插件,因为它可以在不影响你的既有web服务器的情况下生成证书。webroot工作原理为:通过既有的web服务器向外暴露访问接口(需要通过域名能访问得到),在运行certbot命令时指定需要向外暴露访问的目录(通过--webroot-path-w指定),cerbot在于Let‘s Encrypt通信过程中会将挑战文件放在指定文件夹(${webroot-path}/.well-known/acme-challenge)下,然后Let’s Encrypt会通过域名访问该文件,请求格式如下:
66.133.109.36 - - [05/Jan/2016:20:11:24 -0500] "GET /.well-known/acme-challenge/HGr8U1IeTW4kY_Z6UIyaakzOkyQgPr_7ArlLgtZE8SX HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"

如果验证成功,即表示你对该域名具有拥有权。

比如web服务器是nginx,域名为www.example.com,先保证http://example.com/能正常访问到nginx资源,我们决定将webroot-path设置成/var/share/html/certbot,此时需要配置nginx:

location /.well-known {

    root /var/share/html/certbot;

}

然后运行命令(这里的certonly是必须的):

sudo certbot certonly --webroot -w /var/share/html/certbot -d www.example.com
  • Certbot官方文档

你可能感兴趣的:(使用Let's Encrypt创建免费SSL证书)