CloudFlare在2020/10/1新推出了一个名为API Shield的功能,配置详情与使用介绍见这里这里。此处说的就是客户端证书校验的功能。

大致过程为【生成证书=>选择开启校验的host=>建立防火墙规则=>客户端安装证书】。在上面提到的两篇文章也有具体使用介绍。不过还是记录下今日测试的使用过程。

生成证书

【此处流水账摘自官方文档https://developers.cloudflare.com/ssl/client-certificates/generate-client-certificate/】

  1. Log in to the Cloudflare dashboard and click the SSL app.

    The SSL Overview displays.(登录Cloud Flare控制面板,来到SSL/TLS选项)

    SSL app Overview tab

  2. Click the Client Certificates tab.(选择客户端证书选项)

  3. In the the Client Certificates card, click Create Certificate.(选择客户端证书选项里,选择创建证书)

    Client Certificates card

    然后进入了证书生成页面。

    Create client certificates card

  4. To choose between RSA and ECC encryption, use the Private key type drop-down list.(可以选择证书的加密算法,目前支持RSA2048位与ECC算法,此处不需要做选择)

    Private key type drop down

  5. To configure the validity period for your certificate, use the Certificate Validity drop-down list. The default value is 10 years. Available values include 1, 2, 3, 5, and 15 years.(选择证书有效期年限,默认10年)

  6. To create the certificate, click Create. The Client Certificate and Key Generation page displays.(点击创建按钮,此时会为我们显示创建的公钥与私钥)

    Client certification and key generation

    注意:此处生成的私钥(private key)与证书(Cert)一定要保存到文件!该处不会再次显示!推荐将证书保存为domain.pem、私钥保存为domain.key

选择开启校验的host

请看官方文档https://developers.cloudflare.com/ssl/client-certificates/enable-mtls/,介于此处没什么需要注意的地方。不再赘述。

建立防火墙规则

Client Certificates card

可以在客户端页面直接点击 创建API Shield规则。然后就会发现来到了防火墙规则页面。

规则名称随便写。主机名可以选择我们刚才在选择开启校验的host步骤里面创建的。进行部署就可以了。也可以看到防火墙的规则是:

(http.host in {"test.chuibi.cn"} and not cf.tls_client_auth.cert_verified)

客户端安装证书

此时我们打开 https://test.chuibi.cn/ 就会发现 Access denied。因为此时防火墙规则已经生效,需要客户端才可以。例如Chrome支持的个人信息交换证书类型是 PKCS#12。所以此处需要拿到domain.key和domain.pem进行组合。

  1. 可以通过openssl进行转换:

    过程中会让输入export password。根据个人喜好设定。如果设定的话,则在导入客户端时也需要输入该export password

openssl pkcs12 -export -out test.chuibi.cn.p12 -in test.chuibi.cn.pem -inkey test.chuibi.cn.key
  1. 通过在线工具转换

    https://myssl.com/cert_convert.html

    原格式: PEM 目标格式: PKCS12

完成之后就可以通过Chrome进行导入了。然后再次访问 https://test.chuibi.cn/ 时会提示选择证书。选择刚导入的证书后即可正常访问。

此处有扫盲:

  • .DER .CER,文件是二进制格式,只保存证书,不保存私钥。
  • .PEM,一般是文本格式,可保存证书,可保存私钥。
  • .CRT,可以是二进制格式,可以是文本格式,与 .DER 格式相同,不保存私钥。
  • .PFX .P12,二进制格式,同时包含证书和私钥,一般有密码保护。
  • .JKS,二进制格式,同时包含证书和私钥,一般有密码保护。

其他

此功能名为API Shield。说明该功能主要为API设计,浏览器访问不属于考虑范畴,所以并未在创建时直接提供PKCS#12的类型。给出的默认案例是python:

import requests
import json
from datetime import datetime

def readSensor():

    # Takes a reading from a temperature sensor and store it to temp_measurement 

    dateTimeObj = datetime.now()
    timestampStr = dateTimeObj.strftime(%Y-%m-%dT%H:%M:%SZ)

    measurement = {'temperature':str(36.5),'time':timestampStr}
    return measurement

def main():

    print("Cloudflare API Shield [IoT device demonstration]")

    temperature = readSensor()
    payload = json.dumps(temperature)
    
    url = 'https://shield.upinatoms.com/temps'
    json_headers = {'Content-Type': 'application/json'}
    cert_file = ('/etc/ssl/certs/sensor.pem', '/etc/ssl/private/sensor-key.pem')
    
    r = requests.post(url, headers = json_headers, data = payload, cert = cert_file)
    
    print("Request body: ", r.request.body)
    print("Response status code: %d" % r.status_code)

ref:

https://blog.cloudflare.com/introducing-api-shield/

https://myssl.com/cert_convert.html

https://blog.freessl.cn/ssl-cert-format-introduce/

https://developers.cloudflare.com/ssl/client-certificates