文章
问答
冒泡
通过 Caddy Server 实现快速自动申请 SSL 证书,自动续期

1. 概述

        SSL证书是数字证书的一种,类似于驾驶证、护照和营业执照的电子副本。因为配置在服务器上,也称为SSL服务器证书。SSL 证书就是遵守 SSL协议,由受信任的数字证书颁发机构CA,在验证服务器身份后颁发,具有服务器身份验证数据传输加密功能。
 
        SSL证书通过在客户端浏览器和Web服务器之间建立一条SSL安全通道(Secure socket layerSSL)安全协议是由Netscape Communication公司设计开发。该安全协议主要用来提供对用户和服务器的认证;对传送的数据进行加密和隐藏;确保数据在传送中不被改变,即数据的完整性,现已成为该领域中全球化的标准。
 
       由于SSL技术已建立到所有主要的浏览器和WEB服务器程序中,因此,仅需安装服务器证书就可以激活该功能了,即通过它可以激活SSL协议,实现数据信息在客户端和服务器之间的加密传输,可以防止数据信息的泄露,保证了双方传递信息的安全性,而且用户可以通过服务器证书验证他所访问的网站是否是真实可靠。数字签名又名数字标识、签章 (即 Digital Certificate,Digital ID ),提供了一种在网上进行身份验证的方法,是用来标志和证明网络通信双方身份的数字信息文件,概念类似日常生活中的司机驾照或身份证
 
        数字签名主要用于发送安全电子邮件、访问安全站点、网上招标与投标网上签约、网上订购、网上公文安全传送、网上办公、网上缴费、网上缴税以及网上购物等安全的网上电子交易活动。
 
(PS:转述了百度百科的定义说明)

通过上述描述可知,一般意义上我们提到 ssl 证书即用于网站安全认证的服务器 ssl 证书,而非用于数字签名和其他用途。今天我们就来讲讲如何为网站部署 SSL 证书,又如何快速获取 ssl 证书和实现自动续期(SSL 证书早期是一年一续,现在 30 天,频繁手动申请 ssl 证书太费劲)

2. 申请SSL 的途径

(1)通过公有云服务商(阿里云、腾讯云、华为云、亚马逊AWS、 Cloudflare等等)

(2)第三方专业 SSL 证书机构:

  • WoTrus沃通
      沃通是国内唯一一家通过Adobe认证的CA(PDF签名加密证书),能签发全球信任的采用国产加密算法(SM2) 的SSL证书和代码签名证书的商业CA。是中国最大的国产品牌数字证书颁发机构之一,中国市场占有率超过70%!
  • GDCA数安时代
      GDCA数安时代成立于2003年4月,一直致力于发展成为一流的网络信任服务商,经过十余年不断开拓进取、突破创新,逐步在电子认证及相关信息安全产品、服务领域取得了行业领先地位。GDCA通过了WEBTRUST国际认证,成为国内仅有的几家具备国际化电子认证服务能力的企业之一。
  • CFCA中国金融认证中心(政府机构、银行、12306等均在使用)
      中国金融认证中心China Financial Certification Authority,简称CFCA,是由中国人民银行于1998年牵头组建、经国家信息安全管理机构批准成立的国家级权威安全认证机构,是国家重要的金融信息安全基础设施之一。CFCA成为首批获得电子认证服务许可的电子认证服务机构。截至目前,超过2400家金融机构使用CFCA的电子认证服务,在使用数字证书的银行中占98%的份额。
  • 安信证书
      安信证书是国内知名的国际知名品牌SSL证书代理商,专售Symantec、GeoTrust、Comodo、Thawte以及RapidSSL等多家全球权威CA机构的SSL数字证书。证书种类齐全,价格优惠,而且提供高级证书需要的邓白氏、律师意见信等服务。凡在安信证书申请Symantec、Geotrust、Comodo等国际品牌证书,均可享受免费安装SSL证书的服务。
  • ZeroSSL (国外证书机构)

(3)开源非营利性SSL证书机构 

  • Let’s Encrypt

Let’s Encrypt 是一家免费、开放、自动化的公益性证书颁发机构(CA), 由互联网安全研究组(ISRG)运作。

以尽可能对用户友好的方式免费提供数字证书,助力各类网站启用 HTTPS (SSL/TLS)。 这是因为我们想要创建一个更安全,更尊重隐私的 Web 环境。

