参考

ssl.sh JSON API:证书检查、证书链、CT、CAA、HSTS 接口

作者: · 最后核实

ssl.sh 的 API 是 https://ssl.sh/api/v1/ 下的一组只读 JSON 接口。用 GET 请求、把域名放在查询参数里即可,日常使用不需要注册。

认证和额度

  • 匿名:每个 IP 每分钟 30 次检查(令牌桶)。结果缓存 5 分钟(失败结果 1 分钟),命中缓存不计次数。
  • API Key:请求头带 Authorization: Bearer <key>(或参数 ?key=<key>),额度按套餐。Key 无效返回 401 invalid_key。
  • 超出额度:返回 429 rate_limited,Retry-After 头给出需要等待的秒数。
  • 检查类接口加 fresh=1 跳过缓存(会计入次数)。

错误格式

所有错误都是同一个结构:

{"error": "blocked_address", "message": "10.0.0.1 resolves to 10.0.0.1: private or reserved range 10.0.0.0/8"}
状态码 error 取值
400 missing_host、invalid_host、invalid_port、port_not_allowed、invalid_starttls、private_key_rejected、parse_failed
401 invalid_key
403 blocked_address(内网、回环、链路本地、100.64.0.0/10 或其他保留地址)
404 not_found
413 too_large
429 rate_limited
502 dns_failed、connect_refused、connect_failed、timeout、tls_handshake_failed、protocol_mismatch、starttls_failed、ct_unavailable、fetch_failed

/api/v1/check 返回 502 时,响应体仍是完整的检查结果(含 error、error_detail、message),可以据此区分是 DNS 解析失败还是端口不通。message 目前是英文;中文说明在 findings[].message_zh 里。

GET /api/v1/check

检查一个主机。参数:

参数 默认值 说明
host 必填 域名、域名:端口 或网址。
port 443 允许:443、8443、4443、9443、10443、465、587、25、993、995、143、110、21、990、636、853、5222、5432、6443、2083、2087、8883。
starttls 自动 smtp、imap、pop3、ftp、xmpp、postgres。25、587、143、110、21、5222、5432 端口自动启用。
full 关 full=1 再逐个测试 TLS 版本、HSTS、CAA 和吊销状态。
fresh 关 fresh=1 跳过缓存。
curl -s 'https://ssl.sh/api/v1/check?host=example.com&full=1'

返回(节选):

{
  "host": "example.com",
  "port": 443,
  "ip": "203.0.113.10",
  "ok": true,
  "error": null,
  "tls_version": "TLSv1.3",
  "cipher": "TLS_AES_256_GCM_SHA384",
  "alpn": "h2",
  "protocols": {"TLSv1.0": false, "TLSv1.1": false, "TLSv1.2": true, "TLSv1.3": true},
  "chain": [
    {
      "subject_cn": "example.com",
      "sans": ["example.com", "www.example.com"],
      "issuer_cn": "R12",
      "issuer_org": "Let's Encrypt",
      "not_after": "2027-01-13T07:11:59Z",
      "days_left": 64,
      "key_type": "RSA 2048",
      "validation_level": "DV",
      "pem": "-----BEGIN CERTIFICATE-----\n…"
    }
  ],
  "chain_complete": true,
  "trusted": true,
  "hostname_match": true,
  "hsts": "max-age=31536000; includeSubDomains",
  "caa": ["0 issue \"letsencrypt.org\""],
  "revocation": "good",
  "findings": [
    {"level": "ok", "code": "valid", "message": "Certificate is valid and trusted, expires in 64 days.", "message_zh": "证书有效且受信任,64 天后过期。", "link": null}
  ],
  "grade": "A+",
  "days_left": 64,
  "fullchain_pem": "-----BEGIN CERTIFICATE-----\n…",
  "report_url": "https://ssl.sh/example.com"
}

