前言
记录一次使用acme.sh免费开启https的过程,前半部分列举一些用到的概念,后半部分记录具体操作步骤。文章已调整好线性阅读顺序,按顺序阅读即可。流程中涉及的概念会尽量进行讲解,以减少阅读此篇文章时,额外检索产生的时间消耗。
概念
acme.sh
acme.sh是github上的一个开源项目,实现了acme协议, 可以从letsencrypt生成免费的证书。
官方文档(官方文档的使用说明很详细,推荐阅读):
英文:https://github.com/acmesh-official/acme.sh
中文:https://github.com/acmesh-official/acme.sh/wiki/说明
acme.sh 有以下特点(摘自官方文档):
- 一个完全使用用Shell(Unix shell)语言编写的ACME协议的客户端
- 支持ACME v1和ACME v2协议
- 支持ACME v2通配符证书
- 简单,强大且非常易于使用。 您只需3分钟即可学习
- 和bash,dash, sh兼容
-
Let's Encrypt
免费证书客户端最简单的shell脚本 - 完全用Shell编写,不依赖python或官方的
Let's Encrypt
客户端 - 只需一个脚本即可发布,续期和自动安装证书
- 不需要root/sudoer权限
- 对Docker友好的
- 支持IPv6
- 对证书续期和错误等有cron job通知
Let's Encrypt
Let's Encrypt
是一个于2015年三季度推出的数字证书认证机构,旨在以自动化流程消除手动创建和安装证书的复杂流程,并推广使万维网服务器的加密连接无所不在,为安全网站提供免费的SSL/TLS证书。
-- 摘自 维基百科
网站开启https的时候需要证书,证书由CA机构(数字证书认证机构)签发,大部分传统CA机构签发证书需要收费,这不利于https协议的推广。Let's Encrypt
也是一个CA机构,但它是免费签发数字证书的,通过它,我们可以免费开启https
ACME(自动证书管理环境)
ACME协议最初是由 Internet Security Research Group 为其公共 CA(公共证书颁发机构)——Let's Encrypt 开发的。ACME 协议通过在给定 Web 服务器上安装证书管理代理来运行。组织或域在一开始就经过验证,代理协助域控制验证,一旦完成,代理可以请求,续订和撤销证书。
详情:ACME 协议:它是什么以及如何工作——asiaregister.com
ACME协议具体的工作流程这里就不细说了,感兴趣的朋友可以去详情即原出处查看。
全站https,通配符证书
通配符证书是一个可以被多个子域使用的公钥证书,主域名签发的通配符证书可以在所有子域名中使用。在此之前,配置子域名也是需要每个子域名单独的申请证书的。2018年3月14日,Let’s Encrypt
对外宣布ACME v2已正式支持通配符证书,这意外味着用户可以在 Let’s Encrypt
上免费申请支持通配符的SSL证书。
具体操作
官方文档(官方文档的使用说明很详细,推荐阅读):
英文:https://github.com/acmesh-official/acme.sh
中文:https://github.com/acmesh-official/acme.sh/wiki/说明
本文使用的操作系统(Linux各版本操作步骤基本一致):CentOS 7.3
1. 安装acme.sh
输入
curl https://get.acme.sh | sh
或
wget -O - https://get.acme.sh | sh
curl 命令
curl 命令是一个利用URL规则在命令行下工作的文件传输工具。它支持文件的上传和下载,所以是综合传输工具。
wget命令
wget 命令用来从指定的URL下载文件。wget非常稳定,它在带宽很窄的情况下和不稳定网络中有很强的适应性,如果是由于网络的原因下载失败,wget会不断的尝试,直到整个文件下载完毕。如果是服务器打断下载过程,它会再次联到服务器上从停止的地方继续下载。这对从那些限定了链接时间的服务器上下载大文件非常有用。
acmesh安装内部流程
普通用户和 root 用户都可以安装使用. 安装过程进行了以下几步:
-
把 acme.sh 安装到你的 home 目录(即~目录)下:
~/.acme.sh/
并创建一个 bash 的 alias, 方便你的使用: alias acme.sh=~/.acme.sh/acme.sh
(alias:中文释意"别名")
- 自动为你创建 cronjob, 每天 0:00 点自动检测所有的证书, 如果快过期了, 需要更新, 则会自动更新证书。
更高级的安装选项请参考: https://github.com/Neilpang/a...
安装过程不会污染已有的系统任何功能和文件, 所有的修改都限制在安装目录中: ~/.acme.sh/
cron job
工具型软件cron是一款类Unix操作系统下的基于时间的任务管理系统。用户们可以通过cron在固定时间、日期、间隔下,运行定期任务(可以是命令和脚本)。cron常用于运维和管理,但也可用于其他地方,如:定期下载文件和邮件。cron该词来源于希腊语chronos(χρόνος),原意是时间。
——摘自 维基百科
博主最先使用curl命令进行安装,但由于网络原因,失败了:
如果安装成功,~目录下,使用ls -la
可以查看到有一个.acme.sh目录。
curl 命令安装失败后,改用wget命令,成功安装:
安装信息中有一段醒目的红色警告:
It is recommended to install socat first.We use socat for standalone server if you use standalone mode.If you don't use standalone mode, just ignore this warning.
即:
推荐先安装socat。如果你使用standalone mode,那么我们需要为了standalone server使用socat。如果你不使用standalone mode,那么请忽略这条警告
standalone mode 非开启https必须,在官方英文文档中被另一些配置用到(4. Use Standalone server to issue cert
5. Use Standalone ssl server to issue cert
),如果感兴趣的话可以去看官方英文文档。
简略介绍一下socat:
socat
socat 是一个多功能的网络工具,名字来由是“Socket CAT”,可以看作是 netcat 的加强版。它有一些netcat所不具备却又很有需求的功能,例如ssl连接。socat是强大的,可以实现任意socket的转换。而netcat被称为网络工具中的瑞士军刀,体积小巧,但功能强大。netcat可以在两台设备上面相互交互,即侦听模式/传输模式。
想要安装socat的话,可以使用yum安装socat:
yum install socat
2. 生成证书
acme.sh 实现了 acme 协议支持的所有验证协议. 一般有两种方式验证: http 和 dns 验证。
1.http 方式(推荐)
http 方式需要在你的网站根目录下放置一个文件, 来验证你的域名所有权。完成验证, 然后就可以生成证书了。
acme.sh --issue -d mydomain.com -d www.mydomain.com --webroot /home/wwwroot/mydomain.com/
只需要指定域名, 并指定域名所在的网站根目录。 acme.sh 会全自动的生成验证文件, 并放到网站的根目录, 然后自动完成验证。最后会聪明的删除验证文件,整个过程没有任何副作用。
第二个参数"example.com" 是您要为其颁发证书的主要域。这里至少要填写一个域名。
博主的网站根目录填写的是tomcat服务器的webapps目录,文章后面有不需要你不需要指定网站根目录的办法。nginx服务器在80端口做转发,转发到8080端口的tomcat服务器。
如果你用的 apache服务器, acme.sh 还可以智能的从 apache的配置中自动完成验证, 你不需要指定网站根目录:
acme.sh --issue -d mydomain.com --apache
如果你用的 nginx服务器, 或者反代, acme.sh 还可以智能的从 nginx的配置中自动完成验证, 你不需要指定网站根目录:
acme.sh --issue -d mydomain.com --nginx
证书每60天自动更新一次。
请注意, 无论是 apache 还是 nginx 模式, acme.sh在完成验证之后, 都会将服务器配置文件恢复到之前的状态, 不会私自更改你本身的配置。 好处是你不用担心配置被搞坏, 也有一个缺点, 你需要自己配置 ssl 的配置。acme.sh只能成功生成证书, 需要手动配置ssl,才能访问https。这样做虽然麻烦,但是为了配置的安全, 你还是自己手动改配置吧。
这里"你需要自己配置 ssl 的配置"的意思是:
为服务器安装ssl模块(Apache默认没有预装,需要自行安装。nginx默认预装了ssl模块,无需再次安装)。然后在服务器的配置文件中,写证书位置(在第3.步中我们将完成此项操作)。
2.手动 dns 方式(如使用第一种,可忽略第二种方法)
手动在域名上添加一条 txt 解析记录, 验证域名所有权。
这种方式的好处是, 你不需要任何服务器, 不需要任何公网 ip, 只需要 dns 的解析记录即可完成验证。 坏处是,如果不同时配置 Automatic DNS API,使用这种方式 acme.sh 将无法自动更新证书,每次都需要手动重新解析验证域名所有权。
第二种使用方式请见官方文档(文章开头链接),博主使用的http方式,手动dns方式这里不细说了。
3. copy/安装 证书
前面证书生成以后, 接下来需要把证书 copy 到真正需要用它的地方。
请注意,默认生成的证书都放在安装目录下: ~/.acme.sh/, 请不要直接使用此目录下的文件,例如: 不要直接让 nginx/apache 的配置文件使用这下面的文件。这里面的文件都是acmesh工具内部使用, 目录结构在将来可能会变化,进而导致服务器配置文件中填写的证书路径错误的情况。
正确的使用方法是使用 --installcert
命令,并指定目标位置, 然后证书文件会被copy到相应的位置, 例如:
Apache example
acme.sh --installcert -d example.com \
--cert-file /path/to/certfile/in/apache/cert.pem \
--key-file /path/to/keyfile/in/apache/key.pem \
--fullchain-file /path/to/fullchain/certfile/apache/fullchain.pem \
--reloadcmd "service apache2 force-reload"
Nginx example
acme.sh --installcert -d example.com \
--key-file /path/to/keyfile/in/nginx/key.pem \
--fullchain-file /path/to/fullchain/nginx/cert.pem \
--reloadcmd "service nginx force-reload"
(一个小提醒, 这里用的是 service nginx force-reload, 不是 service nginx reload, 据测试, reload 并不会重新加载证书, 所以用的 force-reload)
Nginx 的配置 ssl_certificate
使用 /etc/nginx/ssl/fullchain.cer
,而非 /etc/nginx/ssl/
,否则 SSL Labs 的测试会报 Chain issues Incomplete
错误。
--installcert
命令可以携带很多参数, 来指定目标文件。 并且可以指定 reloadcmd, 当证书更新以后, reloadcmd会被自动调用,让服务器生效。
–reloadcmd “service nginx force-reload”
是为了在让acmesh 自动更新时候能够重启nginx使得证书生效。
值得注意的是, 这里指定的所有参数都会被自动记录下来, 并在将来证书自动更新以后, 被再次自动调用。
首先,我们需要新建一个路径用于存放拷贝的证书(路径可自定义)。习惯是放在/etc/nginx/ssl/目录下。博主新建的路径:
/etc/nginx/ssl/jellyfishmix
执行(nginx方式)
acme.sh --installcert -d jellyfishmix.com \
--key-file /etc/nginx/ssl/jellyfishmix/key.pem \
--fullchain-file /etc/nginx/ssl/jellyfishmix/cert.pem \
--reloadcmd "service nginx force-reload"
--key-file
参数填写:你的自定义路径 + key.pem
--fullchain-file
参数填写:你的自定义路径 + cert.pem
这里的key.pem
和cert.pem
并不表示一个已经存在的文件,而是表示拷贝粘贴后的文件将被命名的名字。
nginx相关
nginx的安装与使用:CentOS 7 下 yum 安装和配置 Nginx
nginx的端口转发:nginx反向代理——将80端口请求转发到8080
nginx的配置文件路径查看:nginx快速查看配置文件的方法
nginx.conf配置ssl
想要https就要监听443端口,nginx.conf已经预留出了server,只要我们放开权限,修改即可。
监听443端口
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /etc/nginx/ssl/jellyfishmix/cert.pem;
ssl_certificate_key /etc/nginx/ssl/jellyfishmix/key.pem;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #指定SSL服务器端支持的协议版本
ssl_ciphers HIGH:!aNULL:!MD5;
#ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; #指定加密算法
ssl_prefer_server_ciphers on; #在使用SSLv3和TLS协议时指定服务器的加密算法要优先于客户端的加密算法
}
注:ssl_certificate 和 ssl_certificate_key 的路径就是我们ssl证书申请的路径
ssl_certificate
证书其实是个公钥,它会被发送到连接服务器的每个客户端,ssl_certificate_key私钥是用来解密的,所以它的权限要得到保护但nginx的主进程能够读取。当然私钥和证书可以放在一个证书文件中,这种方式也只有公钥证书才发送到client。
ssl_session_timeout
客户端可以重用会话缓存中ssl参数的过期时间,内网系统默认5分钟太短了,可以设成30m即30分钟甚至4h。
ssl_protocols
指令用于启动特定的加密协议,nginx在1.1.13和1.0.12版本后默认是ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2,TLSv1.1与TLSv1.2要确保OpenSSL >= 1.0.1 ,SSLv3 现在还有很多地方在用但有不少被攻击的漏洞。
ssl_ciphers
选择加密套件,不同的浏览器所支持的套件(和顺序)可能会不同。这里指定的是OpenSSL库能够识别的写法,你可以通过 openssl -v cipher ‘RC4:HIGH:!aNULL:!MD5’(后面是你所指定的套件加密算法) 来看所支持算法。
ssl_prefer_server_ciphers on
设置协商加密算法时,优先使用我们服务端的加密套件,而不是客户端浏览器的加密套件。
监听80端口
server {
listen 80;
server_name www.example.com;
return 301 https://www.example.com$request$uri;
}
因为http是默认端口,监听80端口可以让http重定向到https端口上。
博主的nginx.conf(部分,如要复制,请把所有"jellyfishmix.com"字样替换成自己的域名,证书路径替换为自己的路径):
server {
# listen 80 default_server;
# listen [::]:80 default_server;
# server_name _;
listen 443 ssl;
server_name www.jellyfishmix.com;
ssl_certificate /etc/nginx/ssl/jellyfishmix/cert.pem;
ssl_certificate_key /etc/nginx/ssl/jellyfishmix/key.pem;
ssl_session_timeout 5m;
# 指定SSL服务器端支持的协议版本
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; 指定加密算法
ssl_ciphers HIGH:!aNULL:!MD5;
# 在使用SSLv3和TLS协议时指定服务器的加密算法要优先于客户端的加密算法
ssl_prefer_server_ciphers on;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://39.97.254.25:8080;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
server {
listen 80;
server_name jellyfishmix.com;
return 301 https://jellyfishmix.com$request$uri;
}
然后重新加载nginx:
systemctl reload nginx
此时请访问自己的域名:example.com
或www.example.com
正常情况下,此时可以正常访问域名,并且连接所使用的协议为https。
4. 续期证书
目前证书在 60 天以后会自动续期, 你无需任何操作。今后有可能会缩短这个时间, 不过都是自动的, 你不用关心。
当然了,你可以强制手动续期:
acme.sh --renew -d example.com --force
5. 如何停止证书续期
如果要停止证书续期,你可以执行以下命令将证书从续期列表中移除:
acme.sh --remove -d example.com
cert/key 文件不会从硬盘中被移除。
你可以自行移除隐藏目录(例如::~/.acme.sh/example.com
)
6. 更新 acme.sh
目前由于 acme 协议和 letsencrypt CA 都在频繁的更新, 因此 acme.sh 也经常更新以保持同步。
升级 acme.sh 到最新版 :
acme.sh --upgrade
如果你不想手动升级, 可以开启自动升级:
acme.sh --upgrade --auto-upgrade
之后, acme.sh 就会自动保持更新了。
你也可以随时关闭自动更新:
acme.sh --upgrade --auto-upgrade 0
-- END