Let’s Encrypt 的宗旨是:

      • 免费:任何人只要持有域名就可以通过 Let’s Encrypt 免费获得可信的数字证书。
      • 自动:使用服务器上运行的软件即可与 Let’s Encrypt 交互,轻松实现证书的获取、安全配置以及自动续期。
      • 安全:Let’s Encrypt 不仅颁发证书,还在积极协助广大网站运作者正确维护服务器安全,从而成为一个推动 TLS 安全最佳实践的平台。
      • 透明:我们颁发及吊销的所有证书都有公开记录,任何人都可以查阅。
      • 开放:我们的证书自动签发及续期协议已作为开放标准发布,各方均可采用。
      • 合作:正如我们所依赖的互联网基础协议一样,Let’s Encrypt 是一支多方合作形成的公益力量,绝不受个别组织团体掌控。

您还可以进一步了解 Let’s Encrypt 证书颁发机构的运作方式

           Let’s Encrypt 就是我们今天要讲的主角,通过  Let’s Encrypt 可以申请免费且自动续期(通过各类 bot 和 脚本客户的)的 ssl 证书 (注意:这类证书虽说是国外非盈利性机构,开源证书,但是仍然掌握在国外机构,所以不建议用于商业机密性场景,一般用于个站、测试网站、一般性网站加密场景足以,如有机密性需求,建议通过国内 SSL 证书机构申请国密 SSL 证书,例如银行和 12306

3. SSL 证书的类型

选择SSL证书时,您需要根据您的网站性质、安全需求以及预算来决定。DV(域名验证)、OV(组织验证)、EV(扩展验证)是三种不同类型的SSL证书,它们在验证深度、安全性和可见性方面有所差异:

DV(域名验证型)SSL证书
验证内容:仅验证域名的所有权,不涉及组织信息。
申请速度:最快,通常几分钟到几小时。
价格:最经济,有时甚至可免费获取。
适用场景:个人网站、博客、小型企业或测试环境,对展示企业身份没有特别要求。
浏览器显示:提供HTTPS和小锁图标,但不会显示公司名称。

OV(组织验证型)SSL证书
验证内容:验证域名所有权的同时,还需验证组织的真实存在性。
申请速度:较长,一般需1-5个工作日。
价格:中等,比DV证书贵,但性价比高。
适用场景:企业官方网站、电子商务平台等,需要提升用户信任度的网站。
浏览器显示:提供HTTPS、小锁图标,证书详细信息中包含公司名称。

EV(扩展验证型)SSL证书
验证内容:最为严格,验证域名所有权、组织信息以及实体的合法性,可能包括法律文件审核。
申请速度:最长,可能需要几天到几周。
价格:最贵,适合预算充足且对安全及品牌形象有高要求的机构。
适用场景:银行、金融机构、大型电商平台等,特别强调安全性和品牌信誉的网站。
浏览器显示:提供HTTPS、绿色地址栏以及直接在地址栏显示公司名称,显著提高用户信任度。

SSL证书详情页

总结来说,如果您追求最高级别的安全性和品牌信任度,尤其是对于处理敏感数据的网站,EV证书是最佳选择。若预算有限且主要是为了基本的加密需求,DV证书足够。而OV证书则是一个平衡选择,适合大多数需要展示一定企业资质的商业网站。

我们今天要讲的也主要是 DV 类型

4.  Nginx 部署 SSL 证书

        目前主流网站均在使用 Nginx 作为 web 服务器,也有 Apache、Tomcat、Caddy、应用程序直接加载 SSL证书文件 等方式,这里略带下 Nginx 是如何部署 ssl 证书的,其他的不在本文重点,因此略过。

查看 nginx 是否安装 http_ssl_module 模块。

$ /usr/local/nginx/sbin/nginx -V

如果出现 configure arguments: –with-http_ssl_module, 则已安装(下面的步骤可以跳过,进入 nginx.conf 配置)。

在 nginx 目录新建 cert 文件夹存放证书文件。

$ cd /usr/local/nginx
$ mkdir cert

将这两个文件上传至服务器的 cert 目录里。
这里使用 mac 终端上传至服务器的 scp 命令(这里需要新开一个终端,不要使用连接服务器的窗口):

$ scp /Users/yourname/Downloads/ssl.pem root@xxx.xx.xxx.xx:/usr/local/nginx/cert/
$ scp /Users/yourname/Downloads/ssl.key root@xxx.xx.xxx.xx:/usr/local/nginx/cert/

编辑 /usr/local/nginx/conf/nginx.conf 配置文件:

配置 https server。注释掉之前的 http server 配置,新增 https server:

server {
    # 服务器端口使用443,开启ssl, 这里ssl就是上面安装的ssl模块
    listen       443 ssl;
    # 域名,多个以空格分开
    server_name  ithere.com www.ithere.net;
    
    # ssl证书地址
    ssl_certificate     /usr/local/nginx/cert/ssl.pem;  # pem文件的路径
    ssl_certificate_key  /usr/local/nginx/cert/ssl.key; # key文件的路径
    
    # ssl验证相关配置
    ssl_session_timeout  5m;    #缓存有效期
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;    #加密算法
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;    #安全链接可选的加密协议
    ssl_prefer_server_ciphers on;   #使用服务器端的首选算法

    location / {
        root   html;
        index  index.html index.htm;
    }
}

 将 http 重定向 https。

server {
    listen       80;
    server_name  ithere.net www.ithere.net;
    return 301 https://$server_name$request_uri;
}

有没有发现,这都是手动方式,每当证书要过期都得手动替换证书,那 Nginx 有没有自动续期的办法,有的:

以下客户端我就不展开描述了,请自行移步查看

这里付上 let's Encrypt  ACME 客户端 https://letsencrypt.org/zh-cn/docs/client-options/   

 

5. 主角 Caddy 登场

在实际配置 Caddy 之前,我们先来聊下,Let’s Encrypt 是如何为您自动申请 ssl 证书的?

当您从 Let’s Encrypt 获得证书时,Let’s Encrypt 的服务器会验证您是否使用 ACME 标准定义的验证方式来验证您对证书中域名的控制权。如何证明您对此域名拥有控制权,有几种验证方式:

HTTP-01 验证

这是当今最常见的验证方式。 Let’s Encrypt 向您的 ACME 客户端提供一个令牌,然后您的 ACME 客户端将在您对 Web 服务器的 http://<你的域名>/.well-known/acme-challenge/<TOKEN>(用提供的令牌替换 <TOKEN>)路径上放置指定文件。 该文件包含令牌以及帐户密钥的指纹。 一旦您的 ACME 客户端告诉 Let’s Encrypt 文件已准备就绪,Let’s Encrypt 会尝试获取它(可能从多个地点进行多次尝试)。 如果我们的验证机制在您的 Web 服务器上找到了放置于正确地点的正确文件,则该验证被视为成功,您可以继续申请颁发证书。 如果验证检查失败,您将不得不再次使用新证书重新申请。

我们的 HTTP-01 验证最多接受 10 次重定向。 我们只接受目标为“http:”或“https:”且端口为 80 或 443 的重定向。 我们不目标为 IP 地址的重定向。 当被重定向到 HTTPS 链接时,我们不会验证证书是否有效(因为验证的目的是申请有效证书,所以它可能会遇到自签名或过期的证书)。

HTTP-01 验证只能使用 80 端口。 因为允许客户端指定任意端口会降低安全性,所以 ACME 标准已禁止此行为。

优点:

  • 它可以轻松地自动化进行而不需要关于域名配置的额外知识。
  • 它允许托管服务提供商为通过 CNAME 指向它们的域名颁发证书。
  • 它适用于现成的 Web 服务器。

缺点:

  • 如果您的 ISP 封锁了 80 端口,该验证将无法正常工作(这种情况很少见,但一些住宅 ISP 会这么做)。
  • Let’s Encrypt 不允许您使用此验证方式来颁发通配符证书。
  • 您如果有多个 Web 服务器,则必须确保该文件在所有这些服务器上都可用。

DNS-01 验证(本文推荐方式)

此验证方式要求您在该域名下的 TXT 记录中放置特定值来证明您控制域名的 DNS 系统。 该配置比 HTTP-01 略困难,但可以在某些 HTTP-01 不可用的情况下工作。 它还允许您颁发通配符证书。 在 Let’s Encrypt 为您的 ACME 客户端提供令牌后,您的客户端将创建从该令牌和您的帐户密钥派生的 TXT 记录,并将该记录放在 _acme-challenge.<YOUR_DOMAIN> 下。 然后 Let’s Encrypt 将向 DNS 系统查询该记录。 如果找到匹配项,您就可以继续颁发证书!

由于颁发和续期的自动化非常重要,只有当您的 DNS 提供商拥有可用于自动更新的 API 时,使用 DNS-01 验证方式才有意义。 我们的社区在此处提供了此类 DNS 提供商的列表。 您的 DNS 提供商可能与您的域名注册商(您从中购买域名的公司)相同或不同。 如果您想更改 DNS 提供商,只需在注册商处进行一些小的更改, 无需等待域名即将到期。

请注意,将完整的 DNS API 凭据放在 Web 服务器上会显着增加该服务器被黑客攻击造成的影响。 最佳做法是使用权限范围受限的 API 凭据,或在单独的服务器上执行 DNS 验证并自动将证书复制到 Web 服务器上。

由于 Let’s Encrypt 在查找用于 DNS-01 验证的 TXT 记录时遵循 DNS 标准,因此您可以使用 CNAME 记录或 NS 记录将验证工作委派给其他 DNS 区域。 这可以用于将 _acme-challenge 子域名委派给验证专用的服务器或区域。 如果您的 DNS 提供商更新速度很慢,那么您也可以使用此方法把验证工作委派给更新速度更快的服务器。

大多数 DNS 提供商都有一个“更新时间”,它反映了从更新 DNS 记录到其在所有服务器上都可用所需的时间。 这个时间可能很难测量,因为这些提供商通常也使用任播,这意味着多个服务器可以拥有相同的 IP 地址,并且根据您在世界上的位置,您和 Let’s Encrypt 可能会与不同的服务器通信(并获得不同的应答)。 最好的情况是 DNS API 为您提供了自动检查更新是否完成的方法。 如果您的 DNS 提供商没有这样的方法,您只需将客户端配置为等待足够长的时间(通常多达一个小时),以确保在触发验证之前更新已经完全完成。

您可以为同一名称提供多个 TXT 记录。 例如,如果您同时验证通配符和非通配符证书,那么这种情况可能会发生。 但是,您应该确保清理旧的 TXT 记录,因为如果响应大小太大,Let’s Encrypt 将拒绝该记录。

优点:

  • 您可以使用此验证方式来颁发包含通配符域名的证书。
  • 即使您有多个 Web 服务器,它也能正常工作。

缺点:

  • 在 Web 服务器上保留 API 凭据存在风险。
  • 您的 DNS 提供商可能不提供 API。
  • 您的 DNS API 可能无法提供有关更新时间的信息。

 

TLS-ALPN-01验证

这一验证类型是在 TLS-SNI-01 被弃用后开发的,并且已经开发为单独的标准。 与 TLS-SNI-01 一样,它通过 443 端口上的 TLS 执行。 但是,它使用自定义的 ALPN 协议来确保只有知道此验证类型的服务器才会响应验证请求。 这还允许对此质询类型的验证请求使用与要验证的域名匹配的SNI字段,从而使其更安全。

这一验证类型并不适合大多数人。 它最适合那些想要执行类似于 HTTP-01 的基于主机的验证,但希望它完全在 TLS 层进行以分离关注点的 TLS 反向代理的作者。 现在其主要使用者为大型托管服务提供商,但 Apache 和 Nginx 等主流 Web 服务器有朝一日可能会实现对其的支持(Caddy已经支持了这一验证类型)。

优点:

  • 它在 80 端口不可用时仍可以正常工作。
  • 它可以完全仅在 TLS 层执行。

缺点:

  • 它不支持 Apache、Nginx 和 Certbot,且很可能短期内不会兼容这些软件。
  • 与 HTTP-01 一样,如果您有多台服务器,则它们需要使用相同的内容进行应答。
  • 此方法不能用于验证通配符域名。

以上描述了这么多,ssl 证书控制权验证挑战,里面涉及到一个 DNS 解析的话题,还不能略过,一般我们申请的域名名称服务器,也就是解析服务器,一般都是域名提供商提供的,也有第三方的解析服务器,例如我就是用的腾讯的 DNSPOD,当然一般的共有云服务商都有 DNS 解析的 SDK 或者 API (这点是关键,因为 caddy 自身支持了一部分 DNS 解析服务商,社区也实现了一部分,例如AliDNS、DNSPOD)Let's Encrypt 客户端包括 caddy server 需要 dns api 的 token 去自动创建 txt 的解析记录,以证明 您对dns的控制权。

https://github.com/caddy-dns 可以在此查看是否有你的域名解析服务商插件

下面讲讲如何通过 dns pod 创建 api token (需要将域名名称服务器指向 dns pod 解析服务器)

例如 ithere.net 的解析是在阿里云的,如果要利用 dnspod 解析,那么需要在阿里云域名后台更改名称服务器为 dnspod 提供的DNS 服务器地址:(如下图所示)

下图是我在 dnspod 正常解析的域名列表

在 dnspod 控制台点击头像,找到 api 密钥菜单

在 api 密钥页面,创建密钥,会得到一个 一个 ID 和 token 文本,其中 token 需要自己离线记录保存

有了上面的准备,终于开始要干大活儿了,水了一堆话,开始走起,什么?你还不了解 caddy 是什么,那么插端介绍:

Caddy 首先是一个用Go实现的Web Server。

https://caddyserver.com/

在追求性能的道路上,nginx已经一骑绝尘。这种情况下诞生的 Caddy有什么特性呢?

Caddy的作者Matt Holt有这样的理念: 其他Web Server为Web而设计,Caddy为human设计。一句话就是 Caddy主打易用性,使用配置简单。

Caddy有下面这些开箱即用的特性:

  • 全自动支持HTTP/2协议,无需任何配置。
  • Caddy 使用 Let’s Encrypt 让你的站点全自动变成HTTPS,无需任何配置。
  • 合理使用多核多核 得益于go的特性
  • 完全支持IPv6环境
  • Caddy 对WebSockets有很好的支持
  • 自动把Markdown转成 HTML
  • Caddy 对log格式的定义很容易
  • 易于部署 得益于go的特性,caddy只是一个小小的二进制文件,没有依赖,很好部署
  • 得益于Go的跨平台特性,Caddy很容易的支持了三大主流系统:Windows、 Linux、Mac
“几乎所有的功能在Caddy里的都是插件,HTTP服务器是插件,高级的TLS特性也是插件,每一行命令实现的功能都是一个插件”

 

好了介绍也介绍完了,如何下载安装

可以通过官网 download 页面定制包含哪些插件,进行下载二进制文件

也可以通过 docker file 自行编译定制

FROM caddy:builder-alpine AS builder

ENV APK_SOURCE="mirrors.aliyun.com"
ENV GOPROXY="https://goproxy.cn"
ENV GOSUMDB="sum.golang.org"
ENV GO111MODULE="on"

RUN xcaddy build \
    --with github.com/caddy-dns/dnspod \
    --with github.com/caddy-dns/vultr \
    --with github.com/jicjoy/caddy-dns-huaweidns \
    --with github.com/caddy-dns/duckdns \
    --with github.com/caddy-dns/cloudflare \
    --with github.com/kirsch33/realip \
    --with github.com/caddy-dns/alidns \
    --with github.com/captncraig/cors \
    --with github.com/sjtug/caddy2-filter \
    --with github.com/caddyserver/replace-response \
    --with github.com/mholt/caddy-webdav \
    --with github.com/imgk/caddy-pprof


FROM caddy:alpine
ENV TZ Asia/Shanghai
ENV APK_SOURCE="mirrors.aliyun.com"

COPY ./Caddyfile /etc/caddy/Caddyfile
COPY --from=builder /usr/bin/caddy /usr/bin/caddy

RUN set -e \
    && echo 'hosts: files dns' > /etc/nsswitch.conf
    && apk upgrade \
    && apk add bash tzdata mailcap \
    && ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime \
    && echo ${TZ} > /etc/timezone \
    && rm -rf /var/cache/apk/*

EXPOSE 80 443

CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]

上述配置是本人的私有配置,保护其他插件,您可以根据自己的需求自行删减

下面是 docker-compose.yml

version: "2"

services:
  ### Caddy Server #########################################
  caddy:
    build: ./stack/caddy
    volumes:
      - ./www:/var/www:cached
      - ./configs/caddy:/etc/caddy
      - ./logs:/var/log/caddy
      - ./data/caddy:/root/.caddy
      - ./data/gitea:/gitea
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "4433-4438:4433-4438"
    environment:
      - TZ=Asia/Shanghai
      - LANG=zh_CN.utf8
      - DNSPOD_API_KEY=${DNS_TOKEN}

终于上 CaddyServer 配置文件了 Caddyfile

{
   debug
   auto_https disable_redirects
   order filter after encode
   email admin@polestarry.com
   acme_ca https://acme-staging-v02.api.letsencrypt.org/directory

   https_port 443

}

:443, *.ithere.net, www.ithere.net {
   tls admin@ithere.net  {
     protocols tls1.2 tls1.3
     dns vultr {env.DNS_TOKEN}
     ciphers TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
   }
   log {
     level ERROR
   }
   #respond "Service Unavailable" 503 {
   #  close
   #}
   header / {
      -Server
   }
   file_server
   try_files {path}.html {path}
}

*.ithere.net:80, www.ithere.net:80 {
    redir https://{host}{uri} permanent
}

至此,全部配置完毕,docker compose up -d  或者直接在本机 run caddy 就等着 https 证书生效吧

 

 

 

 

 


 

caddy ssl

关于作者

wind
像风一样的男子
获得点赞
文章被阅读