rust 超级客户端不接受自签名证书吗?

h6my8fg2  于 2023-05-29  发布在  其他
关注(0)|答案(2)|浏览(252)

我有一个使用hypertokio-rustls构建的Web服务器。在使用自签名证书时,我已确认https请求已被Chrome等Web浏览器成功处理。
但是,当我尝试为测试创建一个hyper客户端并尝试发出请求时,输出以下错误。

hyper::Error(Connect, Custom { kind: Other, error: Custom { kind: InvalidData, error: InvalidCertificateData("invalid peer certificate: UnknownIssuer") } })', tests/server.rs:80:42

甚至当我检查自我签名证书的curl请求时,我得到了200个响应。使用hyper-rustls的客户端不接受自签名证书吗?或者浏览器和测试客户端显示不同结果的原因是什么?
是否有一个单独的选项不检查客户端上的服务器证书(不安全)?
我使用hyper_rustls来发出https请求。

let url = ("https://localhost:5582").parse().unwrap();
let https = hyper_rustls::HttpsConnectorBuilder::new()
    .with_native_roots()
    .https_only()
    .enable_http1()
    .build();

let client: Client<_, hyper::Body> = Client::builder().build(https);

let response = client.get(url).await.unwrap();
w6mmgewl

w6mmgewl1#

所有环境都应该拒绝自签名证书 ,直到明确指示接受它。 例如,对于curl,您可以使用-k--insecure来告诉curl不要验证证书。同样,您的浏览器显示了一个可怕的“证书错误”页面,您绕过了该页面,指示浏览器接受证书。
如果一个环境默认不拒绝这样的证书,那么它很容易受到中间人攻击,这将是一个安全漏洞。
您可以在构建hyper_rustls连接器时通过添加.with_tls_config()调用来禁用证书验证。您需要访问ClientConfig的危险部分,并将certificate verifier设置为不执行任何检查。
或者,您可以将证书作为受信任的主机证书安装在系统的证书存储中,这样可能更简单也更安全。

xnifntxz

xnifntxz2#

要在answer by cdhowie上构建,这里有一个更完整的示例:

use std::{sync::Arc, fs::File, io::Read};

use anyhow::Error;
use hyper::client::HttpConnector;
use hyper_rustls::HttpsConnector;
use rustls::ClientConfig;

// customization for "reqwest" requests
pub fn get_reqwest_client_with_k8s_certs() -> Result<reqwest::Client, Error> {
    // if you just want to add custom certificates, use this
    /*let mut buf = Vec::new();
    File::open("/var/run/secrets/kubernetes.io/serviceaccount/ca.crt")?
        .read_to_end(&mut buf)?;
    let cert = reqwest::Certificate::from_pem(&buf)?;
    Ok(reqwest::ClientBuilder::new()
        .add_root_certificate(cert).build()?)*/

    Ok(reqwest::ClientBuilder::new()

        // if you want to completely disable cert-verification, use this
        .danger_accept_invalid_certs(true)

        .build()?)
}

// customization for "hyper" requests
pub fn get_hyper_client_with_k8s_certs() -> Result<hyper::Client<HttpsConnector<HttpConnector>>, Error> {
    let https = hyper_rustls::HttpsConnectorBuilder::new()
        .with_tls_config(get_rustls_config_dangerous()?)
        .https_only()
        .enable_http1()
        .build();

    let client: hyper::Client<_, hyper::Body> = hyper::Client::builder().build(https);
    Ok(client)
}

pub fn get_rustls_config_dangerous() -> Result<ClientConfig, Error> {
    let mut store = rustls::RootCertStore::empty();

    // if you just want to add custom certificates, use this
    /*let mut buf = Vec::new();
    File::open("/var/run/secrets/kubernetes.io/serviceaccount/ca.crt")?
        .read_to_end(&mut buf)?;
    //let cert = reqwest::Certificate::from_pem(&buf)?;
    store.add_parsable_certificates(&[buf]);*/
    
    let mut config = ClientConfig::builder()
        .with_safe_defaults()
        .with_root_certificates(store)
        .with_no_client_auth();

    // if you want to completely disable cert-verification, use this
    let mut dangerous_config = ClientConfig::dangerous(&mut config);
    dangerous_config.set_certificate_verifier(Arc::new(NoCertificateVerification {}));

    Ok(config)
}
pub struct NoCertificateVerification {}
impl rustls::client::ServerCertVerifier for NoCertificateVerification {
    fn verify_server_cert(
        &self,
        _end_entity: &rustls::Certificate,
        _intermediates: &[rustls::Certificate],
        _server_name: &rustls::ServerName,
        _scts: &mut dyn Iterator<Item = &[u8]>,
        _ocsp: &[u8],
        _now: std::time::SystemTime,
    ) -> Result<rustls::client::ServerCertVerified, rustls::Error> {
        Ok(rustls::client::ServerCertVerified::assertion())
    }
}

相关问题