You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NGINX反向代理无法验证仅含CommonName的自签名TLS证书的解决方案咨询

NGINX反向代理无法验证仅含CommonName的自签名TLS证书的解决方案咨询

你遇到的这个问题确实是 legacy 证书带来的典型坑——现在主流的TLS工具(包括OpenSSL 1.1.0+、Caddy)都严格遵循现代标准,不再默认把证书的CommonName(CN)当作主机名验证的依据,再加上你的路由器证书标记了CA:FALSE,这就导致OpenSSL和NGINX都不认可它作为信任锚,进而出现验证失败。

我来给你梳理几个可行的解决方案,不需要修改路由器,也能实现安全的证书验证:

一、调整NGINX配置,适配这个legacy证书

1. 解决"无法验证第一证书"的问题

你看到的错误码21,本质是OpenSSL不把这个自签名证书当作可信的CA(因为证书里CA:FALSE)。我们可以在本地修改证书,把它标记为CA证书,这样OpenSSL就会信任它:

# 先导出证书的文本配置
openssl x509 -in cert.pem -text -noout > cert_config.txt
# 编辑cert_config.txt,找到X509v3 Basic Constraints那一行,把CA:FALSE改成CA:TRUE
# 然后重新生成修改后的证书
openssl x509 -in cert.pem -out cert_trusted.pem -extfile cert_config.txt

然后修改NGINX的配置,使用这个修改后的证书:

events {
}

error_log /dev/stdout debug;

http {
    upstream tplink_router {
        server tplinkwifi.net:443;
    }

    server {
        access_log /dev/stdout debug;
        listen 80;
        server_name router;

        location / {
            proxy_pass https://tplink_router;
            # 使用修改后的可信证书
            proxy_ssl_trusted_certificate /cert_trusted.pem;
            proxy_ssl_verify on;
            # 关闭SNI,让OpenSSL回退到CN验证(因为证书没有SAN)
            proxy_ssl_server_name off;
            # 指定要验证的主机名(对应证书的CN)
            proxy_ssl_name tplinkwifi.net;
            # 自签名证书验证深度设为1即可
            proxy_ssl_verify_depth 1;
        }
    }
}

2. 强制OpenSSL回退到CN验证(无需修改证书)

如果不想修改证书,也可以通过NGINX的proxy_ssl_conf_command参数,让OpenSSL启用对CN的回退验证:

location / {
    proxy_pass https://tplinkwifi.net;
    proxy_ssl_trusted_certificate /cert.pem;
    proxy_ssl_verify on;
    proxy_ssl_server_name off;
    proxy_ssl_name tplinkwifi.net;
    proxy_ssl_verify_depth 1;
    # 添加这条命令,强制OpenSSL使用CN进行主机名验证
    proxy_ssl_conf_command Options +StrictHostCheck;
}

注:这个参数需要NGINX编译时支持OpenSSL 1.1.0+,如果你的NGINX版本较旧可能不生效。

二、尝试其他反向代理工具

如果NGINX的调整还是不行,这些工具可能更兼容legacy证书:

  • HAProxy:在HAProxy的配置中,可以通过ssl-server-verify required加上ssl-fc-sni tplinkwifi.net,并且指定ca-file /cert.pem,HAProxy对CN回退的支持更灵活,旧版本也能兼容。
  • Python反向代理脚本:用Flask或aiohttp写一个简单的反向代理,使用requests库(默认会回退到CN验证),并且指定verify='/cert.pem',这种方式对legacy证书的兼容性非常好,适合临时或小型场景。

三、补充说明为什么curl能成功

你用curl --cacert cert.pem能成功,是因为curl的证书信任逻辑和OpenSSL命令行/NGINX有差异:curl会忽略证书的CA:FALSE标记,只要你指定了--cacert,就会无条件信任这个证书,同时curl在默认情况下(即使是新版本)会回退到CN进行主机名验证,这两个点刚好适配了你的路由器证书。

备注:内容来源于stack exchange,提问作者TimeMalt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 16:28:05