• 如何快速申请免费的SSL证书并自动续签?
  • 发布于 2个月前
  • 126 热度
    0 评论
最近发现网站域名过期了,之前都是申请阿里云、腾讯云的免费证书来给自己的小网站用的,手动去服务器上安装证书,那个时候免费的证书有效期1年,倒也还行不过现在申请免费的证书,有效期只有3个月了,过期就得重新去申请证书->下载证书->部署证书,由于笔者服务较多,需要管理好多个证书,那确实有点麻烦,所以决定实现申请SSL证书并自动续签,来节约时间和精力,来光明正大地"偷懒"

环境:centos7+nginx
SSL证书与Let's Encrypt
至于为啥需要ssl证书,是因为我们使用最广泛的网络协议http,其数据的明文传输和消息完整性检测的缺乏,早期web和网络主要用于学术资料的传输与共享,但随着web流行于整个地球,使用者也越来越鱼龙混杂,所有经过http传输的信息都可以被抓包等其他手段看的清清楚楚,存在很大的安全隐患

在1994年,网景公司(Netscape Communication)在http协议依赖的TCP/IP协议栈的基础上,创建了一个额外的加密传输层:SSL协议。HTTP+一个 SSL 安全证书 = HTTPS超文本传输安全协议。Https以安全为目标的HTTP通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性

理论上,我们自己可以手动制作一个SSL安全证书,但我们自己签发的安全证书得不到浏览器的信任,所以我们一般用的是,被信任的证书授权中心CA签发的安全证书。一旦将SSL安全证书部署成功后,当用户访问我们的网站时,浏览器会在显示的网址前加一把小绿锁,表明这个网站是安全的

然而一般的SSL安全证书签发服务都需要付费,且价格不菲,但也有一些免费的证书,比如Let’s Encrypt免费证书,由公益组织ISRG于2015年推出,本文就申请该证书

Let’s Encrypt官方推荐的客户端是Certbot,但个人感觉还是第三方工具acme.sh更轻便好用,本文将从零开始讲解如何acme.sh来搭建属于自己的申请SSL证书并自动续签

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通知


安装acme.sh
呼噜噜这台丐版服务器版本:
# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
国内可以参考https://github.com/acmesh-official/acme.sh/wiki/Install-in-China这个安装步骤,为方便起见,都是以root权限的用户来执行
# 堆代码 duidaima.com
# git clone https://gitee.com/neilpang/acme.sh.git
# cd acme.sh
# ./acme.sh --install -m my@example.com
这里my@example.com写自己的邮箱即可,推荐是自己常用的
[Fri Jun 14 11:25:25 CST 2024] It is recommended to install socat first.
[Fri Jun 14 11:25:25 CST 2024] We use socat for standalone server if you use standalone mode.
[Fri Jun 14 11:25:25 CST 2024] If you don't use standalone mode, just ignore this warning.
[Fri Jun 14 11:25:25 CST 2024] Installing to /root/.acme.sh
[Fri Jun 14 11:25:25 CST 2024] Installed to /root/.acme.sh/acme.sh
[Fri Jun 14 11:25:25 CST 2024] Installing alias to '/root/.bashrc'
[Fri Jun 14 11:25:25 CST 2024] OK, Close and reopen your terminal to start using acme.sh
[Fri Jun 14 11:25:25 CST 2024] Installing alias to '/root/.cshrc'
[Fri Jun 14 11:25:25 CST 2024] Installing alias to '/root/.tcshrc'
[Fri Jun 14 11:25:25 CST 2024] Installing cron job
[Fri Jun 14 11:25:25 CST 2024] Good, bash is found, so change the shebang to use bash as preferred.
[Fri Jun 14 11:25:25 CST 2024] OK
这就ok了,但它推荐我们装一下socat,那我们就装一下
# yum install socat
新版acme.sh使用ZeroSSL作为CA,我们这边切换到Let’s Encrypt的CA:
# acme.sh --set-default-ca --server letsencrypt
安装好acme.sh后,会自动为我们创建cronjob,每天会自动检测所有的证书,如果快过期了, 需要更新, 则会自动更新证书

我们输入crontab -l,能看到如下输出
*/5 * * * * flock -xn /tmp/stargate.lock -c '/usr/local/qcloud/stargate/admin/start.sh > /dev/null 2>&1 &'
25 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
定时任务保证了证书在到期前能自动续期;且安装过程不会污染已有的系统任何功能和文件, 所有的修改都限制在安装目录中: ~/.acme.sh/

另外 由于ACME协议和Let’s Encrypt CA都在频繁的更新,可以开启acme.sh的自动升级
# acme.sh  --upgrade  --auto-upgrade

