为了在网站上启用HTTPS, 我们需要从证书颁发机构获取证书文件。以往,普通个人用户获取证书比较困难。尽管有些证书机构提供免费证书,但只能用于单域名,且有效期比较短,不是很实用。Let`s Encrypt是一个公共的颁发免费SSL证书的机构,由Mozilla、Cisco、Akamai、IdenTrust、EFF等组织人员发起,主要的目的也是为了推进网站从HTTP向HTTPS过度的进程,目前已经有越来越多的商家加入和赞助支持。到目前为止,Let's Encrypt可以应用且支持包括FireFox、Chrome在内的主流浏览器的兼容和支持,也有不少的用户在自有网站项目中正式使用。

Let’s Encrypt 由于是非盈利性的组织,需要控制开支,他们搞了一个非常有创意的事情,设计了一个 ACME 协议,目前该协议的版本是 v1。那为什么要创建 ACME 协议呢,传统的 CA 机构是人工受理证书申请、证书更新、证书撤销,完全是手动处理的。而 ACME 协议规范化了证书申请、更新、撤销等流程,只要一个客户端实现了该协议的功能,通过客户端就可以向 Let’s Encrypt 申请证书,也就是说 Let’s Encrypt CA 完全是自动化操作的。任何人都可以基于 ACME 协议实现一个客户端,官方推荐的客户端是Certbot

Let`s Encrypt的证书配置

Let`s Encrypt和传统CA机构一样,支持常用的三种证书:

1)单域名证书:证书只能用于单个域名。

2)SAN证书:证书可以用于多个域名(Let`s Encrypts)的限制是20。例如证书可以作为:www.example1.com, abc.example1.com, www.example2.com等多个域名的证书。

3)通配符证书:证书可以作为带有通配符的域名的证书。例如:*.example.com的通配符证书可以为abc.example.com, bcd.exmaple.com等域名同时提供证书。通配符证书只有ACME v2版本协议支持,因此需要客户端支持v2版本协议。

对于个人用户,在主机不是很多的情况下,单域名证书或者SAN证书完全可以满足需求,但对于大企业来说,其注册域名下的子域名可能非常多。因此,需要使用通配符证书来为所有子域名提供凭据。

配置准备

在配置Let`s Encrypt证书之前,需要做一些准备工作,如安装git, 准备python环境。如果已经安装,则可直接看下一步。

#检查系统是否安装git,如果已经自带有git会出现git版本号,没有则需要我们自己安装
git  --version 
#git 安装
yum install git


#检查Python的版本是否在2.7以上
python -v //2.6版本
#安装python所需的包
yum install zlib-devel
yum install bzip2-devel
yum install openssl-devel
yum install ncurses-devel
yum install sqlite-devel
#获取到Python
cd /usr/local/src
wget https://www.python.org/ftp/python/2.7.12/Python-2.7.12.tar.xz
#解压Python2.7.12
tar -zxvf Python-2.7.12.tar.xz
#编译python
cd Python-2.7.12/
./configure --prefix=/usr/local/python2.7
make && make install
#建立链接
ln -s /usr/local/python2.7/bin/python2.7 /usr/local/bin/python
#解决系统 Python 软链接指向 Python2.7 版本后,因为yum是不兼容 Python 2.7的,所需要指定 yum 的Python版本
# vi /usr/bin/yum 
将头部的
#!/usr/bin/python
改成
#!/usr/bin/python2.6.6

客户端安装

Let`s Encrypt的证书通过其客户端进行申请安装。建议大多数具有命令行访问权限的人使用 Certbot ACME 客户端。它可以在不下线您的服务器的前提下自动执行证书颁发和安装。对于不需要自动配置的用户,Certbot 还提供专家模式。它易于使用,适用于许多操作系统,并且具有出色的文档。访问 Certbot 官网 以获取针对于操作系统和 Web 服务器的订制文档。在没有命令行访问权限的情况下,最好的办法是使用您托管服务提供商提供的内置功能。如果您的托管服务提供商提供 Let’s Encrypt 支持,他们可以帮助您申请免费证书,安装并配置自动续期。对于某些提供商,这是您需要在控制面板/联系客服打开的设置。其他一些提供商会自动为其所有客户请求和安装证书。

