SSL:Let's Encrypt免费证书 和ACME客户端介绍

tlin82大约 6 分钟SSLWeb安全ExchangeServerWindowsLinuxLetsEncrypt免费证书ACME

前言

从前使用的免费SSL证书,开始从1年免费变成了3个月,不再降了。开始考虑使用Let's Encrypt免费证书,结合它的客户端实现自动续订。

正文

Let's Encrypt介绍

Let's Encrypt 是免费、开放和自动化的证书颁发机构。由非盈利组织互联网安全研究小组(ISRG)运营。这里访问 Let's Encrypt官网open in new window.

是否安全

  • 很多大厂,例如Cloudflare都在使用。个人网站使用Let's Encrypt免费证书还是挺安全的。
  • 小企业不想使用昂贵的商业收费的ssl证书也可以考虑。

ACME


ACMElet's Encrypt证书管理实现协议。实现ACME协议的客户端可以实现证书申请、续订等。

选择ACME客户端


实现ACME协议的客户端,有官方版本,也有第三方。

wacs.exe --source manual 
--host mail.example.com,webmail.example.com,autodiscover.example.com 
--certificatestore My 
--acl-fullcontrol "network service,administrators" --installation iis,script 
--installationsiteid 1 
--script "./Scripts/ImportExchange.v2.ps1" --scriptparameters "'{CertThumbprint}' 'IIS,SMTP,IMAP' 1 '{CacheFile}' '{CachePassword}' '{CertFriendlyName}'"

根据自己情况选择ACME客户端

本例选择使用官方客户端acme.sh

选择ACME Challenge


开始之前,要先了解一下ACME Challenge。Let's Encrypt仅给域名所有者颁发免费证书,因此申请证书前我们需要通过域名所有者身份验证。Let's Encrypt验证方法就是Challenge。了解更多 https://letsencrypt.org/docs/challenge-types/open in new window

Challenge大概有这两种:

  • HTTP-01 challenge
  • DNS-01 challenge

HTTP challenge利弊

利:配置比较容易,还可以支持自动续订。

弊:需要在防火墙上长期开放 80 端口。如果你无法控制防火墙或你的ISP因为安全原因不开放80,就无法使用这个HTTP challenge。

DNS challenge 利弊

利:不需要开放80端口。如果DNS服务商支持api访问,可以很方便自动续订证书;还支持通配符证书。

弊:如果DNS服务商不支持API访问,无实现自动续订证书。每次续订证书需要手动,比较麻烦。

根据自己情况选择

本例使用 HTTP Challene。 如果选择DNS chalenge, 可以先查看一下自己的DNS服务商在受支持列表中:

https://github.com/acmesh-official/acme.sh/wiki/dnsapiopen in new window

选择ACME.sh的使用模式


ACME.sh支持很多安装和使用模式。根据自己情况选择模式,不同模式则证书申请、安装选项都不同。

  • webroot模式
  • standalone模式
  • nginx模式
  • 其他

根据自己情况选择模式

https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-certopen in new window

本例使用了webroot模式。

开始Acme.shopen in new window 和 webroot模式


以域名proxy.example.cn举例:

以下操作建议root权限

  • 1、网络防火墙上开启80端口映射。

端口服务器映射按照你的防火墙配置,步骤略。

关于80端口

Let’s Encrypt gives a token to your ACME client, and your ACME client puts a file on your web server at http://YOUR_DOMAIN.well-known/acme-challenge/TOKEN. That file contains the token, plus a thumbprint of your account key. Once your ACME client tells Let’s Encrypt that the file is ready, Let’s Encrypt tries retrieving it (potentially multiple times from multiple vantage points). If our validation checks get the right responses from your web server, the validation is considered successful and you can go on to issue your certificate. If the validation checks fail, you’ll have to try again with a new certificate.

注意

80端口要保持一直开放。从首次申请到后期每次自动续订。关于保持80端口常开,很多人认为不安全,因此Let's Encrypt写了一篇文章特别解释了为什么防火墙保持80端口不会带来安全风险。https://letsencrypt.org/docs/allow-port-80/open in new window 。开放了80端口,要注意把http重定向80到443解决网络攻击面。

  • 2、在web服务器上创建HTTP Challenge主目录
mkdir -p /var/www/html/proxy.example.cn/
  • 3、修改现有nginx配置,在现有配置外添加一个的HTTP challenge 目录。

主要是root指令指定一个webroot站点目录,如下:

server {

        listen       80;
        server_name proxy.example.cn;
        location ^~ /.well-known/acme-challenge/ {
	        default_type "text/plain";
	        allow all;
	        root /var/www/html/proxy.example.cn/;
  		 }
		location /{
	   		rewrite ^(.*)$  https://$host$1 permanent;
	   	}
}

  • 4、开始申请 Request the cert
acme.sh --issue -d proxy.example.cn -w /var/www/html/proxy.example.cn/

如果申请成功,则输出一下类似信息:


[Mon Jun  3 16:50:13 CST 2024] Your cert is in: /root/.acme.sh/proxy.example.cn_ecc/proxy.example.cn.cer
[Mon Jun  3 16:50:13 CST 2024] Your cert key is in: /root/.acme.sh/proxy.example.cn_ecc/proxy.example.cn.key
[Mon Jun  3 16:50:13 CST 2024] The intermediate CA cert is in: /root/.acme.sh/proxy.example.cn_ecc/ca.cer
[Mon Jun  3 16:50:13 CST 2024] And the full chain certs is there: /root/.acme.sh/proxy.example.cn_ecc/fullchain.cer

  • 5、安装和拷贝证书。必须使用amce的命令。否则不会创建自动续订的cron任务。
acme.sh --install-cert -d proxy.example.cn \
--cert-file      /usr/local/openresty/nginx/cert/certstore/proxy.example.cn.cer  \
--key-file       /usr/local/openresty/nginx/cert/certstore/proxy.example.cn.key  \
--fullchain-file /usr/local/openresty/nginx/cert/certstore/fullchain.cer \
--reloadcmd     "/path_to_nginx/nginx -s reload"

安装成功后,输出一下类似信息:

[Mon Jun  3 17:13:52 CST 2024] The domain 'proxy.example.cn' seems to have a ECC cert already, lets use ecc cert.
[Mon Jun  3 17:13:52 CST 2024] Installing cert to: /usr/local/openresty/nginx/cert/certstore/proxy.example.cn.cer
[Mon Jun  3 17:13:52 CST 2024] Installing key to: /usr/local/openresty/nginx/cert//certstore/proxy.example.cn.key
[Mon Jun  3 17:13:52 CST 2024] Installing full chain to: /usr/local/openresty/nginx/cert/certstore/fullchain.cer
[Mon Jun  3 17:13:52 CST 2024] Run reload cmd: nginx -s reload
[Mon Jun  3 17:13:52 CST 2024] Reload success
  • 6、修改nginx配置,把站点证书指向到以上证书路径。
    ssl_certificate   /usr/local/openresty/nginx/cert/certstore/fullchain.cer;
    ssl_certificate_key  /usr/local/openresty/nginx/cert/certstore/proxy.example.cn.cer.key;

务必指定的是fullchain.cer这个包含完整证书链的证书,否则使用cURL测试或是其他工具可能大概率收到 “ssl certificate problem unable to get local issuer certificate”类似错误信息

  • 然后 nginx -t 检查nginx配置
  • 以及nginx -s reload
  • 验证证书是否有效。
  • 检查cron是否右一条任务。
crontab -l

这个crob job主要是实现自动续订。auto renewal is scheduled to run by a cron job from the install process check and confirm that the cron job is already there.

配置邮件通知


通过邮件跟踪证书是否续订成功

  • 配置smtp参数。vi /root/.bashrc

# Email configuration for acme email notifications
export SMTP_FROM="waf@example.com"
export SMTP_TO="it-sysops@example.com"
export SMTP_HOST="mailserver.example.com"
export SMTP_SECURE="none"
export SMTP_BIN="/usr/bin/python2"
  • 开启邮件通知
acme.sh --set-notify --notify-hook smtp --notify-level 2
  • 检查是否收到测试邮件。

关于证书续订


  • 在前面步骤使用cron实现自动续订后,每次续订成功后,会收到以下类似邮件通知:

Good, the cert is renewed.

  • 续订周期。默认证书每60天续订一次,即剩余30天会通过cron进行自动续订。

  • 查看和验证当前证书(续订)信息:

acme.sh --list
  • 如果自动续订不成功,可以尝试手动续订
 acme.sh --renew -d proxy.example.com --force

  1. 详细使用案例可以参考 Install FREE Let’s Encrypt certificate in Exchange Serveropen in new window ↩︎

  2. 大致步骤: ↩︎