申请证书
申请签发证书,有好多种方式:
1.如果网站已经运行Nginx/Apache,直接可以指定对应插件,智能的从Nginx/Apache的配置中自动完成验证, 不需要指定网站根目录
# acme.sh --issue -d 域名 --nginx # or --apache
2.如果你的服务器上已经运行了web软件,指定webroot即可签发证书
# acme.sh --issue -d 域名 --webroot web目录
3.如果没有运行web软件并且80端口空闲,可以使用acme.sh自己监听80端口进行验证
# acme.sh --issue -d 域名 --standalone
4.使用DNS方式,手动在域名上添加一条 txt 解析记录, 验证域名所有权;或者拿到DNS运营商账号的秘钥,自动执行DNS运营商的插件
# acme.sh --issue --dns -d 域名 #命令结束后,acme.sh会显示解析记录,需要手动到DNS后台设置解析
由于笔者的小破站是通过Nginx来反向代理的,本来这里直接选用第一个
# acme.sh --issue -d 你的域名(tmp.xxxx.cn) --nginx /etc/nginx/nginx.conf
但我这个域名是子域名,服务还在容器里面,所以acme无法直接访问这个域名下的文件,笔者这里只能采用第4个方案,域名DNS运营商是腾讯云,不想手动到DNS后台设置解析的话,这里需要腾讯云的秘钥

腾讯云自定义策略,选择策略->按策略语法创建->空白模板,填写基本信息,并将策略语法修改为以下内容,并点击完成,生成一个名为policygen-20240614230651的策略
{
    "statement": [
        {
            "action": [
                "dnspod:DescribeRecordFilterList",
                "dnspod:DescribeRecordList",
                "dnspod:CreateRecord",
                "dnspod:DeleteRecord"
            ],
            "effect": "allow",
            "resource": [
                "*"
            ]
        }
    ],
    "version": "2.0"
}
腾讯云创建子账号,再创建一个子账号,选择 编程访问+名为policygen-20240614230651的策略

点击保存,会生成SecretId、SecretKey

将获取到的 SecretId 和 SecretKey 导入环境变量中,以便 acme.sh 调用 这个方式是在当前终端下,临时生效:
export Tencent_SecretId="<Your SecretId>"
export Tencent_SecretKey="<Your SecretKey>"
以下方式是环境变量永久生效,vim /etc/profile,添加以下内容:
export Tencent_SecretId="<Your SecretId>"
export Tencent_SecretKey="<Your SecretKey>"
保存,并source /etc/profile命令,重新加载环境变量

接着执行acme命令,来申请证书
acme.sh --issue --dns dns_tencent -d example.com -d *.example.com
最终生成的证书/root/.acme.sh/example.com_ecc/fullchain.cer,除了腾讯云,acme.sh目前支持 阿里云, cloudflare, dnspod, cloudxns, godaddy等数十种解析商的自动集成。

但我们不能直接使用,还需要安装证书,并指定目标位置, 然后证书文件会被copy到相应的位置
acme.sh --install-cert -d example.com \
--key-file      /root/myAcmeSSL/example.com/key.pem  \
--fullchain-file /root/myAcmeSSL/example.com/cert.pem \
--reloadcmd     "nginx -s stop && nginx"

--install-cert: 安装证书的命令
-d example.com:读取对应域名配置
–key-file:将证书私钥拷贝到该参数指定的路径
–fullchain-file:将证书链拷贝到该参数指定的路径
–reloadcmd:指定证书拷贝到对应目录后执行的命令
nginx -s stop && nginx这是我本机上的命令这样能够重新加载证书;如果service命令正常,也可以运行service nginx force-reload;

更详细地参数可参考: https://github.com/Neilpang/acme.sh#3-install-the-issued-cert-to-apachenginx-etc

查看已安装证书
# 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 2024
 Le_NextRenewTimeStr=Mon Jun  6 19:12:05 UTC 2024
 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.conf
接着修改nginx.conf,因为笔者的服务是通过nginx来反向代理的,注意证书的实际路径即可
server {
        listen  443 ssl;
        server_name  example.com;

        # 请替换为证书实际路径
        ssl_certificate      /root/myAcmeSSL/example.com/cert.pem;
        ssl_certificate_key  /root/myAcmeSSL/example.com/key.pem;

        # ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers  HIGH:!ADH:!EXPORT56:RC4+RSA:+MEDIUM;
        ssl_prefer_server_ciphers  on;

        // location / {
        //    ...
        // }
    }
这样接下来就可以验证域名了,别忘了防火墙443端口还是要开的。每天0点25分,会检测证书是否过期,如果快过期了或需要更新, 则会自动更新证书,无需我们再操心了!

其他一些命令:
强制手动续期
acme.sh --renew -d example.com --force
停止证书续期
acme.sh --remove -d example.com
acme.sh申请免费的SSL证书并自动续签,总体上使用起来是比较简单,轻便的,非常适合个人开发者~
用户评论