如何强制仅使用指定证书集验证TLS连接(忽略系统内置信任证书)
这确实是curl的一个容易踩的小坑——默认情况下,哪怕你指定了--cacert或--capath,它还是会偷偷同时用上系统内置的信任根证书,所以才会出现用Amazon的根证书访问google.com还能成功的怪事。下面给你几个简单可行的方案,不一定非要死磕curl:
方案一:用新版curl的专用参数(推荐)
如果你用的是curl 7.77.0及以上版本,官方专门加了--no-system-certificates参数,能直接让curl完全忽略系统内置证书,只信任你指定的证书文件:
curl --no-system-certificates --cacert AmazonRootCA4.pem https://google.com
执行这个命令后,访问google.com就会失败(因为Google的证书不是AmazonRootCA4签发的),完全符合你的测试预期。
方案二:旧版curl的替代技巧
要是你的curl版本比较老,没有--no-system-certificates这个选项,也有办法绕过去:通过指定一个空的capath或者不存在的目录,让curl放弃加载系统证书,只使用你指定的cacert:
# 用空路径作为capath curl --cacert AmazonRootCA4.pem --capath "" https://google.com # 或者指定一个不存在的目录 curl --cacert AmazonRootCA4.pem --capath "/this-path-does-not-exist" https://google.com
原理是curl会优先尝试使用capath配置的证书目录,当这个目录无效时,就只会加载你通过--cacert指定的证书,不会再去碰系统内置的信任根。
方案三:改用openssl s_client(无需依赖curl)
如果不想用curl,openssl的s_client工具其实更适合做这种“纯指定证书验证”的测试——它默认就不会加载系统的信任根证书,完全靠你手动指定的CA文件来验证:
openssl s_client -connect google.com:443 -CAfile AmazonRootCA4.pem
执行后如果验证失败,会输出类似Verify return code: 20 (unable to get local issuer certificate)的错误,这就是你要的结果。要是想模拟完整的HTTP请求(像curl那样),可以追加一段HTTP请求头:
openssl s_client -connect google.com:443 -CAfile AmazonRootCA4.pem <<EOF GET / HTTP/1.1 Host: google.com Connection: close EOF
小提示
不管用哪种方法,都要先确认你的PEM证书文件是有效的——比如检查文件格式是否正确,有没有权限读取(避免因为文件问题导致的意外失败)。
备注:内容来源于stack exchange,提问作者Dan Taylor




