1. OpenClaw 报 TLS certificate validation failed 到底卡在哪
你在终端敲下openclaw去调外部 API,结果它没给你返回数据,而是甩出一行Error: TLS certificate validation failed,后面还跟着UNABLE_TO_VERIFY_LEAF_SIGNATURE或者SELF_SIGNED_CERT_IN_CHAIN。这个报错的意思是:OpenClaw 在发起 HTTPS 请求时,客户端和服务器握手阶段,服务器递过来的证书链没能通过客户端的信任校验,于是连接被主动掐断。它不是什么网络不通,也不是 Key 写错了,而是“我不信你这张证书”。
OpenClaw 这类工具底层大多跑在 Node.js 运行时上,而 Node.js 的证书信任逻辑有个很关键的特点:它默认使用自己内置的 CA 证书列表(Mozilla 维护的那套),而不是直接读操作系统的证书存储。这就导致一个很常见的现象——你的系统浏览器访问公司内网服务一切正常,因为系统信任了企业根证书;但 OpenClaw 一跑就挂,因为 Node.js 根本不认系统里装的那张自签名根证书。企业内网自签名、中间证书缺失、安全网关做 TLS 拦截替换证书、系统时间偏差过大、证书过期,这几类原因能覆盖绝大多数现场。
这篇面向的是正在用 OpenClaw 调外部 API、Git 或包下载,被 TLS 证书验证失败挡住的人。我会从证书链、代理与配置文件三个角度带你定位,给出可复制的config.toml/settings.json骨架,并用 TaoToken 统一 Key 通道做接入示例,最后用curl和openssl把证书链和请求连通性验证一遍。适合刚接手 OpenClaw 配置、或者在企业网络环境里第一次踩这个坑的同学。
2. 先把 TaoToken 统一 Key 通道准备好
在排查证书之前,建议先把请求出口统一到一个稳定的通道上,这样能排除掉“到底是证书问题还是 Key/端点问题”的干扰。TaoToken 提供统一 Key 通道,把模型对话、编码类请求收敛到同一个入口,配置一次就能在 OpenClaw 里复用。
你需要先拿到一个可用的 Key。打开控制台创建 API Key:
https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite创建完 Key 之后,API 的基础地址是:
https://taotoken.net/api注意这个 API 地址后面不加任何 UTM 参数,保持干净。Key 的管理页面在这里,后续要轮换或吊销都从这里进:
https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite如果你只是想先验证模型通道是否通,可以直接用模型对话页面测一条请求:
https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite长期跑编码任务或者 Agent 的,建议看下 Coding Plan,把额度规划好再接入 OpenClaw:
https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite接入文档在这里,配置字段和端点说明都以它为准:
https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite提示:先把 Key 通道跑通,再去处理 TLS 证书。否则证书修好了、请求还是 401,你会误以为是证书没修对,白白多绕一圈。
3. 可复制的 config.toml / settings.json 骨架
OpenClaw 的配置一般落在项目目录下的.openclaw/里,常见是config.toml或settings.json。下面给一份能直接抄的骨架,把 TLS 相关字段和 TaoToken 通道都放进去。
先看config.toml版本:
# .openclaw/config.toml [api] provider = "taotoken" base_url = "https://taotoken.net/api" api_key = "sk-你的TaoTokenKey" timeout = 60 [tls] # 指向你的 CA bundle,多个根证书合并成一个 pem 文件 ca_bundle_path = "/home/you/.openclaw/ca-bundle.pem" # 保持 true,不要为了省事关掉验证 reject_unauthorized = true # 尝试读取系统证书存储(部分版本支持) use_system_certs = true [git] ssl_ca_info = "/home/you/.openclaw/ca-bundle.pem" ssl_verify = true再看settings.json版本,字段含义一致,只是格式不同:
{ "api": { "provider": "taotoken", "base_url": "https://taotoken.net/api", "api_key": "sk-你的TaoTokenKey", "timeout": 60 }, "tls": { "caBundlePath": "/home/you/.openclaw/ca-bundle.pem", "rejectUnauthorized": true, "useSystemCerts": true }, "git": { "sslCAInfo": "/home/you/.openclaw/ca-bundle.pem", "sslVerify": true } }配置里最核心的是ca_bundle_path/caBundlePath,它指向一个 PEM 文件,里面可以塞多张根证书。企业内网根证书、安全网关证书、公共 CA 都可以合并进去。reject_unauthorized保持true,这是安全底线,别为了图快改成false。
如果你不想改配置文件,也可以用环境变量兜底,Node.js 认这个变量:
export NODE_EXTRA_CA_CERTS="$HOME/.openclaw/ca-bundle.pem"把它写进~/.zshrc或~/.bashrc就能持久生效:
echo 'export NODE_EXTRA_CA_CERTS="$HOME/.openclaw/ca-bundle.pem"' >> ~/.zshrc source ~/.zshrc注意:
NODE_EXTRA_CA_CERTS是“追加”信任,不是“替换”。它会把指定文件里的证书加到 Node.js 内置列表之上,所以你可以放心把企业证书放进去,不会影响对公共 CA 的信任。
4. 用 curl 和 openssl 验证证书链与请求连通性
配置改完别急着跑 OpenClaw,先用curl和openssl把证书链看清楚,这样能快速判断问题出在哪一环。
第一步,看服务器返回的完整证书链:
echo | openssl s_client -connect api.taotoken.net:443 -showcerts 2>/dev/null | \ grep -E "subject=|issuer=|depth="输出里depth=0是服务器证书,depth=1是中间证书,depth=2往上到根。如果只看到depth=0就没了,说明服务器没把中间证书一起发过来,这就是典型的“证书链不完整”,客户端会报UNABLE_TO_GET_ISSUER_CERT。
第二步,把服务器返回的证书全部导出,逐个看有效期和签发者:
echo | openssl s_client -connect api.taotoken.net:443 -showcerts 2>/dev/null | \ awk '/-----BEGIN CERTIFICATE-----/{i++; out="/tmp/cert_"i".pem"} {print > out}' for cert in /tmp/cert_*.pem; do echo "=== $cert ===" openssl x509 -in "$cert" -subject -issuer -dates -noout done重点看notBefore和notAfter。如果当前时间不在这个区间里,要么证书过期,要么你系统时间跑偏了。顺手查一下系统时间:
date timedatectl status时间偏差超过几分钟,证书校验就会失败,这种坑很隐蔽。
第三步,用你合并好的 CA bundle 去验证连接:
echo | openssl s_client -connect api.taotoken.net:443 \ -CAfile "$HOME/.openclaw/ca-bundle.pem" 2>/dev/null | \ grep "Verify return code"期望输出是:
Verify return code: 0 (ok)只要看到0 (ok),说明证书链在你这份 bundle 下是可信的。如果还是非 0,把返回码记下来,对照下一节的排查表。
第四步,用curl验证实际请求能不能通,带上你的 Key:
curl -v https://taotoken.net/api/v1/models \ -H "Authorization: Bearer sk-你的TaoTokenKey" \ --cacert "$HOME/.openclaw/ca-bundle.pem"-v会打印握手细节,你能看到用的是哪张证书、TLS 版本是多少。如果这一步返回 200 和模型列表,说明证书和 Key 通道都没问题,可以回去跑 OpenClaw 了。
5. 本篇常见错排查
下面这些是我在实际环境里反复见到的报错,按报错信息对号入座即可。
UNABLE_TO_VERIFY_LEAF_SIGNATURE:最常见,服务器证书的签发者不在你的信任列表里。多半是企业自签名证书,或者中间证书没带上。解决方式是拿到那张根证书或中间证书,合并进ca-bundle.pem,再设NODE_EXTRA_CA_CERTS。
SELF_SIGNED_CERT_IN_CHAIN:证书链里出现了自签名证书。企业内网服务很常见。把企业根证书加进 bundle 即可,别去关验证。
CERT_HAS_EXPIRED:证书过期。用上面的openssl x509 -dates确认,然后让服务方换证书,或者更新你本地的 CA 包。
UNABLE_TO_GET_ISSUER_CERT:证书链不完整,缺中间证书。用-showcerts把服务器返回的证书全导出来,把中间证书补进 bundle。
Hostname/IP does not match certificate's altnames:证书上的域名和你请求的域名对不上。检查你配置里的base_url是不是写成了 IP,或者服务方证书没覆盖这个域名。
系统时间错误:date一看差了好几天。Linux 上sudo timedatectl set-ntp true,macOS 上sudo sntp -sS time.apple.com,同步完再试。
Docker 容器里失败:容器没挂载宿主机的 CA,也没装企业证书。运行时挂进去:
docker run -v /host/certs:/certs \ -e NODE_EXTRA_CA_CERTS=/certs/ca-bundle.pem \ your-openclaw-imageGit 操作单独报错:Git 用自己的证书配置,不读 Node.js 的。单独设一下:
git config --global http.sslCAInfo "$HOME/.openclaw/ca-bundle.pem" git config --global http.sslVerify true合并多张证书时,直接cat追加就行,PEM 格式支持一个文件里放多张:
cat company-root-ca.pem >> ~/.openclaw/ca-bundle.pem cat gateway-ca.pem >> ~/.openclaw/ca-bundle.pem注意:不要用
NODE_TLS_REJECT_UNAUTHORIZED=0或--insecure去“解决”生产环境的问题。它只是把校验关掉,等于把 HTTPS 的安全意义抹掉了,只适合本地临时调试,且必须确保不会带到线上。
6. 把通道固定下来,后续少踩坑
证书这类问题,修一次就该把它固化进配置,而不是每次报错再手动 export。我的做法是把ca-bundle.pem放在~/.openclaw/下,config.toml里写死ca_bundle_path,同时在 shell 启动文件里设好NODE_EXTRA_CA_CERTS,双保险。这样无论是 OpenClaw 直接跑,还是它内部调 Git、调 npm,都能吃到同一份信任链。
TaoToken 这边,Key 和端点也建议统一写进配置,别散落在各个脚本里。需要换 Key 或看用量就去控制台,接入细节以文档为准:
https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite跑编码任务多的,把 Coding Plan 配好,省得中途额度断了又回头怀疑是证书问题:
https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite最后留一个我常用的自检顺序:先date看时间,再openssl s_client -showcerts看链,再openssl s_client -CAfile看验证码,最后curl -v看请求。四步走完,TLS certificate validation failed 基本就定位到具体那一环了。