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

使用rumqttc+rustls时遭遇CertNotValidForName证书错误求助

解决rumqttc搭配rustls时的CertNotValidForName证书验证错误

错误原因

CertNotValidForName错误的核心原因是rustls验证服务器证书时,发现证书中声明的域名与你实际连接的test.test.com不匹配。rustls会优先检查证书的Subject Alternative Name(SAN)扩展字段,其次是Common Name(CN)字段,必须确保其中包含目标连接地址。

解决方案

1. 检查服务器证书的域名配置

用openssl命令查看服务器证书的域名信息:

# 查看SAN字段
openssl x509 -in server.crt -text -noout | grep -A 3 "Subject Alternative Name"
# 查看CN字段
openssl x509 -in server.crt -text -noout | grep "Subject:"
  • 如果输出中没有test.test.com,说明证书本身的域名配置错误,需要重新生成包含该域名的证书(生成时可通过-subj "/CN=test.test.com"指定CN,或添加SAN扩展声明域名)。

2. 确认连接地址的正确性

检查代码中MqttOptions::new的第二个参数是否与证书中的域名完全一致:

let mut mqttoptions = MqttOptions::new("test", "test.test.com", 1000);

注意避免拼写错误、大小写差异(域名本身不区分大小写,但需与证书中声明的一致),或使用了错误的子域名/顶级域名。

3. 测试环境临时跳过域名验证(生产环境禁止)

如果是本地测试场景,可通过自定义rustls配置关闭域名验证,但生产环境绝对禁止使用,会引入中间人攻击风险:

#[cfg(feature = "use-rustls")]
#[tokio::main]
pub async fn test_mqtt() -> Result<(), Box<dyn Error>> {
    use rumqttc::{self, AsyncClient, MqttOptions, TlsConfiguration, Transport};
    use rustls::{ClientConfig, RootCertStore, ServerName, Certificate, PrivateKey, client::ServerCertVerifier};
    use rustls_pemfile::{certs, pkcs8_private_keys};
    use std::io::Cursor;
    use std::sync::Arc;
    use std::time::Duration;

    let mut mqttoptions = MqttOptions::new("test", "test.test.com", 1000);
    mqttoptions.set_credentials("test", "test");
    mqttoptions.set_keep_alive(Duration::from_secs(5));

    // 加载CA证书到信任链
    let ca = include_bytes!("../certs/ca.crt");
    let mut root_store = RootCertStore::empty();
    let ca_certs = certs(&mut Cursor::new(ca))?;
    for cert in ca_certs {
        root_store.add(&Certificate(cert))?;
    }

    // 加载客户端证书与密钥
    let client_cert = include_bytes!("../certs/client.crt");
    let client_key = include_bytes!("../certs/client.key");
    let client_certs = certs(&mut Cursor::new(client_cert))?
        .into_iter()
        .map(Certificate)
        .collect();
    let mut keys = pkcs8_private_keys(&mut Cursor::new(client_key))?;
    let client_key = PrivateKey(keys.remove(0));

    // 构建自定义rustls配置,关闭域名验证
    let mut config = ClientConfig::builder()
        .with_safe_defaults()
        .with_root_certificates(root_store)
        .with_client_auth_cert(client_certs, client_key)?;
    
    // 替换验证器,跳过域名检查
    config.dangerous().set_certificate_verifier(Arc::new(DummyVerifier));

    let transport = Transport::Tls(TlsConfiguration::Rustls(config));
    mqttoptions.set_transport(transport);

    let (client, mut eventloop) = AsyncClient::new(mqttoptions, 10);

    client.subscribe("test/test/test", rumqttc::QoS::AtMostOnce).await.unwrap();
    client.subscribe("test/test/test/logs", rumqttc::QoS::AtMostOnce).await.unwrap();

    // 用tokio异步任务替代std线程,避免异步方法调用阻塞问题
    tokio::spawn(async move {
        client.publish("test/test/test", rumqttc::QoS::AtLeastOnce, false, "test").await.unwrap();
        client.publish("test/test/test/logs", rumqttc::QoS::AtLeastOnce, false, "test").await.unwrap();
        tokio::time::sleep(Duration::from_millis(100)).await;
    });

    loop {
        match eventloop.poll().await {
            Ok(v) => println!("Event = {:?}", v),
            Err(e) => {
                println!("Error = {:?}", e);
                break;
            }
        }
    }

    Ok(())
}

// 自定义验证器,跳过所有证书域名检查
struct DummyVerifier;
impl ServerCertVerifier for DummyVerifier {
    fn verify_server_cert(
        &self,
        _end_entity: &Certificate,
        _intermediates: &[Certificate],
        _server_name: &ServerName,
        _scts: &mut dyn Iterator<Item = &[u8]>,
        _ocsp_response: &[u8],
        _now: std::time::SystemTime,
    ) -> Result<rustls::client::ServerCertVerified, rustls::Error> {
        Ok(rustls::client::ServerCertVerified::assertion())
    }
}

4. 排查证书有效期与信任链问题

如果域名匹配仍报错,检查:

  • 证书是否过期:
    openssl x509 -in server.crt -text -noout | grep -A 2 "Validity"
    
  • 加载的CA证书是否是签发服务器证书的根CA或中间CA,确保信任链完整。

内容的提问来源于stack exchange,提问作者GranBoh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 07:15:44