用 testssl.sh 体检一台服务器的 TLS 配置:它查什么、怎么跑、结果怎么看
testssl.sh 能在不改动服务的前提下,把一台服务器的证书、协议版本、加密套件和常见漏洞扫一遍。本文说明它的检查边界、典型用法,以及如何解读那些容易误报的红色告警。
本文目录

线上排障时最常见的场景是:浏览器说"连接不安全",但你看 nginx 配置明明写着 ssl_protocols TLSv1.2 TLSv1.3,证书也没过期。问题往往藏在你没写进配置的地方——比如上游还有一个老旧的 F5,或者 CDN 回源那段的协议栈和你想的完全不一样。这时候与其一条条试 openssl s_client,不如让 testssl.sh 跑一遍,把整个 TLS 面摊开看。
它到底查什么
testssl.sh 是一个纯 bash 脚本(底层调 openssl),只做被动探测,不改任何东西。它的检查范围大致分几块:
- 证书链:有效期、签名算法、链是否完整、主机名匹配、是否被吊销(OCSP stapling 状态)。
- 协议版本:从 SSLv2 一路探到 TLS 1.3,标出服务器实际接受哪些。
- 加密套件:按强度分类列出服务器支持的套件,包括那些你以为早关掉了的 NULL 和 EXPORT 套件。
- 已知漏洞:Heartbleed、POODLE、BEAST、ROBOT、LOGJAM 这类有名字的老朋友,逐个测一遍。
- 杂项:HSTS 头、TLS session 复用、压缩(CRIME 的前提)、证书透明度等。
有个边界要说清楚:它测的是"服务器愿意协商什么",不是"客户端实际走了什么"。两者常常不一致,尤其是有中间设备做 TLS offload 的时候。
怎么跑
最省事的方式是 Docker,不用管本地 openssl 版本:
docker run --rm -ti drwetter/testssl.sh example.com:443或者直接克隆仓库跑 ./testssl.sh example.com。默认输出很长,常用几个收窄范围的参数:

--fast:只查协议、套件和证书,跳过漏洞扫描,日常巡检够用。-U:只跑漏洞部分。--severity LOW:过滤掉信息性输出,只看 LOW 及以上的问题。--jsonfile out.json:结果落盘,方便接进巡检流水线或对比前后变化。
扫 443 以外的端口也行,比如 testssl.sh -t smtp mail.example.com:25 会按 STARTTLS 的方式去测。
结果怎么看
输出按颜色分级,但真正需要动手处理的通常只有三类:
- 证书问题:过期、链不完整、主机名不匹配。这类是硬故障,用户端直接报错,优先级最高。
- 还在接受 TLS 1.0/1.1 或弱套件。要不要关取决于你的客户端面——对公网 API 可以果断关,对内部老系统就得先摸清谁在连。扫描结果只告诉你事实,取舍是你的事。
- 红色但标注 mitigated 的漏洞。比如 BEAST 在现代 TLS 栈上大多已通过协议层面缓解,扫出来红不代表真的可利用。对照它给出的说明再判断,别看到红字就慌。
反过来,有些"全绿"也别太放心:HSTS 没配、OCSP stapling 没开,这些不一定会标成问题,但在很多合规清单里是必查项,需要自己盯一眼输出里的对应小节。
在 CertbotX 中实践
扫描暴露出的最常见根因之一是证书运维靠人记:忘了续期、换了证书没同步到所有入口。CertbotX 在这块能做实的事包括:用 DNS-01(支持 CNAME 委托,适合域名 DNS 不在手上的场景)自动签发证书,到期前自动重新签发,并把新证书自动推送到 Agent、EdgeOne 或其他 CDN 入口,部署动作留有记录可审计。自动化兜底之后,testssl.sh 这类扫描更适合作为验证手段,而不是救火工具。