☰
OpenSSL报IP address mismatch:error 64与IP类型SAN排查
2026/10/14 23:33:06 网站建设 项目流程

证书明明写着192.0.2.10,用IP访问却提示不匹配?先别加信任根,也别把验证关掉。数字相同,不代表身份类型相同。本文定位OpenSSL的IP address mismatch:对照DNS类型SAN与IP类型SAN,复现error 64,再用失败分支检查修复是否真正生效。

一、先确认你验证的是IP,不是域名

域名服务的节点定点测试,与真正的IP身份验证是两件事。前者仍验证域名,后者验证IP地址。本文只讨论后者,不把改Host头或指定连接地址当成证书修复。192.0.2.10是文档示例地址,以下实验完全离线,不连接该地址。

OpenSSL的-verify_ip检查叶证书SAN里的IP地址;X509_check_ip文档明确:放在DNS名称或Common Name中的IP文本会被忽略。因此CN写对、甚至SAN里出现同一串数字,也可能失败。要看字段类型,不是肉眼找字符串。

二、在临时目录准备同一份请求

下面四段按顺序在同一个Bash子进程运行;不要逐段换终端。本轮实测OpenSSL 1.1.1k FIPS,命令使用1.1.1支持的参数。保留默认信任库和系统时钟不动,临时CA只通过CAfile授权给本次命令。未加密私钥、一天有效期和固定序列号仅供实验,退出该Shell自动清理。

umask 077 work=$(mktemp -d) || exit 1 cd "$work" || exit 1 trap 'cd /; rm -rf -- "$work"' EXIT printf '[req]\ndistinguished_name=dn\n[dn]\n' > openssl.cnf export OPENSSL_CONF="$PWD/openssl.cnf" openssl version openssl req -new -x509 -newkey rsa:2048 -nodes -days 1 \ -subj /CN=LabRoot -keyout root.key -out root.pem \ -addext basicConstraints=critical,CA:TRUE \ -addext keyUsage=critical,keyCertSign,cRLSign openssl req -new -newkey rsa:2048 -nodes \ -subj /CN=192.0.2.10 -keyout leaf.key -out leaf.csr

三、只改变SAN的类型,签两张证书

同一CSR、同一叶子密钥、同一CA,把其他条件尽量固定。DNS.pem写DNS:192.0.2.10,IP.pem写IP:192.0.2.10;配置由签发端显式提供,不依赖CSR扩展自动复制。

n=1 for kind in DNS IP; do printf '%s\n' 'basicConstraints=critical,CA:FALSE' \ 'keyUsage=critical,digitalSignature,keyEncipherment' \ 'extendedKeyUsage=serverAuth' \ "subjectAltName=$kind:192.0.2.10" > leaf.ext openssl x509 -req -in leaf.csr -CA root.pem -CAkey root.key \ -set_serial "$n" -days 1 -sha256 -extfile leaf.ext -out "$kind.pem" n=$((n+1)) done openssl x509 -in DNS.pem -noout -ext subjectAltName openssl x509 -in IP.pem -noout -ext subjectAltName

输出中一张是DNS:192.0.2.10,另一张是IP Address:192.0.2.10。签发成功只是文件生成,不代表身份适合应用。两张证书的CN都一样,正好排除“把CN再改一遍”的干扰。

四、复现error 64,再看一个容易误判的对照

for cert in DNS.pem IP.pem; do openssl verify -no-CApath -CAfile root.pem \ -purpose sslserver -verify_ip 192.0.2.10 "$cert" printf 'exit=%s\n' "$?" done openssl verify -no-CApath -CAfile root.pem -purpose sslserver DNS.pem

本轮DNS.pem报error 64 at 0 depth lookup: IP address mismatch,进程退出2;IP.pem返回OK、退出0。64是证书验证错误号,不是Shell退出码;depth 0指被检查的叶证书。

最后一条去掉IP身份条件,两张材料中的DNS.pem也能通过链和服务端用途检查。这恰恰说明:信任路径没问题,不等于IP身份正确。排查脚本漏掉-verify_ip,就像验了门禁卡,却没看持卡人。

五、把现象与修复动作分开

现象先检查处理方向
数字相同却error 64SAN是DNS还是IP经授权签发正确IP SAN
只改CN仍失败最终叶证书的SAN不要依赖CN兜底
另一个IP失败实际请求的身份核对批准地址范围
不加verify_ip就OK测试条件是否缩水恢复身份条件再验

本轮还测了错误IP、只有CN的证书和缺失文件,均不能放行。IPv6由IP类型SAN承载,等价文本写法应按地址匹配,不必强求显示字符串一致;本轮用2001:db8::10及其展开写法做了离线正对照,另一个地址为负对照。

六、脚本必须保留失败,不只搜索OK

下面先把完整输出写入日志,成功条件直接绑定verify进程。错误地址、错误类型、缺文件或日志无法创建都不能走成功分支;不要在verify后插入其他命令再读取退出码,也别用管道最后一段的成功覆盖前段失败。

check_ip() { openssl verify -no-CApath -CAfile root.pem \ -purpose sslserver -verify_ip "$1" "$2" } if check_ip 192.0.2.10 IP.pem >check.log 2>&1; then printf 'IP identity and chain passed\n' else rc=$? cat check.log >&2 exit "$rc" fi

七、修复后仍要回到真实HTTPS

正式修复是核对业务真正需要的IP身份、经CA授权签发并部署新证书,再读取服务实际发送的叶证书。不能把DNS数字字段改个显示标签:SAN属于签名保护内容,修改后必须重新签发。

本文离线通过只证明给定材料、时间、信任锚、用途和IP身份下验证通过;没有测试浏览器、负载均衡或生产握手。上线还要核对实际终点、发链、客户端信任配置和HTTP业务结果。证书文件正确,不代表流量已经用上它。

八、交付前的检查清单与资料

  • 确认访问身份到底是IP还是域名,测试条件保持一致。
  • 读取最终证书而非只看CSR;检查IP SAN、有效期与用途。
  • 正确IP通过,错误IP和DNS数字类型负例失败。
  • 保留退出码和完整错误;检查日志创建失败也会阻断。
  • 离线验证与真实服务验收分别记录,不关闭验证换取绿色结果。

参考资料与实现:

  • OpenSSL verify
  • OpenSSL X509v3配置
  • OpenSSL身份检查API
  • CertbotX

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询