对于很多对外业务,都有使用ssl证书的诉求,要么是自己生成,要么是在证书平台采购,对于采购,简单看了阿里云和腾讯云的证书购买价格:
基本上所有的主流平台,购买域名证书一年也都需要大几百RMB。而成本是一个重要的考量因素,对于为什么要自己生成证书,核心原因可以归结为:
自签名证书无需购买,适合预算敏感的项目或内部系统。
完全掌控证书的生成、配置和管理,便于定制加密参数和有效期。购买证书需提交域名验证、企业资质等材料(如 DV/OV/EV 证书),流程耗时(数分钟至数天)
不依赖第三方证书机构,提升系统独立性和安全性。
之前写过一篇文章《白嫖https免费证书》,用于在安装了nginx服务的机器上生成和使用免费证书,但是这里有一个明显的缺陷就是本地生成和本地使用,那么也就是说自己的服务器公网ip和端口是暴露的,容器被攻击。而现在很多项目都是基于云平台开发部署的,那么可以使用云平台的能力更好的防护服务,比如使用云平台的ALB负载前后端服务资源,这样就把服务器的真实ip隐藏并保护起来了。
而对于需要把证书绑定到ALB上提供加密访问的需求,使用原来的http解析方式生成证书就有点无能为力了。
对于aws云平台,可以结合ALB+ACM(AWS Certificate Manager)来实现,ACM是aws提供的一种的一种免费证书托管服务,按照其要求申请证书并配置dns解析即可,并提供自动续期能力。
而aliyun国际站以及其他一些云平台,并不提供免费的证书服务,但是提供证书生成后上传到平台提供半托管能力,并且不提供续期能力。
但是我们既想使用云平台的证书托管能力,但是又不想花钱怎么办呢?
没错,我们本篇文章就介绍下使用certbot和acme.sh两种工具通过dns解析方式实现这个需求。
Certbot是由电子前哨基金会(EFF) 开发的一款免费、开源的自动化工具,Certbot 是用Python编写,主要用于从 Let's Encrypt 等证书颁发机构获取和管理SSL/TLS 证书。它可以帮助用户自动申请、安装和更新证书,简化了为网站启用HTTPS 的过程,从而提高互联网的安全性。它也是Let's Encrypt推荐的使用方式。
#安装相关驱动
rpm -ivh https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
#安装cerbot工具
yum install -y certbot
与之前使用cerbot通过http解析生成证书方式不同,certbot通过dns解析生成证书,需要在域名管理平台配置txt类型二级域名解析,并且cerbot通过手动方式生成证书大致分为三个阶段,先发起生成证书请求,产生txt解析记录,命令会卡在这里,然后到域名平台配置txt类型解析,等解析生效后回车生成证书。
certbot certonly -d xxx --cert-name xxx --manual --force-renewal --no-self-upgrade --preferred-challenges dns
到域名平台配置txt解析,等解析生效回车:
这样就在/etc/letsencrypt/live/目录下生成了对应域名的证书了。
证书生成后,就可以到证书托管平台进行上传管理,以aliyun为例,选择证书管理服务
证书上传成功后,配置ALB https协议监听的时候就可以绑定上传托管的证书了。
acme.sh是一个基于 ACME 协议(Automatic Certificate Management Environment,自动证书管理环境)的开源工具,是基于shell脚本编写的ACME协议客户端,主要用于自动化申请、续期和管理 SSL/TLS 证书(尤其是 Let's Encrypt 证书)。它通过实现 ACME 协议的核心逻辑,简化了证书获取流程。
curl https://get.acme.sh | sh -s email=my@example.com
#或者
wget -O - https://get.acme.sh | sh -s email=my@example.com
安装可能会报如下错误,无法连接到服务器:
原因是github的一些域名的DNS解析被污染,导致DNS解析过程无法通过域名取得正确的IP地址。
解决方案是打开https://www.ipaddress.com/输入访问不了的域名。
查询之后可以获得正确的IP地址,然后在本机hosts文件添加解析配置:
然后继续执行上述安装命令,可以看到acme.sh安装成功。
使用acme.sh工具通过dns解析方式手动生成证书需要执行两个命令,先请求dns解析,然后到域名平台配置解析,然后请求生成证书,大致流程如下:
首先是和certbot类似,请求证书生成dns解析的key和value。
#设置Let's Encrypt为默认CA
acme.sh --set-default-ca --server letsencrypt
#请求证书
acme.sh --issue -d xxx --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please
执行命令后可以看到会生成对应需要验证域名所有权的二级域名以及对应的txt解析内容:
到域名平台配置上述txt解析记录后等待dns解析生效,然后执行生成证书的命令:
acme.sh --renew -d xxx --yes-I-know-dns-manual-mode-enough-go-ahead-please --force
命令执行后,如果txt解析记录已经生效则会打印生成成功的相关信息:
生成的证书内容默认在用户目录.acme.sh下,进入对应域名的目录可以看到生成的证书文件:
上传证书和certbot类似,只不过生成的证书文件有所差异,填写的内容需要调整。
上述两种工具生成证书的操作每一步都是手动完成的,免费证书有个严重缺陷就是有效期只有3个月。
这样就会存在一个问题,要时不时的人工盯一下过期时间,再快要过期的时候手动生成证书续期,周而复始还是比较麻烦的,那有没有什么方式既能实现类似aws ACM既能实现免费托管,又能自动续期?
答案是肯定的,certbot和acme.sh都提供了两个核心的钩子参数:
以certbot为例我们结合两个核心钩子参数以及服务器自带的crond任务来实现证书的自动更新和上传能力。
改造前边手动生成证书的cerbot命令,添加钩子参数:
certbot certonly -d xxxx --cert-name xxxx --manual --force-renewal --no-self-upgrade --preferred-challenges dns --manual-auth-hook '/opt/tools/script/add-txt-hook.sh' --deploy-hook '/opt/tools/script/upload-certs.sh'
add-txt-hook.sh脚本需要实现调用域名平台api配置dns txt解析的能力,upload-certs.sh脚本需要实现调用云平台证书托管api上传证书的能力,这样命令执行后就实现了dns txt解析、证书生成和证书上传一体化。对于域名平台的api以及云平台证书管理api或者sdk可自行了解和研究。如下贴一下namecheap的api以及aliyun证书上传的sdk:
上述改造后的命令实现了域名所有权验证、证书生成和上传集中化处理,但是如果想实现自动化还需要借助任务调度能力,前边聊过免费证书的有效期是3个月,那么我们可以结合crond调度任务,配置每个月1号执行证书续期的命令即可。
0 0 1 * * /bin/bash /opt/tools/script/renew_cert.sh >>/opt/tools/script/renew_cert_$(date +"\%Y-\%m-\%d").log
上述任务代表,每个月1号凌晨执行封装后的证书续期脚本renew_cert.sh,这样能保证证书每个月都会做续期操作,永远不会过期,同时也降低了人工做操作的时间成本。
虽然证书自动化续期省时省力,但是有时候并不能完全按照技术的思维把方案落地,对于一些项目,域名是非常核心的资产,往往域名的所属权并不属于研发团队,可能是由不懂或者不碰技术的人员把控,也就是说不大可能给到域名账号对应的平台api能力,那么自动化就无法进行,那么只能进行妥协,还是老老实实常规性的做一下过期检查和续期操作。
https://www.ipaddress.com/
https://letsencrypt.org/
https://github.com/certbot/certbot
https://github.com/acmesh-official/acme.sh
https://github.com/hawtim/hawtim.github.io/issues/10
本文分享自 PersistentCoder 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!