因为 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/
引维基百科的说法
超文本传输安全协议(英语:Hypertext Transfer Protocol Secure,缩写:HTTPS )是一种网络安全传输协议。在计算机网络上,HTTPS 经由超文本传输协议进行通信,但利用 SSL/TLS 来对数据包进行加密。HTTPS 开发的主要目的,是提供对网络服务器的身份认证,保护交换数据的隐私与完整性
HTTPS 的主要思想是在不安全的网络上创建一安全信道,并可在使用适当的加密包和服务器证书可被验证且可被信任时,对窃听和中间人攻击提供合理防护。
HTTPS 的信任继承基于预先安装在浏览器中的证书颁发机构(如 Symantec、Comodo、GoDaddy 和 GlobalSign 等)(意即“我信任证书颁发机构告诉我应该信任的”)。因此,一个到某网站的 HTTPS 连接可被信任,当且且当:
HTTP 协议传输的数据都是未加密的,也就是明文的,因此使用 HTTP 协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了 SSL ( Secure Sockets Layer )协议用于对 HTTP 协议传输的数据进行加密,从而就诞生了 HTTPS。简单来说,HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,要比 HTTP 协议安全。
HTTPS 和 HTTP 的区别主要如下:
Types of SSL Certificates for a Secure Business Website
传输层安全协议(英语:Transport Layer Security,缩写:TLS ),及其前身安全套接层( Secure Sockets Layer,缩写:SSL )是一种安全协议,目的是为互联网通信,提供安全及数据完整性保障
说到底,就是 HTTPS 更安全。甚至为了安全,一个专业可靠的网站,HTTPS 是必须的。Firefox 和 Chrome 都计划将没有配置 SSL 加密的 HTTP 网站标记为不安全(貌似 Firefox 50 已经这么干了),目前它们也正在联合其他相关的基金会与公司推动整个互联网 HTTPS 化,现在大家访问的一些主要的网站。如 Google 多年前就已经全部启用 HTTPS,国内的淘宝、搜狗、知乎、百度等等也全面 HTTPS 了。甚至 Google 的搜索结果也正在给予 HTTPS 的网站更高的排名和优先收录权。
你只需要有一张被信任的 CA ( Certificate Authority )也就是证书授权中心颁发的 SSL 安全证书,并且将它部署到你的网站服务器上。一旦部署成功后,当用户访问你的网站时,浏览器会在显示的网址前加一把小绿锁,表明这个网站是安全的,当然同时你也会看到网址前的前缀变成了 HTTPS,不再是 HTTP 了。
理论上,我们自己也可以签发 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 是 一个叫 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 支持两种证书。
1 )单域名证书:证书仅仅包含一个主机。
2 ) SAN 证书:一张证书可以包括多个主机( Let’s Encrypt 限制是 20 ),也就是证书可以包含下列的主机:www.example.com 、www.example.cn 、blog.example.com 等等。
证书包含的主机可以不是同一个注册域,不要问我注册域是什么?注册域就是向域名注册商购买的域名。
对于个人用户来说,由于主机并不是太多,所以使用 SAN 证书完全没有问题,但是对于大公司来说有一些问题:
读者可以思考下,对于大企业来说,SAN 证书可能并不能满足需求,类似于 sina 这样的网站,所有的主机全部包含在一张证书中,而使用 Let’s Encrypt 证书是无法满足的。
通配符证书就是证书中可以包含一个通配符,比如 .example.com 、.example.cn ,读者很快明白,大型企业也可以使用通配符证书了,一张证书可以防止更多的主机了。
这个功能可以说非常重要,从功能上看 Let’s Encrypt 和传统 CA 机构没有什么区别了,会不会触动传统 CA 机构的利益呢?
为了实现通配符证书,Let’s Encrypt 对 ACME 协议的实现进行了升级,只有 v2 协议才能支持通配符证书。
也就是说任何客户端只要支持 ACME v2 版本,就可以申请通配符证书了,是不是很激动。
在了解该协议之前有几个注意点:
客户在申请 Let’s Encrypt 证书的时候,需要校验域名的所有权,证明操作者有权利为该域名申请证书,目前支持三种验证方式:
而申请通配符证书,只能使用 dns-01 的方式
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 现在需要运行在安装了 Python ( 2.7 or 3.4 )的类 unix 系统上,内存大于 512MB (如果小于的话,官方解决方案),默认是需要 root 权限的,比如写证书操作需要 root 权限。
Certbot 客户机支持获取和安装证书的两种插件:auth
和install
,当使用 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
方式来管理
因为域名在 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
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, $domain
is 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/live
is 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 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
简单介绍 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
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
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.