概要
目前很多浏览器默认都会标记http访问的网站为不安全,https部署已经称为大趋势,我之前利用业余时间搭建了一个网站,本文就以这个域名为基础说明如何给网站加上证书。本文使用的操作系统centos、软件使用nginx、域名是bingimg.cn
什么是 Let's Encrypt
当我们要为网站加上https的访问时,我们必须申请https证书,证书的申请一般是要去有证书颁发资质的机构(CA)去申请,并且在CA申请的证书一般需要按年缴一定的维护费用,作为个人搭建的学习型网站,我们找到了一个免费的证书颁发组织,Let's Encrypt 就是一个由非营利性组织 互联网安全研究小组(ISRG)提供的免费、自动化和开放的证书颁发机构(CA)。
简单的说,借助 Let's Encrypt 颁发的证书可以为我们的网站免费启用 HTTPS(SSL/TLS) 。Let's Encrypt免费证书的签发/续签都是脚本自动化的,官方提供了几种证书的申请方式方法,点击此处 快速浏览。官方推荐使用 Certbot 客户端来签发证书,这种方式可参考文档自行尝试,不做评价。我这里直接使用第三方客户端 acme.sh 申请,据了解这种方式可能是目前 Let's Encrypt 免费证书客户端最简单、最智能的 shell 脚本,可以自动发布和续订 Let's Encrypt 中的免费证书。
为了实现自动化证书管理Let's Encryp制订了ACME 协议,这个协议是 Let's Encrypt 实现证书签发流程自动化的根本。目前ACME 协议已正式成为 IETF 标准(RFC 8555)。而acme.sh是一个第三方的脚本工具,其实现了ACME协议的内容。本文我们将使用这个工具来下载,安装,部署证书。
安装 acme.sh
首先我们需要将acme.sh工具安装在在系统上,安装很简单,一条命令:
curl https://get.acme.sh | sh
整个安装过程进行了以下几步(这是安装命令自动完成的),了解一下即可:
1. 把 acme.sh
安装到当前用户的主目录$HOME下的.acme.sh
文件夹中,即~/.acme.sh/
之后所有生成的证书也会放在这个目录下;
2. 创建了一个指令别名alias acme.sh=~/.acme.sh/acme.sh
这样我们可以通过acme.sh
命令方便快速地使用 acme.sh
脚本;
3. 自动创建cronjob定时任务, 每天 0:00 点自动检测所有的证书,如果快过期了,则会自动更新证书。
安装命令执行完毕后,执行acme.sh --version
确认是否能正常使用acme.sh
命令。
https://github.com/Neilpang/acme.sh
v2.7.9
如有版本信息输出则表示环境正常;如果提示命令未找到,执行source ~/.bashrc
命令重载一下环境配置文件。
整个安装过程不会污染已有的系统任何功能和文件,所有的修改都限制在安装目录~/.acme.sh/
中,这个脚本被安装之后,会自动往crontab中添加一条定时任务,我的机器上看到的是下面这条:
48 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
生成证书
据 acme.sh 官方文档介绍,其实现了 acme 协议支持的所有验证协议,一般有两种方式验证:http 和 dns 验证。
也就是我们有两种选择签发证书,这里我直接选择 http 验证方式,另外一种方式本篇不做介绍,可参考文档自行尝试。
签发证书也很简单,一条命令:
acme.sh --issue -d bingimg.cn -d www.bingimg.cn -w /data/bingimg/static
简单解释下这条命令涉及的几个参数:
- --issue是 acme.sh 脚本用来颁发证书的指令;
- -d是--domain的简称,其后面须填写已备案的域名;
- -w是--webroot的简称,其后面须填写网站的根目录
最后一个 -w 参数其实不一定非要是网站的根目录,只不过指定的这个目录,随后acme.sh会将一个文件放到这个目录下,并且尝试去访问这个目录的这个文件,只要我们配置nginx让他能够访问到就可以,不一定非要是根目录。不过我经过上面的设置之后,报错了:
按照提示我们添加一个 --debug
选项之后继续运行这个命令,以便能看到详细的报错信息:
acme.sh --issue -d bingimg.cn -d www.bingimg.cn -w /data/bingimg/static --debug
其提示从网站根目录访问他生成的文件路径访问不到,因为我们指定的目录是 /data/bingimg/static
这个并不是网站根目录,我们只需配置一下nginx让他能够访问到这个文件即可,重新配置nginx之后再次运行上面的acme.sh命令,输出没有任何报错,知道最后成功,最后的输出如下:
生成好之后如果发现少了一个域名,需要另外在生成一个域名,因为之前已经生成过两个域名,在生成会报错,我们可以加上参数 --force
强制重新生成:
acme.sh --issue -d bingimg.cn -d www.bingimg.cn -d pc.bingimg.cn -w /data/bingimg/static --debug --force
可以看出我们加了一个域名 pc.bingimg.cn
但是报错,看报错的意思是,没有找到这个域名的dns记录,所以我们只需要在域名解析服务那里为这个域名添加一条dns记录,在重新运行上面的命令就可以了。到此证书下载成功,我们生成的证书可以给 bingimg.cn、www.bingimg.cn、pc.bingimg.cn
这3个域名使用,证书被放在 /root/.acme.sh/bingimg.cn/
目录下。另外我们可以通过下面的命令查看和删除已经生成的证书:
# 查看证书列表
acme.sh --list
# 删除证书
acme.sh remove <SAN_Domains>
安装证书
下面我们就将下载下来的证书安装到网站上,这里主要说明如何将证书安装到nginx上,其他 webserver 请参考 acme.sh 文档自行实践。废话不多说,进入本节正题。
上一小节,生成的证书放在了 /root/.acme.sh/bingimg.cn
目录,因为这是 acme.sh 脚本的内部使用目录,而且目录结构可能会变化,所以我们不能让 Nginx 的配置文件直接读取该目录下的证书文件。
正确的做法就是使用 --installcert
命令,指定目标位置,然后证书文件会被 copy 到相应的位置。一条命令即可解决:
acme.sh --installcert -d bingimg.cn \
--key-file /etc/nginx/certinfo/bingimg.cn.key \
--fullchain-file /etc/nginx/certinfo/fullchain.cer \
--reloadcmd "service nginx force-reload"
我们之前生成的证书是在目录/root/.acme.sh/bingimg.cn
下面,从上面的截图可以看到,这个目录下有4个文件,我们在生成证书的时候指定了3个域名,生成的这个证书可以被用在这3个域名上,并且生成证书的时候第一个 -d bingimg.cn
表示的是主域名,后面的是 SAN 域名。如果需要用一个证书保护多个域名的情况,有2种办法,第一种办法就是使用SAN证书,就像我们这里生成的证书一样,可以在生成证书的时候指定多个域名,其中第一个是主域名,后面的是需要被保护的SAN域名,一个SAN证书最多可以保护500个域名,这这些域名之间可以没有关系,例如 abc.com
和 222.com
这两个域名可以被放在一个 SAN 证书中。另一种是使用泛域名证书例如 *.abc.com
的证书可以被用来保护主域名和无数个 abc.com
的二级子域名。安装之后成功输出下面内容:
这里我将证书放到了/etc/nginx/certinfo/
目录,这个目录本身没有,我们需要手工创建,当然也可以自行指定。
最后一步就是,修改 Nginx 配置文件启用 ssl,修改完成后需要重启下 Nginx,这一块不再详述。Nginx 配置请参考:
# 监听80端口,对所有 http://bingimg.cn 和 http://www.bingimg.cn 的请求都301转向到 https://www.bingimg.cn 上
server {
listen 80;
server_name bingimg.cn,www.bingimg.cn;
return 301 https://www.bingimg.cn$request_uri;
}
# 监听443端口,对所有 https://bingimg.cn 的请求301转向到 https://www.bingimg.cn 上,这个不用配置ssl证书
server {
listen 443 ;
server_name bingimg.cn; # 这个跳转的https的server块里面不需要配置证书,不知道为什么,当请求上来之后第一步不是建立ssl连接吗,那就应该需要证书才对吧,然而确实不需要
return 301 https://www.bingimg.cn$request_uri;
}
# 监听443端口,接受所有 https://www.bingimg.cn 的请求
server {
listen 443 default_server ssl; # 这里必须要加上 default_server
server_name www.bingimg.cn;
ssl on;
ssl_certificate /etc/nginx/certinfo/fullchain.cer; # 这里配置上证书的路径
ssl_certificate_key /etc/nginx/certinfo/bingimg.cn.key;
..... other config .....
}
我们上面不仅仅对http的请求配置了跳转到https上,并且对bingimg.cn的https请求也跳转到www.bingimg.cn的https上,最后所有的请求都会落到www.bingimg.cn域名的https服务上,这样做首先将所有http请求跳转成https,其次讲所有bingimg.cn的请求跳转到www.bingimg.cn域名上,因为本质上这是两个不同的域名,都落到www.bingigm.cn域名上有利于SEO,另外要注意的是,上面的配置中最后一个 server 块中的listern命令需要添加 default_server 参数,否则跳转不正常,在nginx的error log 中会找到如下错误:
完成证书部署后可以通过如下站点检测网站的安全级别:
更新证书
目前 Let's Encrypt 的证书有效期是90天,时间到了会自动更新,您无需任何操作。 今后有可能会缩短这个时间, 不过都是自动的,不需要您关心。但是,您也可以手工运行命令强制续签证书:
acme.sh --renew -d example.com --force
更新 acme.sh 脚本
目前由于 acme 协议和 letsencrypt CA 都在频繁的更新, 因此 acme.sh 也经常更新以保持同步。升级 acme.sh 到最新版:
acme.sh --upgrade
如果您不想手动升级,,可以开启自动升级:
acme.sh --upgrade --auto-upgrade
您也可以随时关闭自动更新:
acme.sh --upgrade --auto-upgrade 0
以下关于acme.sh的资料参考:
到此关于部署免费ssl证书到网站的记录就说完了,可以点击连接查看效果 必应壁纸|必应美图