Let's Encrypt 是国外一个公共的免费 SSL 项目,该项目是为了普及 HTTPS 而发起的,目前已经被 Mozilla、Google、Microsoft 和 Apple 等主流浏览器支持,对 HTTPS 技术的普及有着巨大贡献。随着 HTTPS 的普及,Let's Encrypt 已经成为全球最受欢迎的免费 SSL 证书签发机构。
注意事项
- Let's Encrypt 的基础证书只提供了数据加密,不验证身份,从而也无法证明网站的所有者,虽然已经满足绝大部分应用场景,但若涉及核心功能时还是需要进行身份验证
- Let's Encrypt 签发的证书一次的有效期为 3 个月,需要定期更新证书(官方推荐两个月左右更新一次,本文有提供自动更新方案)
安装 EPEL 仓库
Let's Encrypt 的签发证书工具在 EPEL 仓库中才能找到,所以如果没有安装 EPEL 仓库的话要先安装一下
# 查询是否已安装 epel 仓库
rpm -qa epel-release
# 若没有安装再安装 epel 仓库
sudo yum install -y epel-release
安装签发证书工具
用 Certbot 工具申请 Let's Encrypt 证书,要先安装该工具:
sudo yum install certbot-nginx
如果报以下错误:
ImportError:No module named 'requests.packages.urllib3'
执行以下命令解决:
# 如果没有 pip 可使用 `sudo yum install python-pip` 安装
pip install --upgrade --force-reinstall 'requests==3.6.0' urllib3
申请证书
I. 网站运行在申请 SSL 证书的服务器上
这边将申请证书分为两种情况,正常情况下我们使用第一种就好了,也就是网站运行在申请 SSL 证书的服务器上。另外就是比如在 A 机器上申请证书,但网站运行在 B 机器上,当然如果你是用 Docker 跑的 Nginx 也得用第二种方式
- 第一种方式有以下几个条件:
- 你要申请 SSL 证书的域名已经指向到申请证书服务器的 ip
- 你的 Web 服务器需要使用 Nginx(在本例子中,可以在官网查看其它服务器的方式)
- Nginx 配置完成,并且已经绑定了你要申请 SSL 证书的域名
具备以上条件,就可以执行以下操作啦:
# 申请 SSL 证书,certonly 表示只生成证书,不做额外操作
sudo certbot --nginx certonly
certbot 会自动查找当前 Nginx 上的虚拟主机,并提示:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org
Which names would you like to activate HTTPS for?
-------------------------------------------------------------------------------
1: xxx.wolfcode.cn
-------------------------------------------------------------------------------
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1
如果出现以下错误:
# Saving debug log to /var/log/letsencrypt/letsencrypt.log
# The nginx plugin is not working; there may be problems with your existing configuration.
# The error was: NoInstallationError()
可能是因为找不到 nginx 命令,解决方案:
# 以下命令是分别将 nginx 安装目录的 nginx 命令与配置文件软连接到指定文件
# 你可以根据自己的具体情况修改目录
ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx
ln -s /usr/local/nginx/conf /etc/nginx
还有可能提示无法连接到你的服务器,主要要开放防火墙的 443 端口
看到前面正确提示,出现我的 Nginx 上绑定的一个域名,如果你的 Nginx 有绑定多个,那么列表中也会以多个显示,然后输入你需要申请 SSL 证书对应域名的序号即可,验证成功后 Let's Encrypt 就会立即给你签发 SSL 证书,成功后提示:
# Obtaining a new certificate
# Performing the following challenges:
# tls-sni-01 challenge for g.wangchujiang.com
# Waiting for verification...
# Cleaning up challenges
#
# IMPORTANT NOTES:
# - Congratulations! Your certificate and chain have been saved at:
# /etc/letsencrypt/live/xxx.wolfcode.cn/fullchain.pem
# Your key file has been saved at:
# /etc/letsencrypt/live/xxx.wolfcode.cn/privkey.pem
# Your cert will expire on 2018-03-29. 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/xxx.wolfcode.cn/fullchain.pem
/etc/letsencrypt/live/xxx.wolfcode.cn/privkey.pem
# 过期时间:Your cert will expire on 2018-06-19.
# 你的证书将在 2018-06-19 过期
# 可以使用如下命令更新证书有效期
certbot renew --dry-run
配置 Nginx,让所有 HTTP 请求转发到 HTTPS:
# 将 http 请求转发到 https
server {
listen 80;
server_name xxx.wolfcode.cn;
rewrite ^(.*)$ https://$host$1 permanent;
# 禁止在 heaader 中出现服务器版本,防止黑客利用版本漏洞攻击
server_tokens off;
}
# https 的配置
server {
listen 443 ssl;
server_name xxx.wolfcode.cn;
ssl_certificate /etc/letsencrypt/live/xxx.wolfcode.cn/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xxx.wolfcode.cn/privkey.pem;
# 禁止在 heaader 中出现服务器版本,防止黑客利用版本漏洞攻击
server_tokens off;
# 设置ssl/tls会话缓存的类型和大小。如果设置了这个参数一般是shared,buildin可能会参数内存碎片,默认是none,和off差不多,停用缓存。如shared:SSL:10m表示我所有的nginx工作进程共享ssl会话缓存,官网介绍说1M可以存放约4000个sessions。
ssl_session_cache shared:SSL:1m;
# 客户端可以重用会话缓存中ssl参数的过期时间,内网系统默认5分钟太短了,可以设成30m即30分钟甚至4h。
ssl_session_timeout 5m;
# 选择加密套件,不同的浏览器所支持的套件(和顺序)可能会不同。
# 这里指定的是OpenSSL库能够识别的写法,你可以通过 openssl -v cipher 'RC4:HIGH:!aNULL:!MD5'(后面是你所指定的套件加密算法) 来看所支持算法。
ssl_ciphers HIGH:!aNULL:!MD5;
# 设置协商加密算法时,优先使用我们服务端的加密套件,而不是客户端浏览器的加密套件。
ssl_prefer_server_ciphers on;
location / {
root /www/html/website;
index dist/index.html;
}
error_page 404 /404.html;
location = /404.html {
root html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
到此就配置完成啦,使用 HTTPS 访问看看吧
II. 网站运行在申请 SSL 证书以外的服务器上
为其他主机上的网站或 Docker 中的网站申请 SSL 证书,只需要多一步验证即可:
# 申请证书
# certonly 只生成证书,不做额外操作
# --manual 交互式操作,也就是追加验证条件
sudo certbot certonly --manual
提示让你输入想要申请证书的域名
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org
Please enter in your domain name(s) (comma and/or space separated) (Enter 'c'
to cancel): xxx.wolfcode.cn
接着会提示需要记录你申请 SSL 证书域名对应服务器的 IP,问你是否同意:
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for ninghao.net
-------------------------------------------------------------------------------
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
然后会给一个字符串,让你将字符内容保存在一个文件内,并可以通过它所指定的 URL 进行访问,cretbot 会对该 URL 进行校验
-------------------------------------------------------------------------------
Create a file containing just this data:
HNIVXWGNL99iXcy5zI9OwSZmugf0xnv786nw5HchlJ4.n3Pm5l0vxnRwAslvOBBkXT1rGGJ7AwbTnaSCsSiQJFc
And make it available on your web server at this URL:
http://wolfcode.cn/.well-known/acme-challenge/HNIVXWGNL99iXcy5zI9OwSZmugf0xnv786nw5HchlJ4
-------------------------------------------------------------------------------
Press Enter to Continue
比如我这个,则可以在 website 根目录创建:
# 创建验证文件夹
mkdir -p /yourwebsite/.well-known/acme-challenge/
# 进入该文件夹
cd /yourwebsite/.well-known/acme-challenge/
# 创建文件(以下两部内容请修改为你自己的数据)
touch HNIVXWGNL99iXcy5zI9OwSZmugf0xnv786nw5HchlJ4
# 将提示信息写入文件
echo "HNIVXWGNL99iXcy5zI9OwSZmugf0xnv786nw5HchlJ4.n3Pm5l0vxnRwAslvOBBkXT1rGGJ7AwbTnaSCsSiQJFc" > HNIVXWGNL99iXcy5zI9OwSZmugf0xnv786nw5HchlJ4
验证通过之后便会签发证书:
Waiting for verification...
Cleaning up challenges
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/wolfcode.cn/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/wolfcode.cn/privkey.pem
Your cert will expire on 2018-03-29. 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
到此证书申请便完成了,Nginx 配置可以参考上面的配置
添加定时任务完成自动更新
现在证书申请、配置都已经完成了,并且也可以正常访问,但还有个小问题就是 Let's Encrypt 签发的证书只有 90 天的有效期,到期后需要再更新,此时便可以使用到 linux 上的 crontab 工具来定时帮我们完成更新操作
certbot 为我们提供了很方便的更新方式,你只需要执行如下命令:
# 更新所有证书
sudo certbot renew --dry-run
使用以上命令便可以将所有证书更新,那么此时我们可以添加一个定时任务来完成这一操作:
# 进入定时任务存放目录
cd /etc/cron.d
# 将脚本写入文件,该脚本是每 2 个月的 20 号凌晨 2:15 执行一次
echo "15 2 20 */2 * certbot renew --dry-run" > certbot-auto-renew-cron
# 将脚本加入到 crontab
crontab certbot-auto-renew-cron
至此,SSL 证书就算彻底完成啦