V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
BaymaxK
V2EX  ›  程序员

使用 ACME 申请免费“永久”的 SSL 证书

  •  
  •   BaymaxK · 127 天前 · 4740 次点击
    这是一个创建于 127 天前的主题,其中的信息可能已经有所发展或是发生改变。

    三个多月没写文章了,上半年经历了被裁员,找工作,入职,转正等一系列事情,目前总算是尘埃落定了,继续开始搞创作🤗

    前言

    通过 https 协议访问网站时,SSL 证书确保了数据传输的安全性。目前,大多数云服务提供商提供的免费证书有效期只有 90 天,想要更长时间的证书则需要付费。这意味着每隔 90 天就需要重新签发并替换证书文件。

    折腾一番后,我找到了一个免费且优雅的方案,只需要在服务器上安装相关脚本,就能申请到免费的域名证书,它会定期检查证书的有效期,实现到期自动续期与更新,从而有效地获得了一个“永久”的证书。

    本文就跟大家详细分享下这个方案,欢迎各位感兴趣的开发者阅读本文。

    环境搭建

    我们需要用到ACME这个程序来完成证书的申请与签发。

    程序安装

    首先,我们需要通过SSH连接到服务器,通过以下命令来安装:

    curl  https://get.acme.sh | sh
    

    安装程序会自动做以下操作:

    • 自动把acme.sh安装到你的 home 的.acme.sh目录下,即~/.acme.sh/
    • 自动创建一个 bash的别名,方便命令行的直接使用: alias acme.sh=~/.acme.sh/acme.sh
    • 自动为你创建 cron 任务, 每天 0:00 点自动检测所有的证书, 如果快过期了, 需要更新,则会自动更新证书。

    更改默认证书

    因为 acme 已经被 ZeroSSL 收购,其默认的证书方式为 ZeroSSL ,但此证书生成时会携带邮箱,因此需要更换为letsencrypt

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

    申请泛域名证书

    泛域名证书是一种能够为同一个主域名(例如 kaisir.cn )下的所有子域名(如 www.kaisir.comresource.kaisir.cn 等)提供安全加密的数字证书。能够通过一个单一的证书来保护主域名及其所有子域名的数据传输,使得网站管理者无需为每个子域名分别购买和管理多个 SSL 证书。

    通过 acme 申请的证书,可以绑定满足该通配符型规则的任意三级子域名,例如:

    www.kaisir.cn
    test.kaisir.cn
    aaa.kaisir.cn
    bb.kaisir.cn
    ...
    

    如果你对数字证书比较感兴趣,可以移步我的另一篇文章:数字证书的理解

    获取 DNS API 参数

    acme 提供的泛域名证书只能通过 dns 的形式来做验证,因此我们需要进入域名解析控制台(你可以在此处找到你的域名解析提供商)创建 API ID 和 API Key 。

    我这里以阿里云为例,登录成功后,去到阿里云的RAM 访问控制面板来创建用户。

    image-20240619225842654

    • 创建完用户之后,点击添加权限按钮

    image-20240619225912624

    • 勾选第一页的所有权限

    image-20240619225956814

    • 复制AccessKey IDAccessKey Secret下来,保存好。

    image-20240619230641776

    配置环境变量

    由于每个平台的环境变量名称是不一样的,因此你需要去acme-dnsapi 网站里找到你平台的变量名。我这里以阿里云为例,将 key 和 secret 换成上一步创建的即可。

    export Ali_Key="key"
    export Ali_Secret="secret"
    

    生成证书

    做完上述操作后,我们的准备工作就做完了,可以使用acme.sh脚本来创建证书了。

    acme.sh --issue --dns dns_ali -d kaisir.cn -d '*.kaisir.cn' --dnssleep 300 --debug
    
    • --dns 用于指定 dns 校验平台,我这里是阿里云
    • 第一个-d是你的网站主域名,第二个是泛域名
    • --dnssleep用于等待操作,因为把 txt 添加到后台,解析不一定能做到立刻生效,所以需要延时一下,此处我设置了 300 秒的延时,执行命令的过程会有个等待倒计时。
    • --debug开启调试模式,创建过程中会打印详细的日志出来,方便定位错误。

    创建成功后,你将看到如下所示的内容:

    image-20240619231229712

    安装证书

    最后,我们只需要找到创建好的证书,将其在服务器上的路径填写到 nginx 中即可。脚本会在证书快到期时,自动续期并创建相关文件。

    本章节将以我的服务器为例,跟大家分享下如何去做相关的配置。

    配置路径映射

    如果你的服务是直接运行在宿主机上的,请跳过这一步。

    我的服务是运行在 docker 容器里的,因此需要先把服务器的证书路径映射进容器中,此处我以docker-compose为例,在volumes节点下添加映射即可。

        nginx-server:
            image: nginx:1.18.0
            container_name: local_nginx
            volumes:
                - /root/.acme.sh/kaisir.cn_ecc:/usr/share/acme
    

    注意:如果你只使用了 docker ,则需要在运行docker run指令时,通过添加-v参数来添加路径映射,例如docker run -v /root/.acme.sh/kaisir.cn_ecc:/usr/share/acme

    • /root/.acme.sh/kaisir.cn_ecc 是宿主机上的路径
    • /usr/share/acme是容器内部的路径

    如果你对 docker 不是很了解,可以移步我的另一篇文章:使用 docker 来编排 Web 应用

    配置 nginx

    随后,我们就可以打开nginx的配置文件,指定ssl 证书的位置即可。

    • /usr/share/acme/就是我们上一步所映射出来的路径
    • fullchain.cer就是我们申请到的泛域名证书
    server {
    	# 配置 ssl 证书
    	ssl_certificate   /usr/share/acme/fullchain.cer;
    	ssl_certificate_key  /usr/share/acme/kaisir.cn.key;
    }
    

    实现效果

    最后,我们重启 nginx ,通过浏览器访问网站就能看到证书信息了🤗

    image-20240620230554443

    • 访问子域名的服务也是正常的

    image-20240620232129698

    • 证书详情如下所示

    image-20240620232154469

    写在最后

    至此,文章就分享完毕了。

    我是神奇的程序员,一位前端开发工程师。

    如果你对我感兴趣,请移步我的个人网站,进一步了解。

    • 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注😊
    • 本文首发于神奇的程序员公众号,未经许可禁止转载💌
    第 1 条附言  ·  127 天前

    忽略图片的防盗链问题了🥹。大家移步我的网站看吧:使用ACME申请SSL证书

    第 2 条附言  ·  126 天前
    文章中阿里云的 ram 控制台授权那里给的权限太多了,其实只用给一个就可以了,v 站没法更新了,原文已经更正错误了。原文地址: https://www.kaisir.cn/post/178
    44 条回复    2024-09-26 10:41:59 +08:00
    Nosub
        1
    Nosub  
       127 天前 via iPhone
    刚好今天也写了一篇类似的文章,用的是 certbot ,感觉比你的简单。

    使用 Certbot 申请 SSL 证书并自动续期
    https://nosub.net/posts/p/167
    Love4Taylor
        2
    Love4Taylor  
       127 天前
    你不考虑下掘金图片防盗链的问题么
    BaymaxK
        3
    BaymaxK  
    OP
       127 天前
    @Love4Taylor 😂v 站能看到就行了,问题不大。
    Love4Taylor
        4
    Love4Taylor  
       127 天前 via iPhone
    BaymaxK
        5
    BaymaxK  
    OP
       127 天前
    @Love4Taylor 奇怪了,我这里又能看到。![image-20240718000308986]( https://resource.kaisir.cn/uploads/MarkDownImg/20240718/VD6KSP.png)
    BaymaxK
        6
    BaymaxK  
    OP
       127 天前
    @Love4Taylor 卧槽,我开浏览器的无痕模式就看不到了🙂‍↔️![image-20240718000426560]( https://resource.kaisir.cn/uploads/MarkDownImg/20240718/G42YCE.png)
    ysc3839
        7
    ysc3839  
       126 天前   ❤️ 4
    acme.sh 曾经出现过远程代码执行漏洞,因为是脚本,不知道现在是否还有相关漏洞,或许很难保证安全。
    除了安全问题,acme.sh 解析数据似乎是直接使用 grep 等正则表达式匹配,健壮性不足。
    再者还有隐性依赖问题,可能系统里没装某些工具,直接执行脚本并不能看出缺少哪些工具,等到执行到那部分时可能崩溃或出现奇怪的问题。

    Certbot 主要问题是依赖过多东西,官网的 CentOS 7 安装教程干脆让装个 snap ,过于复杂了。

    目前我选择 Lego https://github.com/go-acme/lego
    单文件,无外部依赖,配合自己写的 systemd service 和 timer 自动运行。
    DefoliationM
        8
    DefoliationM  
       126 天前 via Android
    看到开头就知道是公众号,直接翻到结尾。
    BaymaxK
        9
    BaymaxK  
    OP
       126 天前
    @DefoliationM 害 也不是,就是分享文章,没其他意思。
    BaymaxK
        10
    BaymaxK  
    OP
       126 天前
    @ysc3839 soga ,学到了
    BaymaxK
        11
    BaymaxK  
    OP
       126 天前
    @Nosub 学到了😂,这个不错
    yhxx
        12
    yhxx  
       126 天前   ❤️ 3
    v 站分享这个引不到什么流啊
    这里的人应该没几个不会的
    看标题说永久我还以为有什么新姿势
    BaymaxK
        13
    BaymaxK  
    OP
       126 天前
    @yhxx 😂不引流,就是单纯的分享下
    evill
        14
    evill  
       126 天前
    “最后,我们重启 nginx ”,acme 可以执行命令重启
    --reloadcmd "service nginx force-reload"
    goodryb
        15
    goodryb  
       126 天前
    不如你贴个原文的连接
    BaymaxK
        16
    BaymaxK  
    OP
       126 天前
    veapon
        17
    veapon  
       126 天前
    勾选第一页的所有权限
    ----
    这个这么高的权限吗?我去原文看了下,第一页其中包括 AdministratorAccess ,AliyunECSFullAccess ,AliyunRAMFullAccess 这些
    ounxnpz
        18
    ounxnpz  
       126 天前
    标题党
    BaymaxK
        19
    BaymaxK  
    OP
       126 天前
    @veapon 😂 他需要的是增、删权限,我图省事,就把第一页的全勾选了
    BaymaxK
        20
    BaymaxK  
    OP
       126 天前
    @bluicezhen 啊?不算吧,文中讲的东西确实无痛更新了
    madao199
        21
    madao199  
       126 天前
    你不是去年去了一家上市公司吗 被裁了?
    maladaxia
        22
    maladaxia  
       126 天前
    这不是正常操作吗?
    let's encrypt 官网就有, 还以为你发现新大陆了, 标题党👎🏿
    mohumohu
        23
    mohumohu  
       126 天前
    还不如用 caddy ,0 配置
    BaymaxK
        24
    BaymaxK  
    OP
       126 天前
    @madao199 对的,被裁员了,事业部被一锅端了
    ciki
        25
    ciki  
       126 天前   ❤️ 1
    看到标题想到不会是自动续期吧?没想到还真是,以为有什么黑科技。太水了
    busier
        26
    busier  
       126 天前
    acme 走 DNS API 更新的话,根本不涉及操作系统文件,就不应该给 root 权限操作
    imydou
        27
    imydou  
       126 天前   ❤️ 1
    续签就说续签,根证书都没永久
    root71370
        28
    root71370  
       126 天前
    不如体验下 1panel ,证书从来没管过~
    yunyuyuan
        29
    yunyuyuan  
       126 天前
    文章确实比较基础,但 OP 分享的精神还是值得支持的
    BaymaxK
        30
    BaymaxK  
    OP
       126 天前
    文章中阿里云的 ram 控制台授权那里给的权限太多了,其实只用给一个就可以了,v 站没法更新了,原文已更正错误了。原文地址: https://www.kaisir.cn/post/178
    NoDataNoBB
        31
    NoDataNoBB  
       126 天前
    我需要一台永久的服务器
    xiangyuecn
        32
    xiangyuecn  
       126 天前
    如果需要手动获取证书 pem 文件,可以使用我的网页版 ACME 客户端:
    向 Let's Encrypt 、ZeroSSL 、Google 等支持 ACME 协议的证书颁发机构,免费申请获得用于 HTTPS 的 SSL/TLS 域名证书( RSA 、ECC/ECDSA ),支持多域名和通配符泛域名;只需在现代浏览器上操作即可获得 PEM 格式纯文本的域名证书,不依赖操作系统环境,无需下载和安装软件,纯手动操作,只专注于申请获得证书这一件事。

    仅一个静态 HTML 文件,不依赖其他任何文件:
    https://xiangyuecn.github.io/ACME-HTML-Web-Browser-Client/ACME-HTML-Web-Browser-Client.html
    xiamuguizhi
        33
    xiamuguizhi  
       126 天前
    @imydou 是的。 需要楼主开放一个服务器给我们自动续签,实现永久 哈哈。
    Actrace
        34
    Actrace  
       126 天前
    @xiamuguizhi 微林有这项服务,免费的,非常好用。
    ilylx2008
        35
    ilylx2008  
       126 天前
    还得调用 cdn 接口自动更新 cdn 证书,很多地方
    charley008
        36
    charley008  
       126 天前
    这不是基本操作吗?对这 acme 文档来一遍也会啊。。
    alanyuan
        37
    alanyuan  
       126 天前 via iPhone
    虚假标题
    Rennen
        38
    Rennen  
       126 天前
    评论区看满离
    pota
        39
    pota  
       126 天前
    我现在就是自己写脚本自动化 acme.定时读取多个云的域名 https 有效期,通过 dns 对接多个云自动申请部署。很好用
    lxcopenwrt
        40
    lxcopenwrt  
       126 天前
    acme.sh 还不支持 ACME Renewal Information (ARI),这玩意给证书续期不受 letsencrypt 的速率限制,看 GitHub 有人提了 PR 但最后没合并进主线
    defunct9
        41
    defunct9  
       126 天前
    嘟噜嘟噜一大堆,用 lego 不比这个轻便么
    victimsss
        42
    victimsss  
       126 天前
    能更新阿里云上面的证书吗,比如

    , 这些证书是给 OSS 自定义域名用的
    sanshao124
        43
    sanshao124  
       57 天前
    @Actrace @BaymaxK @DefoliationM @Love4Taylor @NoDataNoBB @Nosub @Rennen @alanyuan @busier @charley008

    各位大佬,请教一个问题,我的系统是 mac ,安装了 docker ,如果我只是想通过 docker 实现自动获取某个域名的证书该怎么弄呢?最好带自动续期的

    我只需要本地获取了证书文件就行,比如域名.key ,域名.pem ,这种文件,不需要再做其他操作,网上搜的要么很复杂,要么就在 mac 上无法实现

    我对 docker 了解的不多,只会照着已有的命令改改参数
    Actrace
        44
    Actrace  
       56 天前
    @sanshao124 目前我用的是微林家的免费证书服务,只需要设置一个 CNAME 完成域名的验证,就可以自动生成证书,不需要跑 docker 什么的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1260 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 17:55 · PVG 01:55 · LAX 09:55 · JFK 12:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.