使用 certbot 代替 acme.sh 免费申请 wildcard 通配符证书和自动更新实践小结

2020-02-20 17:15:29 +08:00
 wsgzao

前言

因为 Google Chrome 和运营商劫持干扰访问者体验的努力推动了大型网站加速应用全站 HTTPS,而Let's Encrypt这个项目通过自动化把配置和维护 HTTPS 变得更加简单,Let's Encrypt 设计了一个 ACME 协议目前版本是 v2,并在 2018 年支持通配符证书Wildcard Certificate Support is Live。官网主推的客户端是Certbot,任何人都可以基于 ACME 协议实现一个客户端,比如大名鼎鼎的acme.sh。本文主要使用certbot-dns-route53插件为例,由于 certbot 官方 DNS Plugins 插件支持有限,如果你需要支持 aliyun/tencentyun/godaddy dns 可以参考certbot-letencrypt-wildcardcertificates-alydns-au,随着 Docker 容器化和 K8S(Kubernetes)的进击,相信会促进 certbot 多样化玩法。

使用 certbot 代替 acme.sh 免费申请 wildcard 通配符证书和自动更新实践小结

更新历史

2020 年 02 月 19 日 - 初稿

阅读原文 - https://wsgzao.github.io/post/certbot/


基础知识

关于 HTTPS

引维基百科的说法

超文本传输安全协议(英语:Hypertext Transfer Protocol Secure,缩写:HTTPS )是一种网络安全传输协议。在计算机网络上,HTTPS 经由超文本传输协议进行通信,但利用 SSL/TLS 来对数据包进行加密。HTTPS 开发的主要目的,是提供对网络服务器的身份认证,保护交换数据的隐私与完整性

HTTPS 的主要思想是在不安全的网络上创建一安全信道,并可在使用适当的加密包和服务器证书可被验证且可被信任时,对窃听和中间人攻击提供合理防护。

HTTPS 的信任继承基于预先安装在浏览器中的证书颁发机构(如 Symantec、Comodo、GoDaddy 和 GlobalSign 等)(意即“我信任证书颁发机构告诉我应该信任的”)。因此,一个到某网站的 HTTPS 连接可被信任,当且且当:

HTTP 和 HTTPS 区别

HTTP 协议传输的数据都是未加密的,也就是明文的,因此使用 HTTP 协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了 SSL ( Secure Sockets Layer )协议用于对 HTTP 协议传输的数据进行加密,从而就诞生了 HTTPS。简单来说,HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,要比 HTTP 协议安全。

HTTPS 和 HTTP 的区别主要如下:

Types of SSL Certificates for a Secure Business Website

关于 TLS/SSL

传输层安全协议(英语:Transport Layer Security,缩写:TLS ),及其前身安全套接层( Secure Sockets Layer,缩写:SSL )是一种安全协议,目的是为互联网通信,提供安全及数据完整性保障

为什么要部署 HTTPS

说到底,就是 HTTPS 更安全。甚至为了安全,一个专业可靠的网站,HTTPS 是必须的。Firefox 和 Chrome 都计划将没有配置 SSL 加密的 HTTP 网站标记为不安全(貌似 Firefox 50 已经这么干了),目前它们也正在联合其他相关的基金会与公司推动整个互联网 HTTPS 化,现在大家访问的一些主要的网站。如 Google 多年前就已经全部启用 HTTPS,国内的淘宝、搜狗、知乎、百度等等也全面 HTTPS 了。甚至 Google 的搜索结果也正在给予 HTTPS 的网站更高的排名和优先收录权。

怎么部署 HTTPS

你只需要有一张被信任的 CA ( Certificate Authority )也就是证书授权中心颁发的 SSL 安全证书,并且将它部署到你的网站服务器上。一旦部署成功后,当用户访问你的网站时,浏览器会在显示的网址前加一把小绿锁,表明这个网站是安全的,当然同时你也会看到网址前的前缀变成了 HTTPS,不再是 HTTP 了。

怎么获得 SSL 安全证书

