使用 Google CA 免费签发 SSL 证书

众所周知,我们可以使用 acme.sh 客户端来申请HTTPS证书,达到使网站更安全的目的。而 acme.sh 支持的 CA 有 ZeroSSL 、 Let’s Encrypt 、 Buypass 和 SSL.com 等。

但是在上个月 30 日,Google Cloud 在其博客发表文章 Automate Public Certificates Lifecycle Management via RFC 8555 (ACME),文章大意是:Google Cloud 推出了自动化的公共 CA 管理程序(流程),大家可以通过 ACME 协议来申请 Google Trust Services 的证书了。这套系统实现了大规模的公共证书的部署云云。

简而言之,对诸位站长而言,免费 SSL 证书多了一种选择。目前 GCP 公共证书和 Let’s Encrypt 一样,有效期最长 90 天。前者的其他特性列举如下:

  • 支持多域名及通配符;(与 Let’s Encrypt 相同)
  • 仅支持 DNS 验证和文件验证,不支持邮件验证;(与 Let’s Encrypt 相同)
  • 支持 IP 地址,但是仅允许该 IP 地址块的所有者进行验证;(Let’s Encrypt 暂不支持)
  • 不支持 IDN (International Domain Name, 国际化域名,使用 Punycode 进行编码,形如 xn--1.xn--2).(Let’s Encrypt 已经支持)
  • 若 CSR 为 ECC ,则仅叶子证书(最终用户证书)为 ECC 。(Let’s Encrypt 已经支持全链 ECC)

以下是操作流程。本操作流程仅为当时操作之步骤,并不保证长期有效。

申请权限

欲使用此服务,需要一个 Google Cloud Platform 账号,并填写表单以申请内测权限。

表单里有一项 Google Cloud Project ID ,可以通过 https://console.cloud.google.com/apis/dashboard 得到。

填写表格后,大概半天内即可收到邮件。邮件内附一个指向 Confidential material 的链接,具体内容在此不表。

然后,进入到 https://console.cloud.google.com/apis/library/publicca.googleapis.com ,单击“启用”,等他圈圈转完。

然后,单击右上角的“激活 Cloud Shell”,打开 Google Cloud Shell 。

键入 gcloud beta publicca external-account-keys create 获取相关凭据。

至此,会返回如下内容:

Created an external account key
[b64MacKey: sWxMMqW5DAa4Cxkm7EXKr6l1HpzGi2B2Kw7qxRHyAOII1LsnsVpWkKuSKcPOhmKZ
keyId: 1dde669efbd34e10b71297227b18ac28]

申请证书

首先我们在服务器上安装 acme.sh 。非常简单,一行命令即可。

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

会安装在 ~/.acme.sh/ 目录下,以后生成的证书也会在这里面,按照域名为文件夹放置。安装过程不会污染已有的系统任何功能和文件 , 所有的修改都限制在安装目录中: ~/.acme.sh/ 它同时会为你创建一个 CronJob ,每天 00:00 自动检测所有的证书,如果快过期了,需要更新,则会自动更新证书。

理论上会自动添加一个 acme.sh 全局应用别名,但有时候会 command not found ,需要手动执行以下命令:source ~/.bashrcsource ~/.bash_profile 后再继续。

接着,设置阿里云或其他DNS服务商的密钥,这部分可以参考官网,这里就不详细说明了。

这边以阿里云的DNS为例:

export Ali_Key="aaaaaaaaaaaaaaaaaaaa"
export Ali_Secret="aaaaaaaaaaaaaaaaaaaa"

接着,在 acme.ch 上注册账户:

acme.sh --register-account --email  ## --server google  --eab-kid ## --eab-hmac-key ##

你需要更改 “##”的值,并用英文双引号包裹。以下是一个例子:

acme.sh --register-account --email  "example@gmail.com" --server google  --eab-kid "1dde669efbd34e10b71297227b18ac28" --eab-hmac-key "sWxMMqW5DAa4Cxkm7EXKr6l1HpzGi2B2Kw7qxRHyAOII1LsnsVpWkKuSKcPOhmKZ"

