reqwest调用启用TLS的Docker容器REST API出现证书不被信任错误
排查步骤
- 验证证书有效性和匹配性
首先执行命令openssl x509 -in ./cert.pem -text -noout校验本地证书文件是否合法,确认证书未过期、和容器内配置的根证书完全一致。重点检查证书的**主题备用名称(SAN)**字段:如果请求URL用IP访问,SAN必须包含对应的IP记录(格式为IP:xxx.xxx.xxx.xxx);如果用域名访问,必须包含对应的DNS记录。仅在证书通用名(CN)字段填写地址是不生效的,reqwest的native-tls后端会强制校验SAN字段,这是最常见的报错原因。 - 校验ClientBuilder配置
确认传入的ClientBuilder没有提前配置danger_accept_invalid_certs(false)以外的冲突配置,也没有加载其他根证书覆盖了你添加的自签名证书。 - 确认证书加载路径正确
你代码中读取的./cert.pem是相对于程序运行时的工作目录,而非源码存放目录,可以打印std::fs::read("./cert.pem")的返回结果长度,确认没有读错文件、也没有把证书文件和私钥文件混淆。 - 排查TLS后端兼容性问题
你当前使用的native-tls依赖系统原生的TLS实现,不同操作系统(Windows/macOS/Linux)对自定义根证书的加载逻辑存在差异,经常出现自签名证书识别失败的问题。
解决方案
本地临时调试方案(禁止生产环境使用)
如果仅需要快速验证接口功能,可以直接关闭证书校验,修改客户端构建逻辑即可:
let client = builder .danger_accept_invalid_certs(true) .default_headers(headers) .build()?;
生产可用方案
- 重新生成符合规范的自签名证书,确保SAN字段包含访问用的IP/域名,参考生成命令:
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \ -keyout cert.key -out cert.pem \ -subj "/CN=你的服务地址" \ -addext "subjectAltName=DNS:你的域名,IP:你的服务IP"
用新生成的证书替换容器内的配置和本地的cert.pem文件后重启容器。
2. 替换TLS后端为纯Rust实现的rustls,兼容性更强,修改Cargo.toml中的reqwest依赖即可,业务代码无需改动:
reqwest = { version = "0.11.4", features = ["blocking", "json","rustls-tls-native-roots"] }
- 优化客户端初始化逻辑,不要每次调用接口都重新读取证书、新建Client实例,将初始化完成的Client存入你的结构体中复用,减少不必要的IO开销。
内容的提问来源于stack exchange,提问作者nagaraj
相关产品推荐
相关产品推荐