理论上,我们自己也可以签发 SSL 安全证书,但是我们自己签发的安全证书不会被主流的浏览器信任,所以我们需要被信任的证书授权中心( CA )签发的安全证书。而一般的 SSL 安全证书签发服务都比较贵,比如 Godaddy、GlobalSign 等机构签发的证书一般都需要 20 美金一年甚至更贵,不过为了加快推广 HTTPS 的普及,EEF 电子前哨基金会、Mozilla 基金会和美国密歇根大学成立了一个公益组织叫 ISRG ( Internet Security Research Group ),这个组织从 2015 年开始推出了 Let’s Encrypt 免费证书。这个免费证书不仅免费,而且还相当好用,所以我们就可以利用 Let’s Encrypt 提供的免费证书部署 HTTPS 了

Let’s Encrypt 简介

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

部署 HTTPS 网站的时候需要证书,证书由 CA 机构签发,大部分传统 CA 机构签发证书是需要收费的,这不利于推动 HTTPS 协议的使用。

Let’s Encrypt 也是一个 CA 机构,但这个 CA 机构是免费的!!!也就是说签发证书不需要任何费用。

Let’s Encrypt 由于是非盈利性的组织,需要控制开支,他们搞了一个非常有创意的事情,设计了一个 ACME 协议,目前该协议的版本是 v1。

那为什么要创建 ACME 协议呢,传统的 CA 机构是人工受理证书申请、证书更新、证书撤销,完全是手动处理的。而 ACME 协议规范化了证书申请、更新、撤销等流程,只要一个客户端实现了该协议的功能,通过客户端就可以向 Let’s Encrypt 申请证书,也就是说 Let’s Encrypt CA 完全是自动化操作的。

任何人都可以基于 ACME 协议实现一个客户端,官方推荐的客户端是 Certbot。

Let’s Encrypt 通配符证书

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

1 )单域名证书:证书仅仅包含一个主机。

2 ) SAN 证书:一张证书可以包括多个主机( Let’s Encrypt 限制是 20 ),也就是证书可以包含下列的主机:www.example.comwww.example.cnblog.example.com 等等。

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

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

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

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

这个功能可以说非常重要,从功能上看 Let’s Encrypt 和传统 CA 机构没有什么区别了,会不会触动传统 CA 机构的利益呢?

如何申请 Let’s Encrypt 通配符证书

为了实现通配符证书,Let’s Encrypt 对 ACME 协议的实现进行了升级,只有 v2 协议才能支持通配符证书。

也就是说任何客户端只要支持 ACME v2 版本,就可以申请通配符证书了,是不是很激动。

在了解该协议之前有几个注意点:

客户在申请 Let’s Encrypt 证书的时候,需要校验域名的所有权,证明操作者有权利为该域名申请证书,目前支持三种验证方式:

而申请通配符证书,只能使用 dns-01 的方式

Certbot 简介

What’s Certbot?

Certbot is a free, open source software tool for automatically using Let’s Encrypt certificates on manually-administrated websites to enable HTTPS.

Certbot is made by the Electronic Frontier Foundation (EFF), a 501(c)3 nonprofit based in San Francisco, CA, that defends digital privacy, free speech, and innovation.

Certbot 的官方网站是 https://certbot.eff.org/ ,打开这个链接选择自己使用的 web server 和操作系统,EFF 官方会给出详细的使用方法,如果 DNS 在官方的支持插件列表中可以按官方文档操作,但如果是国内的 DNS 可以参考certbot-letencrypt-wildcardcertificates-alydns-au

DNS plugin's name on the Documentation list

certbot docs

certbot 插件介绍

Certbot 现在需要运行在安装了 Python ( 2.7 or 3.4 )的类 unix 系统上,内存大于 512MB (如果小于的话,官方解决方案),默认是需要 root 权限的,比如写证书操作需要 root 权限。

Certbot 客户机支持获取和安装证书的两种插件:authinstall,当使用 certonly 参数的时候,只会获取证书,并不会安装证,获取的证书位于 /etc/letsencrypt 目录下

主要插件的介绍:

Getting certificates (and choosing plugins)