虽然我们已经在上面命令设置了 CA 为 Google ,但是为了保险起见,我们再手动设置一遍:

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

至此,就可以使用 acme.sh + “DNS 模式” 申请证书了。命令如下:

acme.sh –issue –dns dns_ali -d www.example.com [-d example.com …]

example.com 为自己的域名。如果想要通配符可将 www.example.com 改为 *.example.com (PS:使用通配符后证书不支持一级域名 example.com 域名,需单独生成证书)。

申请下来的SSL证书有效期为3个月,虽然脚本有自动验证和更新操作,但有可能需要自己手动更新,此时运行命令:

acme.sh --cron -f -d *.example.com
# 或者
acme.sh --renew --force -d *.examplae.com

安装证书

前面证书生成以后,接下来需要把证书安装(复制)到真正需要用它的地方。

注意,默认生成的证书都放在安装目录下:  ~/.acme.sh/ ,请不要直接使用此目录下的文件,例如:不要直接让 Nginx/Apache 的配置文件使用这下面的文件。这里面的文件都是内部使用,而且目录结构可能会变化。

正确的使用方法是使用 --install-cert 命令,并指定目标位置,然后证书文件会被安装(复制)到相应的位置。例如:

# Apache example:

acme.sh --install-cert -d example.com \
--cert-file      /path/to/certfile/in/apache/cert.pem  \
--key-file       /path/to/keyfile/in/apache/key.pem  \
--fullchain-file /path/to/fullchain/certfile/apache/fullchain.pem \
--reloadcmd     "service apache2 force-reload"
# Nginx example:

acme.sh --install-cert -d example.com \
--key-file       /path/to/keyfile/in/nginx/key.pem  \
--fullchain-file /path/to/fullchain/nginx/cert.pem \
--reloadcmd     "service nginx force-reload"

这里用的是 service nginx force-reload ,不是 service nginx reload ,据测试,reload 并不会重新加载证书,所以用的 force-reload

Nginx 的配置 ssl_certificate 使用 /etc/nginx/ssl/fullchain.cer ,而非 /etc/nginx/ssl/<domain>.cer 。如不这样操作,会导致证书链不全的问题。

--install-cert 命令可以携带很多参数,来指定目标文件。并且可以指定 reloadcmd ,当证书更新以后,reloadcmd 会被自动调用,让服务器生效。

值得注意的是,这里指定的所有参数都会被自动记录下来,并在将来证书自动更新以后,被再次自动调用。

启用 acme.sh 的自动更新

目前由于acme协议和相关 CA 们都在频繁的更新, 因此 acme.sh 也需要经常更新保持同步。执行下面的命令,acme.sh 就会自动更新:

acme.sh  --upgrade  --auto-upgrade

关于 Nginx 证书的配置

文件解释

文件名内容
cert.pem服务端证书
chain.pem浏览器需要的所有证书但不包括服务端证书,比如根证书和中间证书
fullchain.pem包括了 cert.pem 和 chain.pem 的内容
privkey.pem证书的私钥

配置文件

你需要再加上一个 server 条目用于 HTTPS 服务。改完之后的结果是这个样子:

http {
    server {
        listen 80; 
        listen [::]:80;
        server_name example.com www.example.com;
        location / {
            root /var/www/html;
        }
        ...
    }
    server {
        listen 443 ssl;
        server_name example.com www.example.com;
        ssl_certificate /etc/letsencrypt/live/example.com/cert.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
        location / {
            root /var/www/html;
        }
        ...
    }
    ...
}

现在,你的服务器同时接受 HTTP 和 HTTPS 请求。如果你希望只受理 HTTPS 请求,可以在 nginx.conf 中添加一个 301 跳转规则,告知浏览器将 HTTP 变成 HTTPS。

http {
    server {
        listen 80; 
        listen [::]:80;
        server_name example.com www.example.com;
        return 301 https://$server_name$request_uri;
    }
    server {
        listen 443 ssl;
        server_name example.com www.example.com;
        ssl_certificate /etc/letsencrypt/live/example.com/cert.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
        location / {
            root /var/www/html;
        }
        ...
    }
    ...
}

上一篇
下一篇