网站启用 HTTPS 可以应对运营商的「HTTP 劫持」,避免被插入广告。大多数情况,使用免费的「SSL 证书」就足够了。

推荐的 CA 及签发工具

ZeroSSLLet’s Encrypt 是两个常见的 CA(证书授权机构)。最大的特点是,提供免费的 SSL 证书,有效期为 90 天。有以下优点:

  • 支持 Wildcard Certificates (通配符证书,类似 *.example.com )
  • 支持 ECC 证书(同等安全下,ECC 证书比 RSA 体积小)
  • 可以通过 API 直接签发,不用手动申请。

推荐使用 acme.sh 作为证书签发工具。它支持 ACME v2,纯 shell 实现,无其它依赖,Linux / BSD 都可以使用。

安装 acme.sh

curl https://get.acme.sh | sh -s email=[email protected]

有些 Linux 发行版默认没有安装 cron,导致安装无法完成。像 Alpine Linux、Arch Linux 之类的,可以安装 cronie, 再执行一次上方的脚本。

脚本会做 3 件事情:

  • 复制 acme.sh 到 ~/.acme.sh/
  • 创建 alias :acme.sh=~/.acme.sh/acme.sh
  • 创建每日执行的 cronjob 。

配置 acme.sh

Wildcard Certificate(通配符证书)要求必须使用域名验证。acme.sh 支持几十个 DNS 服务商的 API。这里以「Cloudflare DNS」举例。

编辑 ~/.acme.sh/account.conf,加入 Cloudflare DNS 的 API Key 及 email。

ACCOUNT_EMAIL="[email protected]"
export CF_Key="My Cloudflare API Key"
export CF_Email="[email protected]"

Cloudflare API Key 详见:“Profile - Global API Key - View API Key”。其它 DNS 配置参考 How to use DNS API

签发证书

acme.sh --issue -d example.com -d '*.example.com' -k ec-256 --dns dns_cf --dnssleep 60

参数说明:

  • --issue:签发证书。
  • -d:后面跟域名,通配符域名需要加单引号。
  • example.com: 要签发证书的域名,替换成你自己的。
  • -k ec-256:签发 ECC 证书(-k 等于 --keylength)。
  • --dns dns_cf:表示使用 Cloudflare DNS API。
  • --dnssleep 60:dns 更新后,等待 60 秒。

因为签发的是 ecc 证书,生成的证书文件夹是 example.com_ecc 。

签发成功后会有以下类似提示:

Your cert is in  /PATH/.acme.sh/example.com_ecc/examplecom.cer
Your cert key is in  /PATH/.acme.sh/example.com_ecc/example.com.key
The intermediate CA cert is in  /PATH/.acme.sh/example.com_ecc/ca.cer
And the full chain certs is there:  /PATH/.acme.sh/example.com_ecc/fullchain.cer

安装证书

修改服务器的配置,指定证书路径。

# Caddy Server
tls /srv/ssl/example.com_fullchain.cer /srv/ssl/example.com.key

# nginx
ssl_certificate     /srv/ssl/example.com_fullchain.cer;
ssl_certificate_key /srv/ssl/example.com.key;
acme.sh --install-cert \
        -d example.com --ecc \
        --key-file /srv/ssl/example.com.key \
        --fullchain-file /srv/ssl/example.com_fullchain.cer \
        --reloadcmd "rc-service caddy reload"

参数说明:

  • --install-cert:安装证书,把证书文件复制到相应的目录。
  • -d:指定域名。
  • --ecc:ecc 证书使用此参数,对应签发时使用的-k ec-256
  • --key-file:指定 key 的存储路径。
  • --fullchain-file:指定 合并的证书文件 的存储路径。
  • --reloadcmd:复制完成后执行命令。这里是「重新加载 caddy」,如果用的是 nginx 可以使用 systemctl restart nginxnginx -s reload

证书路径及重新加载的命令,请根据需要调整功能。

自动更新证书

acme.sh 可以使用 crontab 定时检查证书是否过期,并重新签发。crontab 文件一般位于 /var/spool/cron//etc/crontabs 目录下。

crontab -l 查看计划任务;crontab -e 编辑计划任务。

cronjob 格式一般如下:

# 分钟 小时 日期 月份 星期 命令
17 02 * * * "/PATH/.acme.sh"/acme.sh --cron --home "/PATH/.acme.sh" > /dev/null

表示每天凌晨 02:17 检查证书是否到期。默认设定证书到期前 30 天更新证书。

如果安装时 cronjob 没有添加成功,可以使用 acme.sh --install-cronjob 手动添加。

手动更新证书

# 更新一个证书
acme.sh --renew -d example.com --ecc

# 更新所有证书
acme.sh --renew-all

# 运行 cronjob 来更新证书(可用于检查 cronjob 命令是否正确)
acme.sh --cron

更新证书时,会自动跳过未到期的。可以使用 --force 参数进行强制更新。

其它说明

# 默认 CA 为 zerossl,可以切换为 letsencrypt
acme.sh --set-default-ca --server letsencrypt

# 使用 staging 环境测试签发,防止超限导致 IP 被封。
acme.sh --staging --issue -d example.com -d '*.example.com' -k ec-256 --dns dns_cf --dnssleep 60

# 更新账户 email
acme.sh --update-account --accountemail '[email protected]'

# 如果需要同时使用多个 DNS API Key,可以使用 --config-home 指定配置的目录,issue、install-cert、cronjob都需要
acme.sh --config-home '/PATH/TO/CONFIG_DIR' --issue -d example.com -d '*.example.com' -k ec-256 --dns dns_cf --dnssleep 60

# 查看证书
openssl x509 -text -noout -in fullchain.cer