| Plugin | Auth | Install | Notes | Challenge types (and port) | | --- | --- | --- | --- | --- | | apache | Y | Y | 自动化获取并安装证书 | tls-sni-01 (443) | | webroot | Y | N | 已经有运行的服务,通过验证 webroot 目录来获取证书 | http-01 (80) | | nginx | Y | Y | 使用 nginx 自动获取和安装证书 | tls-sni-01 (443) | | standalone | Y | N | 建立一个 standalone WEB 服务,需要 80 或者 443 端口可用,如果你没有类似 nginx 和 apache 等服务,这很有用 | http-01 (80) or tls-sni-01 (443) | | DNS plugins | Y | N | 通过修改 dns 服务器的 text 记录,来获取证书,野卡证书只能通过此方式获取 | dns-01 (53) | | manual | Y | N | 通过自己给指令获取证书,支持添加定制脚本来完成任务 | http-01 (80), dns-01 (53) or tls-sni-01 (443) |

解析:

插件的具体使用可以参考letsencrypt 证书-管理工具 certbot

我个人推荐选择DNS plugins 或者 manual方式来管理

certbot-dns-route53 实践

因为域名在 Amazon Route 53,所以选择使用 certbot-dns-route53 插件会比较方便,敏感信息都用 xxx 打码了但不影响阅读理解

https://github.com/certbot/certbot/tree/master/certbot-dns-route53

# Create a virtual environment
pip install virtualenv
cd /root
virtualenv certbot
source certbot/bin/activate

# Update its pip and setuptools (VENV/bin/pip install -U setuptools pip) to avoid problems with cryptography's dependency on setuptools>=11.3.

certbot/bin/pip install -U setuptools pip

pip list

Package    Version
---------- -------
pip        20.0.2
setuptools 44.0.0
wheel      0.34.2

# Make sure you have libssl-dev and libffi (or your regional equivalents) installed. You might have to set compiler flags to pick things up (I have to use CPPFLAGS=-I/usr/local/opt/openssl/include LDFLAGS=-L/usr/local/opt/openssl/lib on my macOS to pick up brew's openssl, for example).

pip install certbot-dns-route53

# create aws credentials
mkdir ~/.aws/
vim ~/.aws/credentials
[default]
aws_access_key_id=xxx
aws_secret_access_key=xxx

# generate certificate
certbot certonly \
  -n --agree-tos --email xxx \
  --dns-route53 \
  -d "*.xxx" 

(certbot) [root@xxx ~]# certbot certonly \
>   -n --agree-tos --email xxx  \
>   --dns-route53 \
>   -d "*.xxx"
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Found credentials in shared credentials file: ~/.aws/credentials
Plugins selected: Authenticator dns-route53, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for xxx
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/xxx/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/xxx/privkey.pem
   Your cert will expire on 2020-05-19. 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"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - 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


certbot 证书默认存放路径结构

Where are my certificates

All generated keys and issued certificates can be found in /etc/letsencrypt/live/$domain. In the case of creating a SAN certificate with multiple alternative names, $domainis the first domain passed in via -d parameter. Rather than copying, please point your (web) server configuration directly to those files (or create symlinks). During the renewal, /etc/letsencrypt/liveis updated with the latest necessary files.

# check letsencrypt directory
[root@xxx ~]# tree /etc/letsencrypt/
/etc/letsencrypt/
├── accounts
│   └── acme-v02.api.letsencrypt.org
│       └── directory
│           └── xxx
│               ├── meta.json
│               ├── private_key.json
│               └── regr.json
├── archive
│   └── xxx
│       ├── cert1.pem
│       ├── chain1.pem
│       ├── fullchain1.pem
│       └── privkey1.pem
├── csr
│   ├── 0000_csr-certbot.pem
│   └── 0001_csr-certbot.pem
├── keys
│   ├── 0000_key-certbot.pem
│   └── 0001_key-certbot.pem
├── live
│   ├── xxx
│   │   ├── cert.pem -> ../../archive/xxx/cert1.pem
│   │   ├── chain.pem -> ../../archive/xxx/chain1.pem
│   │   ├── fullchain.pem -> ../../archive/xxx/fullchain1.pem
│   │   ├── privkey.pem -> ../../archive/xxx/privkey1.pem
│   │   └── README
│   └── README
├── renewal
│   └── xxx.conf
└── renewal-hooks
    ├── deploy
    ├── post
    └── pre

15 directories, 18 files

如果是配置 Nginx SSL 证书,通常只需要按照下面这样修改即可

	ssl_certificate /etc/letsencrypt/live/xxx/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/xxx/privkey.pem;

Certbot command-line options

