简介
随着https
越来越火,似乎也将是未来的大势所趋,这几天就抽空把自己的博客也给升级了一下。
部署https
需要有一张被信任的 CA ( Certificate Authority )
也就是证书授权中心颁发的 SSL 安全证书,虽然也可以自己签发SSL
安全证书,但自己签发的安全证书不会被主流的浏览器信任,所以需要被信任的证书授权中心( CA )签发的安全证书。而一般的 SSL 安全证书签发服务都比较贵,比如Godaddy
、 GlobalSign
等机构签发的证书一般都需要20美金一年甚至更贵,不过为了加快推广 https 的普及, EEF 电子前哨基金会
、Mozilla 基金会
和美国密歇根大学
成立了一个公益组织叫ISRG ( Internet Security Research Group )
,这个组织从 2015 年开始推出了 Let’s Encrypt
免费证书,Let’s Encrypt
免费证书有效期为3个月,不过可以无限次续签,作为个人使用已经绰绰有余了,所以这里我选择了 Let’s Encrypt
提供的免费证书来部署 https
。
使用Certbot申请证书
Certbot
是一个易于使用的自动客户端,可为Web服务器提取和部署SSL/TLS
证书。Certbot
由EFF
和其他人开发,作为Let's Encrypt
的客户端,之前被称为“官方Let's加密客户端
或“Let's Encrypt Python客户端
。
访问Certbot
官方网址:https://certbot.eff.org/,选择自己的web server
和操作系统,官方会有相应的使用方式,我是Nginx
+ CentOS 7.5.1804
。
安装Certbot
由于CentOS 7
没有官网教程说的python2-certbot-nginx
插件,因此我并没有使用官网的安装教程,而是使用下面的命令来获取安装插件副本:
wget https://dl.eff.org/certbot-auto
chmod a + x certbot-auto
证书申请
certbot-auto
插件所在目录下使用下列命令生成证书:
./certbot-auto certonly --manual --email myemail@gmail.com -d *.wujx.top --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory
参数解释:
- certonly:表示安装模式,Certbot有安装模式和验证模式两种类型的插件。
- --manual:表示手动安装插件,Certbot有很多插件,不同的插件都可以申请证书,用户可以根据需要自行选择。
- --email:证书申请者邮箱地址。
- -d:为哪些主机申请证书,如果是申请的通配符证书,输入
*.wujx.top
(替换为自己的域名) - --preferred-challenges dns:使用 DNS 方式校验域名所有权。在申请证书的时候,需要校验域名是否当前申请者所有,而校验方式certonly提供了三种:
dns-01
:给域名添加一个 DNS TXT 记录。http-01
:在域名对应的 Web 服务器下放置一个 HTTP well-known URL 资源文件。tls-sni-01
:在域名对应的 Web 服务器下放置一个 HTTPS well-known URL 资源文件。
而申请通配符证书,只能使用dns-01
的方式。
- --server:指定请求的
Let's Encrypt
地址,不同版本可能会出现请求地址不同,所以显式指定。
过程中会出现交互提示,第一条是说明要下载的文件大小,询问是否下载,输入y
确认下载:
Total download size: 71 M
Is this ok [y/d/N]: y
请阅读并同意服务条款,输入A
:
-------------------------------------------------------------------------------
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
是否对域名和机器(IP)进行绑定,选择是
:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
接着出现了一条非常重要的提示,要求配置DNS TXT
记录,从而验证证书申请者是否拥有域名的所有权:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.wujx.top with the following value:
2pwGozLTXn_rSJ-Jto9Er2Kt1K4ydukN7TgKfBZXz_B
Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
上诉提示要求给_acme-challenge.wujx.top
配置一条值为2pwGozLTXn_rSJ-Jto9Er2Kt1K4ydukN7TgKfBZXz_B
的TXT记录,在没有确认TXT记录生效前不要回车执行。
我用的是阿里云的域名服务,登陆阿里云控制台,添加一条域名解析,具体解析设置如下图:
配置完解析记录之后,可以在开一个ssh
连接,先使用dig
工具确认一下TXT记录是否生效,如果没有安装dig
,CentOS 7
下安装dig
的命令是yum install bind-utils
。
输入命令dig -t txt _acme-challenge.wujx.top @8.8.8.8
确认TXT记录是否生效,已生效可见如下信息:
; <<>> DiG 9.9.4-RedHat-9.9.4-72.el7 <<>> -t txt _acme-challenge.wujx.top @8.8.8.8
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22443
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;_acme-challenge.wujx.top. IN TXT
;; ANSWER SECTION:
_acme-challenge.wujx.top. 599 IN TXT "2pwGozLTXn_rSJ-Jto9Er2Kt1K4ydukN7TgKfBZXz_B"
;; Query time: 4192 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Tue Jan 22 00:19:45 CST 2019
;; MSG SIZE rcvd: 109
这时回到之前的地方,按下回车键确认进行下一步,可以看到如下提示:
Waiting for verification...
Cleaning up challenges
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/wujx.top/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/wujx.top/privkey.pem
Your cert will expire on 2019-04-21. 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
至此,证书申请成功,可以查看一下证书保存的目录:
[root@certbot]# tree /etc/letsencrypt/live/wujx.top/
/etc/letsencrypt/live/wujx.top/
├── cert.pem -> ../../archive/wujx.top/cert1.pem
├── chain.pem -> ../../archive/wujx.top/chain1.pem
├── fullchain.pem -> ../../archive/wujx.top/fullchain1.pem
├── privkey.pem -> ../../archive/wujx.top/privkey1.pem
└── README
0 directories, 5 files
可以使用openssl
校验一下证书信息:
openssl x509 -in /etc/letsencrypt/live/wujx.top/cert.pem -noout -text
输出的信息比较多,有一行关键输出如下:
X509v3 Subject Alternative Name:
DNS:*.wujx.top
与预期一致,申请下来的证书对*.wujx.top
整个通配符域名都有效。
Nginx配置
申请完证书之后,需要在Nginx
中进行相应的配置,编辑Nginx
里的域名配置文件,添加SSL
配置:
server {
add_header X-Frame-Options SAMEORIGIN;
listen 443 ssl;
server_name wujx.top www.wujx.top;
ssl on;
ssl_certificate /etc/letsencrypt/live/wujx.top/fullchain.pem; # 证书文件路径
ssl_certificate_key /etc/letsencrypt/live/wujx.top/privkey.pem; # 证书私钥路径
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
# 其他配置省略........
}
保存后重启Nginx
:
nginx -s reload
访问https://www.wujx.top
,网页正常出现没问题。除了上面的配置,还可以在Nginx
中配置HTTP
强制重定向跳转到HTTPS
,在上诉server
块上面在加入一个server
块,写入以下配置:
server{
add_header X-Frame-Options SAMEORIGIN;
listen 80;
server_name wujx.top www.wujx.top;
# rewrite ^(.*)$ https://$host$1 permanent; # 强制将http重定向到https,早期的写法
return 301 https://$server_name$request_uri; # http重定向到https,新写法
}
保存后重启Nginx
:
nginx -s reload
自动续签
申请下来的证书只有三个月的有效期,但可以无限续签,Certbot提供了续签的工具,在加上定时任务,即可做到自动检测自动续签。
使用Linux
内置的crond
服务定时执行续订任务。
编辑当前用户定时任务文件:
crontab -e
在文件中添加新的定时任务:
0 0 3 * * ? /wujx/certbot/certbot-auto renew
参数解释:
- 0 0 3 * * ?:
Cron
表达式,表示每天凌晨三点时执行,可根据自己需要设定执行时间。 - /wujx/certbot/certbot-auto:
Certbot
插件所在完整路径,在第一步进行安装Certbot
时处于哪个目录,下载下来的Certbot
插件就在哪个目录下。 renew
:检查所有已安装的证书是否即将到期并尝试续订它们。
添加完配置任务,保存并使用以下命令查看当前用户的定时任务:
crontab -l
重启crond
:
service crond restart
设置为开机自启动:
systemctl enable crond.service
错误解决
在整个证书申请、部署配置的过程中,我出现了两处错误
错误一:内存分配不足
遇到的第一个错误是我生成证书的时候报了个内存分配不足的错误:
Error downloading packages:
libss-1.42.9-13.el7.x86_64: [Errno 5] [Errno 12] Cannot allocate memory
libkadm5-1.15.1-34.el7.x86_64: [Errno 5] [Errno 12] Cannot allocate memory
libXft-2.3.2-2.el7.x86_64: [Errno 5] [Errno 12] Cannot allocate memory
.........
直接重启了一下服务器:
reboot
顺道修改了一下最大进程数,先查看当前最大进程数:
sysctl kernel.pid_max
设置为无限大:
echo "kernel.pid_max=1000000 " >> /etc/sysctl.conf
sysctl -p
错误二:Nginx配置完无法访问
遇到的第二个问题是在配置完Nginx
后,访问网址却连不上,浏览器提示:
此网站无法提供安全连接 www.wujx.top 发送的响应无效。
尝试运行 Windows 网络诊断。
ERR_SSL_PROTOCOL_ERROR
出现这个问题是因为Nginx
配置里监听了443 HTTPS端口,但却没有强制要求使用443端口使用SSL
连接,所以出现SSL
协议错误连接不上,解决方式是监听443端口配置加上ssl
参数,强制使用SSL
连接:
server {
add_header X-Frame-Options SAMEORIGIN;
listen 443 ssl; # 这里加上ssl参数,强制使用ssl
server_name wujx.top www.wujx.top;
#其他配置省略........
}
Nginx
配置除了出现上诉错误,还有可能出现下面这个错误:
无法访问此网站 www.wujx.top 意外终止了连接。
请试试以下办法:
检查网络连接
检查代理服务器和防火墙
运行 Windows 网络诊断
ERR_CONNECTION_CLOSED
Nginx
错误日志提示:
*720 no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking, client: 21.133.66.122, server: 0.0.0.0:443
这一个错误则是因为在Nginx
的其他server
块配置里面,也有监听443
端口的配置,但它们却没有实际使用,也就是只打开了监听443
端口的配置,却没有配置相关的SSL
证书。
解决方式是检查其他的server
配置,注释掉没有实际使用的监听443端口的配置,或者为该server
配置相关ssl
证书也可以。
注释掉监听443端口配置:
server {
add_header X-Frame-Options SAMEORIGIN;
listen 80;
# listen 443;
# 其他配置省略.........
}