我们在自己的服务主机上进行测试,首先安装let`s encrypt官方客户端。注意,只有0.22.0版本以上的客户端才支持v2版本协议。若已安装较早版本,则需要对其进行升级。

# 通过git安装Let`s Encrypt客户端,也可以下载Release包后解压
git clone https://github.com/letsencrypt/letsencrypt

# 注意,最新版中已经去掉了-V选项,查看版本使用 --version 选项
# 若已安装较早版本,则需要使用-V命令,自动对其进行升级
./certbot-auto -V
Upgrading certbot-auto 0.21.1 to 0.22.0...
Replacing certbot-auto... 

# 查看版本
./certbot-auto -V
certbot 0.22.0 

若系统环境准备不足,则会在第一次运行certbot-auto命令时自动进行安装相关依赖包。如下:

选择同意安装依赖

查看账户

由于ACME v2 和 v1 协议是互相不兼容的,已经安装过客户端的主机使用 v2 版本客户端,需要创建另外一个账户(代表客户端操作者),以 Certbot 客户端为例,可以通过tree命令查看客户端所有账户。

$ tree /etc/letsencrypt/accounts 
.
├── acme-staging.api.letsencrypt.org
├── acme-v01.api.letsencrypt.org
└── acme-v02.api.letsencrypt.org

为了实现通配符证书,v2版本协议中Let's Encrypt  在申请者身份校验上做了很大的改变。

  • 有了订单 ID 的概念,主要是为了追踪通配符域名。

申请限制,在 V1 版本,Let's Encrypt 为了避免滥操作,对申请证书有一些限制(很难学习,但是正常使用不会遇到该限制)。而 v2 版本,对于通配符证书,多了一个限制,New Orders per Account(每个证书订单数限制)。


域名所有权校验

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

  • dns-01:给域名添加一个 DNS TXT 记录。
  • http-01:在域名对应的 Web 服务器下放置一个 HTTP well-known URL 资源文件。
  • tls-sni-01:在域名对应的 Web 服务器下放置一个 HTTPS well-known URL 资源文件。

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

证书申请

使用下面的命令申请证书。

# 跳转到客户端安装目录下
cd /letsencrypt

# 证书申请
./certbot-auto certonly  -d *.yourdomain.top --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory

命令中的参数含义如下:

certonly,表示安装模式,Certbot 有安装模式和验证模式两种类型的插件。
--manual 表示手动安装插件,Certbot 有很多插件,不同的插件都可以申请证书,用户可以根据需要自行选择
-d 为那些主机申请证书,如果是通配符,输入 *.yourdomain.top(可以替换为你自己的一级域名)
--preferred-challenges dns,使用 DNS 方式校验域名所有权
--server,Let's Encrypt ACME v2 版本使用的服务器不同于 v1 版本,需要显式指定。

命令执行过程中,需要交互:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): youremail@email.com

-------------------------------------------------------------------------------
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

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


Plugins selected: Authenticator manual, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for yourdomain.top

-------------------------------------------------------------------------------
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: y

