一次证书踩坑记:我以为证书到2027年才过期,结果它活不过一个周末
第一坑:我以为证书就是一张纸
去年年底,公司有个内网系统,让我负责把 HTTPS 配好。我从免费 CA 那里下载了一张证书,有效期写着 2027年3月11日。我长舒一口气:两年半不用管了。
我把证书传上服务器,Web 服务里配好路径,reload 一下,浏览器打开——绿锁,完美。
我心里想:证书不就是一张"到期才作废"的凭证嘛,跟身份证一样,在有效期内永远有效。
这是我这辈子最贵的认知。
第二坑:我以为"合并证书"只是复制粘贴
过了两个月,老板说手机上打不开这个系统,报"不安全"。我用自己的电脑、Chrome、Firefox 试了一遍,全正常。我回他:你手机有问题,清缓存。
老板没说话,只是把截图发到群里。截图上是 NET::ERR_CERT_AUTHORITY_INVALID。
我开始查。用 openssl s_client 一连,输出里只有我那张服务器证书,中间证书一张都没发过来。
恍然大悟:我从 CA 那里下载了三个文件——my.crt(我的证书)、intermediate.crt(中间证书)、root.crt(根证书)。我只把 my.crt 配进了 Web 服务。我以为浏览器自己会去找中间证书。
我以为证书是"一张纸",其实是"一串糖葫芦":我的证书挂在中间证书下面,中间证书挂在根证书下面。浏览器手里只有最顶上那颗"根",你如果不把下面几颗递过去,它根本够不着你的证书。
我把 my.crt 和 intermediate.crt 拼在一起,做成 fullchain.pem,重新 reload。老板的手机立刻好了。
那一刻我学到了:所谓"合并证书",就是补链。不是把两张纸粘一起,是把整条路铺到浏览器脚底下。
第三坑:我以为 CA 倒闭了跟我无关
这次之后,我变"聪明"了。我想:只要我把中间证书存在服务器上,随每次握手发出去,这条链就永远不断。CA 就算哪天注销了、中间证书作废了,反正我手上这张证书写着2027年,它管不着我。
我还得意地把这个想法讲给同事听:你看,证书有效期是写死在证书里的,签出去就固定了,不会变。
同事只问了一句:"浏览器验证的时候,会不会顺便看看中间证书本身是不是被注销了?"
我愣住了。
我想当然地以为:浏览器拿到中间证书,就只是用它去验证我的证书签名,不会去查这张中间证书本身有没有效。毕竟,每次联网去查,多慢啊,万一 CA 的服务器挂了怎么办?
我又去翻资料,这次把我吓出一身冷汗。
浏览器确实查中间证书本身。而且不光查签名、查有效期,还要查它是不是被注销了(吊销)。链上的每一环,都要单独过一遍全部校验,中间证书没有任何特权。
那它怎么查?难道每次访问都联网?
第四坑:原来"不联网"才是最可怕的地方
我本以为"每次联网查"会很慢、会失败,很脆弱。结果一查才发现:主流浏览器根本不做在线查询。
Chrome 用一份叫 CRLSet 的本地黑名单,Firefox 用 CRLite,都是后台静默推送到我电脑上的。我访问网站时,浏览器只在本地内存里比对序列号,一次联网都没有,零延迟。
这听起来很美,对吧?
但这也意味着:如果一张中间证书被注销了,但我的浏览器还没收到这份黑名单,我就完全不知道。
我前面那句"签出去就固定了",错得离谱。证书有效期只是"时间上限"。注销是提前终止信任的按钮。 而且这个按钮一按,是批量杀伤——那个中间证书下面签过的所有证书,全部报废。
更要命的是:注销信息不是实时的。 CA 把中间证书写进吊销列表,浏览器厂商爬取、打包、推送,到你电脑上,可能要几小时,可能要几天,Chrome 的黑名单甚至不覆盖所有吊销。
也就是说,中间证书被注销后,到浏览器真正"知道"这件事之间,有一段时间差。这段时间里,我的那张2027年的证书,还在大摇大摆地假装有效。
这不是假设,这是真实存在、业界公认的设计缺陷。正是因为吊销这套机制二十年都没真正可靠过,行业现在干脆走向另一个极端:短寿命证书,最多7天,不依赖吊销,让它自己快点过期。
第五坑:我以为我的电脑"很干净"
有一天,我照例用 openssl 查我们系统的证书链。突然发现,颁发者不是我们那个正规 CA,而是一个 内网代理自签 CA 的名字。
我证书明明是从正规 CA 下的,怎么变成了这个?
我这才想起来,公司为了做上网行为管理和安全审计,在内网部署了 HTTPS 解密代理。它的原理是:在公司每台电脑的信任库里,预先装了一张公司自己的根证书。 然后代理设备用这张根证书,对每个网站"现场签发"一张假证书。因为你的电脑信任了那张根证书,所以浏览器不会报错,绿锁照样亮。
我以为信任库里那些根证书是神圣不可侵犯的。其实任何有管理员权限的程序,都可以往里加一张自己的根证书,而且默认静默、无提示。
我顺手查了一下自己的信任库,还真发现了几张不认识的、伪装成正规 CA 的条目。后来确认是某次装软件时带进来的。
那一刻我后背发凉:如果有人往我信任库里加了一张自己的根证书,那前面我追问的整条信任链——根、中间、叶子——全由他一个人签。所有校验都会通过,但我所有的 HTTPS 流量,都在被他解密。
证书体系的一切安全,都建立在"我的信任库是干净的"这个前提上。这个前提,是可能不成立的。
最后的领悟
我把这次踩坑,浓缩成几句话,贴在工位上:
- 证书不是一张纸,是一条链。 你要把整条链(叶子 + 中间)都发给浏览器,缺一环就全断。
- 有效期只是上限。 签发者被注销、过期、信任库被污染,都会让你的证书在到期之前就失效。
- 吊销不靠联网查,靠本地黑名单。 它快、它省流量,但它不实时,有时间差,有漏网。
- 根证书是地基,但地基是可以被挖的。 任何有管理员权限的程序,都能往你信任库里塞一张"万能签发者"。
- 永远别信"2027年才过期"这几个字。 它只说明你的证书"最多能活到2027",不说明它"一定能活到2027"。
我那张写着2027年的证书,最后确实没活到2027。它在一次中间证书轮换时,因为服务器没及时配新的 fullchain,在部分客户端上报错,我花了半个通宵重配。
它没等到被注销,先被自己人的运维给坑了。