1. 概述
通过上述描述可知,一般意义上我们提到 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、绿色地址栏以及直接在地址栏显示公司名称,显著提高用户信任度。
总结来说,如果您追求最高级别的安全性和品牌信任度,尤其是对于处理敏感数据的网站,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 有没有自动续期的办法,有的:
以下客户端我就不展开描述了,请自行移步查看
- acme.sh (Compatible to bash, dash and sh)
- https://certbot.eff.org/
- njs-acme JavaScript library compatible with the ‘ngx_http_js_module’ runtime (NJS), allows for the automatic issue of TLS/SSL certificates for NGINX without restarts
- lua-resty-auto-ssl
- Nginx ACME
- lua-resty-acme
这里付上 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。
在追求性能的道路上,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 证书生效吧