第一个交互提示输入电子邮件地址用于接收通知,可以按c不输入。第二个交互提示询问是否同意Let`s Encrypt的协议要求,输入A同意。第三个交互提示询问是否要分享邮箱地址。第四个交互提示询问是否对域名和IP进行绑定,输入y同意后才能继续。

接下来会要求进行域名所有权校验。

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

2_8KBE_jXH8nYZ2unEViIcW52LhIqxkg7i9mcwsRvhQ

Before continuing, verify the record is deployed.
-------------------------------------------------------------------------------
Press Enter to Continue
Waiting for verification...
Cleaning up challenges 

由于上一步我们已经选择通过DNS TXT的方式校验域名,所以需要配置DNS TXT记录。上面的输出要求在指定子域名下配置一条TXT记录,在没有确认配置的记录生效前,不要回车执行。配置好的校验域名如下图所示

然后输入下列命令确认TXT记录是否生效。

$ dig  -t txt  _acme-challenge.yourdomain.top @8.8.8.8    

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;_acme-challenge.newyingyong.cn.        IN      TXT

;; ANSWER SECTION:
_acme-challenge.yourdomain.top. 599 IN  TXT     "2_8KBE_jXH8nYZ2unEViIcW52LhIqxkg7i9mcwsRvhQ"

确认生效后,回车继续执行命令,输出如下:

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/newyingyong.cn/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/newyingyong.cn/privkey.pem
   Your cert will expire on 2018-06-12. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot-auto
   again. To non-interactively renew *all* of your certificates, run
   "certbot-auto 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/archive/yourdomain.top"或"/etc/letsencrypt/live/yourdomain.top"目录下。

$ tree /etc/letsencrypt/archive/yourdomain.top 
.
├── cert1.pem
├── chain1.pem
├── fullchain1.pem
└── privkey1.pem

证书校验

证书生成后,可以对证书进行校验,检查证书的信息是否正确,命令如下:

openssl x509 -in  /etc/letsencrypt/archive/newyingyong.cn/cert1.pem -noout -text 

其输出为证书的域名,检查是否为申请时输入的域名。

X509v3 Subject Alternative Name: 
    DNS:*.yourdomain.top

可以看到,证书包含了通配符域名*.yourdomain.top。

证书续签

Let's Encrypt证书是有效期90天的,需要我们自己手工更新续期才可以。命令如下:

 ./letsencrypt-auto certonly --renew-by-default --email youremail@email.com  -d www.yourdomain.top

这样我们在90天内再去执行一次就可以解决续期问题,这样又可以继续使用90天。如果我们怕忘记的话也可以利用linux crontab定时执行更新任务。证书在到期前30天才会续签成功,但为了确保证书在运行过程中不过期,官方建议每天自动执行续签两次;使用crontab自动续期的命令如下:

crontab -e // 编辑定时任务
0 */12 * * * /usr/local/bin/certbot-auto renew --quiet --renew-hook "/etc/init.d/nginx reload"

需要注意"/etc/init.d/nginx reload"为nginx重启命令,需要根据自己服务器的重启命令重启即可;这里建议使用reload,不推荐使用restart,因为这样万一配错了,也不会影响服务器其他项目的运行。

单域名证书可以通过上述脚本完成更新,但通配符证书的更新需要验证域名所有权,否则会报异常“authentication script must be provided with --manual-auth-hook
when using the manual plugin non-interactively.”。这标识我们在自动更新通配符域名时,必须提供一个身份验证脚本来进行dns验证(同上文证书申请中的DNS验证)。

脚本设置可以参考github上大佬开源的更新脚本d

Nginx开启HTTPS

证书生成完成后可以到 /etc/letsencrypt/live/ 目录下查看对应域名的证书文件。编辑 nginx 配置文件监听 443 端口,启用 SSL,并配置 SSL 的公钥、私钥证书路径,如下:

server {
   listen   443 ssl;
   server_name  yourdomain.top;
   root /home/www/you;
   index  index.html index.htm index.php;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/you.cn/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/you.cn/privkey.pem;
    ...
}

添加HTTP自动跳转到HTTPS,配置如下:

server {
    listen 80;
    server_name yourdomain.top;
    location / {
        rewrite ^(.*)$  https://$host$1 permanent;
    }
}

配置好之后,重启nginx即可启用证书,指定域名下的所有二级域名都可以使用。

如果要对ssl进行性能优化,可以参考:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES256-SHA384:AES256-SHA256:RC4:HIGH:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!AESGCM;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

取消证书

可以使用下面的命令取消生成的证书。

certbot revoke --cert-path /etc/letsencrypt/live/you.cn/cert.pem
certbot delete --cert-name you.cn