Certbot supports a lot of command line options. Here’s the full list, from certbot --help all:

(certbot) [root@xxx ~]# certbot -h

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  certbot [SUBCOMMAND] [options] [-d DOMAIN] [-d DOMAIN] ...

Certbot can obtain and install HTTPS/TLS/SSL certificates.  By default,
it will attempt to use a webserver both for obtaining and installing the
certificate. The most common SUBCOMMANDS and flags are:

obtain, install, and renew certificates:
    (default) run   Obtain & install a certificate in your current webserver
    certonly        Obtain or renew a certificate, but do not install it
    renew           Renew all previously obtained certificates that are near
expiry
    enhance         Add security enhancements to your existing configuration
   -d DOMAINS       Comma-separated list of domains to obtain a certificate for

  (the certbot apache plugin is not installed)
  --standalone      Run a standalone webserver for authentication
  (the certbot nginx plugin is not installed)
  --webroot         Place files in a server's webroot folder for authentication
  --manual          Obtain certificates interactively, or using shell script
hooks

   -n               Run non-interactively
  --test-cert       Obtain a test certificate from a staging server
  --dry-run         Test "renew" or "certonly" without saving any certificates
to disk

manage certificates:
    certificates    Display information about certificates you have from Certbot
    revoke          Revoke a certificate (supply --cert-name or --cert-path)
    delete          Delete a certificate (supply --cert-name)

manage your account:
    register        Create an ACME account
    unregister      Deactivate an ACME account
    update_account  Update an ACME account
  --agree-tos       Agree to the ACME server's Subscriber Agreement
   -m EMAIL         Email address for important account notifications

More detailed help:

  -h, --help [TOPIC]    print this message, or detailed help on a topic;
                        the available TOPICS are:

   all, automation, commands, paths, security, testing, or any of the
   subcommands or plugins (certonly, renew, install, register, nginx,
   apache, standalone, webroot, etc.)
  -h all                print a detailed help page including all topics
  --version             print the version number
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

certbot 自动更新证书

简单介绍 2 种常见的需求,其他情况如使用容器 renew 的朋友相信应该都不用参考本文了

# 最简单的手动 renew 命令,看到 success 表示成功
certbot renew --force-renewal

(certbot) [root@xxx ~]# certbot renew --force-renewal
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/xxx.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found credentials in shared credentials file: ~/.aws/credentials
Plugins selected: Authenticator dns-route53, Installer None
Renewing an existing certificate

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
new certificate deployed without reload, fullchain is
/etc/letsencrypt/live/xxx/fullchain.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/xxx/fullchain.pem (success)

使用 crontab 定期执行

# 编辑 certbot_renew.sh ,强制更新并重新 reload nginx 加载新证书
vim /root/certbot_renew.sh

#!/bin/bash
certbot renew --force-renew
nginx -s reload

# 如果是 virtualenv 虚拟环境可以这样写

#!/bin/bash
export PATH=$PATH:/usr/local/bin
source /root/source certbot/bin/activate
certbot renew --force-renew
nginx -s reload


# 添加执行权限
chmod a+x /root/certbot_renew.sh

# 设置定时任务自动更新证书,“At 01:01 on day-of-month 1.”
vim /etc/crontab
1 1 1 * * /root/certbot_renew.sh >/root/crontab.log 2>&1

# 如果需要记录日志可以这样写
1 1 1 * * echo `date -R` >> /var/log/certbot.crontab.log; certbot renew --force-renewal >> /var/log/certbot.crontab.log 2>&1; nginx -s reload

# certbot 官方使用 python 产生了一个分钟的随机数,让更新时间随机一些
echo "0 0,12 * * * root python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew" | sudo tee -a /etc/crontab > /dev/null

参考文章

Let’s Encrypt Documentation

acme.sh

Certbot

certbot docs

How To Secure Apache with Let's Encrypt on CentOS 7

How To Secure Nginx with Let's Encrypt on Ubuntu 18.04

How To Secure Apache with Let's Encrypt on Ubuntu 18.04

LET'S ENCRYPT 给网站加 HTTPS 完全指南

申请 Let's Encrypt 通配符 HTTPS 证书

Let's Encrypt 终于支持通配符证书了

Certobot 管理 Let's Encrypt 证书的几个经验

