使用 acme.sh 实现 ssl 证书免费获取+自动续费

今天也是在 sth 的指点下从 http → https 了 5555555

前言:HTTP、HTTPS、SSL、TLS、证书相关内容

HTTP 是超文本传输协议,是互联网上使用最广泛的协议之一,用于从服务器传输超文本到本地浏览器的传输协议

HTTPS 是 HTTP 的安全版本,它在HTTP的基础上通过 SSL/TLS 协议提供了数据加密、完整性校验和身份验证。这意味着使用HTTPS的网页数据在传输过程中是加密的,可以防止数据在传输过程中被窃听或篡改,是现代网站安全的基本要求。如果继续使用 HTTP 可能会被浏览器拦截或报警告

SSL 是安全套接字层,是一种安全协议,用于在互联网上提供安全通信。SSL 可以用于在客户端和服务器之间建立一个加密的连接,确保数据传输的安全性

TLS 是传输层安全协议,是 SSL 的继承者,提供了更高级的安全特性。TLS用于在两个通信应用程序之间提供数据加密和数据完整性保障,防止数据在传输过程中被窃听或篡改

数字证书用于在 SSL/TLS 握手过程中验证服务器的身份。当客户端(如浏览器)尝试与服务器建立安全连接时,服务器会提供其数字证书,之后浏览器验证证书的有效性(是否过期,是否由受信任的机构颁发,验证证书的域名和当前尝试连接的域名是否匹配),然后客户端使用服务器证书中的公钥加密生成的对称密钥,并将加密后的密钥发送给服务器,服务器使用其私钥解密客户端发送的加密密钥,从而获得对称密钥,客户端和服务器现在都拥有相同的对称密钥,可以使用这个密钥来加密和解密它们之间的通信。这确保了数据传输的机密性和完整性。一旦密钥交换完成,SSL/TLS 握手过程结束,客户端和服务器之间的安全连接建立成功。客户端和服务器可以开始加密通信

数字证书通常由受信任的第三方证书颁发机构(CA)签发,证书中包含了公钥、证书持有者的身份信息以及证书的有效期等。

有了以上基础知识,我们就知道想要实现域名 HTTPS 连接其实只需要两步:获得机构颁发的证书,安装证书

sth 的推荐下使用了 acme.sh,acme.sh 是一个开源的、用 Unix shell 脚本编写的 ACME 协议客户端工具,用于自动化申请、更新和部署 SSL/TLS 证书。非常香的工具)

以下教程改编自 GitHub Wiki

安装 acme.sh

安装很简单, 一个命令:

1
curl https://get.acme.sh | sh -s [email protected]

其中 email 请修改为自己的邮箱

这个命令会将 acme.sh 安装到 ~/.acme.sh/,以下操作均在该目录下进行

同时会创建一个 cronjob,每天 0:00 点自动检测所有的证书,如果快过期了,则会自动更新证书

请确保 cronjob 正确安装,看起来是类似这样的:

1
2
3
crontab  -l

56 * * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

生成证书

1、http 方式

需要在你的网站根目录下放置一个文件, 来验证你的域名所有权,完成验证. 然后就可以生成证书了.

1
./acme.sh --issue -d mydomain.com -d www.mydomain.com --webroot /home/wwwroot/mydomain.com/

只需要指域名,并指定域名所在的网站根目录。acme.sh 会全自动的生成验证文件,并放到网站的根目录,然后自动完成验证,最后会聪明的删除验证文件。整个过程没有任何副作用

2、使用 apache

acme.sh 还可以智能的从 apache 的配置中自动完成验证,你不需要指定网站根目录:

1
./acme.sh --issue -d mydomain.com --apache

其中 mydomain.com 请修改为自己的邮箱,下同

3、使用 nginx

acme.sh 还可以智能的从 nginx 的配置中自动完成验证,你不需要指定网站根目录:

1
./acme.sh --issue -d mydomain.com --nginx

4、使用 acme.sh 监听 80 端口

如果你还没有运行任何 web 服务,80 端口是空闲的,那么 acme.sh 还能假装自己是一个 webserver,临时听在 80 端口,完成验证

1
./acme.sh --issue -d mydomain.com --standalone

注意

acme.sh 脚本默认 ca 服务器是 zerossl,经常出错,会导致获取证书的时候一直出现:Pending, The CA is processing your order, please just wait.

只需要把ca服务器改成 letsencrypt 即可,虽然更改以后还是有概率出现 pending,但基本2-3次即可成功

1
./acme.sh --set-default-ca --server letsencrypt

安装证书

使用 --install-cert 命令并指定目标位置迁移证书

注意,默认生成的证书都放在安装目录下:~/.acme.sh/,请不要直接使用此目录下的文件,例如:不要直接让 nginx 或 apache 的配置文件使用这下面的文件。这里面的文件都是内部使用, 而且目录结构可能会变化

Apache example:

1
2
3
4
5
acme.sh --install-cert -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:

1
2
3
4
acme.sh --install-cert -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

请将 example.com 修改为你自己的域名,/path/to/keyfile/in/nginx 和 /path/to/fullchain/nginx 修改为自己的路径

查看已安装证书信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
acme.sh --info -d example.com
# 会输出如下内容:
DOMAIN_CONF=/root/.acme.sh/example.com/example.com.conf
Le_Domain=example.com
Le_Alt=no
Le_Webroot=dns_ali
Le_PreHook=
Le_PostHook=
Le_RenewHook=
Le_API=https://acme-v02.api.letsencrypt.org/directory
Le_Keylength=
Le_OrderFinalize=https://acme-v02.api.letsencrypt.org/acme/finalize/23xxxx150/781xxxx4310
Le_LinkOrder=https://acme-v02.api.letsencrypt.org/acme/order/233xxx150/781xxxx4310
Le_LinkCert=https://acme-v02.api.letsencrypt.org/acme/cert/04cbd28xxxxxx349ecaea8d07
Le_CertCreateTime=1649358725
Le_CertCreateTimeStr=Thu Apr 7 19:12:05 UTC 2022
Le_NextRenewTimeStr=Mon Jun 6 19:12:05 UTC 2022
Le_NextRenewTime=1654456325
Le_RealCertPath=
Le_RealCACertPath=
Le_RealKeyPath=/etc/acme/example.com/privkey.pem
Le_ReloadCmd=service nginx force-reload
Le_RealFullChainPath=/etc/acme/example.com/chain.pem

修改配置文件

由于我个人用的是 nginx,所以只给出 nginx 的修改案例

旧:

1
2
3
4
5
6
7
8
server {
listen 80;
server_name blog.houyi2333.top;
location / {
root /path/to/hexo;
index index.html;
}
}

新:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 443 ssl;
ssl_certificate "/path/to/fullchain/nginx/cert.pem";
ssl_certificate_key "/path/to/keyfile/in/nginx/key.pem";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
# 表示优先使用服务端加密套件。默认开启
ssl_prefer_server_ciphers on;
server_name blog.houyi2333.top;
location / {
root /path/to/hexo;
index index.html;
}
}

之后重启 nginx

开启自动更新

目前由于 acme 协议和 letsencrypt CA 都在频繁的更新,因此 acme.sh 也经常更新以保持同步,使用以下命令来开启自动更新

1
./acme.sh --upgrade --auto-upgrade