字段说明:

  • chain 是服务器实际发送的顺序;aia_fetched 是服务器没发、由 ssl.sh 按 AIA 下载的中间证书,它不为空时 chain_complete 为 false。
  • findings[].code 供程序判断:expired、not_yet_valid、expires_soon、hostname_mismatch、self_signed、untrusted_root、incomplete_chain、revoked、weak_key、sha1、tls10_enabled、tls11_enabled、weak_cipher、legacy_only、no_tls13、no_hsts、hsts_short、caa_missing、client_auth_eku。link 是对应的解决办法页面(中文页面在前面加 /zh)。
  • grade 为 A+、A、B、C、F 或 T(不受信任);握手都没成功时为 null。
  • protocols、hsts、caa、revocation 只在 full=1 时有值;key_exchange_group 取不到时为 null。

GET /api/v1/chain

返回补齐后的证书链:{host, port, trusted, chain_complete, root, pem_fullchain, certs: [...]}。pem_fullchain 按验证路径排列(站点证书在前,中间证书在后,不含根证书);certs 每项字段同上,另有 source:server(服务器发送)或 aia(补齐下载)。

curl -s 'https://ssl.sh/api/v1/chain?host=example.com' | jq -r .pem_fullchain > fullchain.pem

GET /api/v1/ct

查询证书透明度日志,先查 crt.sh,失败时改查 Cert Spotter,结果缓存 6 小时。可以用来发现别人用你的域名申请的证书。

参数 默认值 说明
domain 必填 域名。
include_subdomains 1 0 只查这个域名本身。
include_expired 0 1 包含已过期的证书。

每条记录:{id, issuer, not_before, not_after, dns_names, serial, source},按 not_before 倒序。

GET /api/v1/caa

?domain=example.com 返回生效的 CAA 记录:按 RFC 8659 从该域名逐级往上找,第一个有记录的名字生效。返回 {domain, found_at, records, issue, issuewild, iodef, any_ca_allowed}。阿里云、腾讯云 DNSPod 的解析控制台都支持添加 CAA 记录。

GET /api/v1/hsts

?host=example.com 请求 https://example.com/,返回 {host, port, http_status, header, max_age, max_age_days, include_subdomains, preload_directive, preload_list}。preload_list 是 hstspreload.org 接口给出的预加载状态(preloaded、pending、unknown 等),该服务无响应时为 null。

GET /api/v1/mixed-content

?url=https://example.com/page(或 ?host=)下载页面(最多 2 MB,跟随跳转),列出用 http:// 加载的子资源:{url, final_url, status, page_is_https, count, active, passive, insecure_forms, items: [{tag, attr, url, type}]}。active(脚本、样式表、iframe)会被浏览器直接拦截,passive(图片、音视频)会让地址栏显示不安全。详见混合内容警告。

POST /api/v1/decode

在请求体里发送证书或 CSR,PEM 或 base64 DER 都可以(纯文本、JSON {"pem": "…"} 或表单字段 pem),最大 256 KB。只要内容里出现 PRIVATE KEY 就返回 400 private_key_rejected,不做任何处理。私钥不要发给任何在线工具。

curl -s https://ssl.sh/api/v1/decode --data-binary @cert.pem

证书返回 {"type": "certificate", "count": n, "certificates": [...]},字段同 chain;CSR 返回 {"type": "csr", "csr": {subject, subject_cn, sans, key_type, sig_alg, signature_valid}}。

常见问题

有没有官方 SDK?

不需要 SDK:所有接口都是普通的 GET 请求(解析证书是一个 POST),返回 JSON。curl、Python 的 requests、Node 的 fetch、Go 的 net/http 都能直接调。

国内服务器调用会不会很慢?

检查本身需要 ssl.sh 连接你的目标主机,耗时主要取决于目标服务器的响应速度,通常 1~3 秒。CT 查询依赖 crt.sh 等海外服务,第一次可能要十几秒,之后 6 小时内走缓存。

资料来源

  1. RFC 6962:证书透明度
  2. crt.sh
  3. Cert Spotter API v1
  4. HSTS 预加载列表
  5. RFC 8659:DNS CAA 记录