letsencrypt 证书-管理工具 certbot

8197 次点击
所在节点    程序员
57 条回复
flynaj
2020-02-20 18:19:57 +08:00
acme.sh 简单高效。
gearfox
2020-02-20 18:39:16 +08:00
谢谢分享
SingeeKing
2020-02-20 18:49:33 +08:00
好奇的问一下,为啥要用 Certbot 代替 acme.sh ,全文看下来没找到什么特别的优点
GTim
2020-02-20 19:30:46 +08:00
我去,你这是退化啊
crystone
2020-02-20 19:56:22 +08:00
@GTim 同问啊,acme 方便多啊
KENNHI
2020-02-20 19:57:01 +08:00
我说个最简单的,caddy 服务器。
可以代替 Nginx 的大部分功能,语法简单,支持 quic ( http3 ),还支持自动申请证书和自动维护更新证书,自动 https 跳转支持。
举个反代的栗子:
example.com {
proxy / http://127.0.0.1:8080 {
transparent
}
}
已经完成。你的证书将会被自动部署和维护,通过 http 访问网站的用户会被自动跳转到 HTTPS。
ysc3839
2020-02-20 20:12:47 +08:00
acme.sh 主要是不想配置 Python 吧,而且也不依赖 bash,ash 等 shell 也能运行,能在嵌入式设备上跑。能配置 Python 的环境下用 certbot 没什么问题。
LokiSharp
2020-02-20 21:27:51 +08:00
Certbot 包管理就能装
uptime
2020-02-20 21:31:54 +08:00
caddy 了解一下
qile1
2020-02-21 01:02:20 +08:00
Windows 系统好像执行不了这些,最简单方法就是去代理网站上面申请,dns 设置为点鼠标就生成了
qile1
2020-02-21 01:04:20 +08:00
@ysc3839 Windows 系统能运行,无法生成,Windows 系统下 nginx 更没法配置
KENNHI
2020-02-21 08:02:14 +08:00
@uptime 我也提过还有发帖推荐过 caddy,就是好像没多少人感兴趣。宁愿打补丁重新编译 Nginx 也不愿意试一下原生支持 quic 的 caddy ;宁愿顶着 Nginx 复杂难懂的语法复制粘贴删删改改也不愿意尝试一下说人话简单易用的 caddy ;宁愿研究完 acme.sh 再研究 certbot,搞出这么长一篇教程,也不愿尝试一下能够全自动获取维护更新证书的 caddy。(生产环境另算不做讨论)人还是更喜欢自己熟悉的东西,呆在舒适区不想动就会找出 1 万个借口来,例如为自己没什么访问量的博客找一个性能理由 2333
LokiSharp
2020-02-21 09:07:32 +08:00
@KENNHI CentOS 8 上 Nginx 和 certbot 官方源就能装了,caddy acme.sh 还要自己折腾,没必要吧。Nginx 的配置文件我觉得很简单易懂啊,有什么问题?
009694
2020-02-21 11:06:43 +08:00
@LokiSharp acme.sh 一个 curl 就装了。。折腾啥
KENNHI
2020-02-21 11:11:09 +08:00
@LokiSharp 我回想了一下 Nginx 的配置反代要多少行,还有给 Nginx 打 quic 补丁编译安装的过程,caddy 简单很多了。
KENNHI
2020-02-21 11:16:54 +08:00
@LokiSharp 还有如果使用 caddy,可以直接不用管证书这件事了,从申请到更新都和你无关,也不需要 acmesh (就我而言 acmesh 明显比 certbot 香啊,简单到想写都写不出这么长的教程)
LokiSharp
2020-02-21 12:21:19 +08:00
@009694 你装上就完事了?不更新了?
LokiSharp
2020-02-21 12:28:44 +08:00
@KENNHI 他这个教程是没事找事,实际上 apt dnf 装好 certbot 之后就一条命令的事情
LokiSharp
2020-02-21 12:40:49 +08:00
@009694 还有就是 curl 装的东西 SELinux 的上下文还得自己来配
uptime
2020-02-21 15:15:36 +08:00
@LokiSharp #13 你需要打开看一眼 caddy 官网,连官网都不看一眼就不要说话。caddy 就是全自动,就是自动续签,不用命令,不用你操心。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/646155

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX