使用async-native-tls配置自定义CA连接Burp透明代理遇证书验证错误
解决async-native-tls连接Burp透明代理的证书验证错误
问题背景
我尝试使用async-native-tls连接Burp透明代理,Burp会根据传入TLS连接的SNI参数动态生成由自身CA签名的新证书。虽然已将Burp CA配置为信任根,且openssl s_client验证正常,但程序仍报错"自签名证书在证书链中"。
相关代码片段
use async_native_tls::{Certificate, TlsConnector}; use http_client::hyper::HyperClient; use http_client::{hyper, Config, HttpClient, Request}; use std::error::Error; use std::sync::Arc; let mut tls_builder = native_tls::TlsConnector::builder(); tls_builder // This is important, as it's how Burp knows which certificate to present .use_sni(true) // This is important, as it indicates that Burp's CA should be trusted .add_root_certificate(Certificate::from_pem( std::fs::read("/tmp/ca.pem")?.as_slice(), )?) // These should not be required, but I've turned them on in despairation .danger_accept_invalid_hostnames(true) .danger_accept_invalid_certs(true) .disable_built_in_roots(true) .max_protocol_version(None) .min_protocol_version(None); let burp_proxy_tls = TlsConnector::from(tls_builder); let burp_proxy_config = Config::default().set_tls_config(Some(Arc::new(burp_proxy_tls))); let mut http_client = HyperClient::new(); http_client.set_config(burp_proxy_config)?; let mut request = Request::get("https://127.0.0.1:8000/..."); request.append_header("Cookie", "..."); // Not strictly needed since it's also in SNI request.append_header("Host", "..."); let mut response = http_client.send(request).await?;
openssl验证结果
$ openssl s_client -connect 127.0.0.1:8000 \ -servername www......com \ -CAfile /tmp/ca.pem \ </dev/null CONNECTED(00000003) depth=1 C = PortSwigger, ST = PortSwigger, L = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = PortSwigger CA verify return:1 depth=0 C = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = www......com verify return:1 --- Certificate chain 0 s:C = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = www........com i:C = PortSwigger, ST = PortSwigger, L = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = PortSwigger CA a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256 v:NotBefore: Jan 10 02:29:14 2023 GMT; NotAfter: Jan 10 02:29:14 2024 GMT 1 s:C = PortSwigger, ST = PortSwigger, L = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = PortSwigger CA i:C = PortSwigger, ST = PortSwigger, L = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = PortSwigger CA a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256 v:NotBefore: Jan 24 00:53:54 2014 GMT; NotAfter: Jan 24 00:53:54 2033 GMT ... subject=C = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = www.......com issuer=C = PortSwigger, ST = PortSwigger, L = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = PortSwigger CA --- No client certificate CA names sent Peer signing digest: SHA256 Peer signature type: RSA-PSS Server Temp Key: X25519, 253 bits --- SSL handshake has read 2521 bytes and written 403 bytes Verification: OK --- New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384 Server public key is 2048 bit Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE No ALPN negotiated Early data was not sent Verify return code: 0 (ok) --- DONE
程序运行错误
$ cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.15s Running `target/debug/xxxxxx` Error: error trying to connect: error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:1889: (self-signed certificate in certificate chain) Caused by: 0: error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:1889: (self-signed certificate in certificate chain) 1: error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:1889:
解决方案
核心问题:配置顺序错误
你的代码中先调用add_root_certificate再调用disable_built_in_roots(true),而disable_built_in_roots会清空所有已加载的根证书(包括你刚添加的Burp CA),导致实际没有信任任何根证书,最终触发验证错误。
修正后的代码
调整配置顺序,先禁用内置根证书,再添加Burp CA:
use async_native_tls::{Certificate, TlsConnector}; use http_client::hyper::HyperClient; use http_client::{hyper, Config, HttpClient, Request}; use std::error::Error; use std::sync::Arc; let mut tls_builder = native_tls::TlsConnector::builder(); tls_builder // 先禁用内置根证书,避免干扰自定义CA .disable_built_in_roots(true) // 启用SNI,让Burp正确生成对应证书 .use_sni(true) // 添加Burp的根CA证书 .add_root_certificate(Certificate::from_pem( std::fs::read("/tmp/ca.pem")?.as_slice(), )?) // 信任正确CA后可移除以下危险配置 .danger_accept_invalid_hostnames(true) .danger_accept_invalid_certs(true) .max_protocol_version(None) .min_protocol_version(None); let burp_proxy_tls = TlsConnector::from(tls_builder); let burp_proxy_config = Config::default().set_tls_config(Some(Arc::new(burp_proxy_tls))); let mut http_client = HyperClient::new(); http_client.set_config(burp_proxy_config)?; let mut request = Request::get("https://127.0.0.1:8000/..."); request.append_header("Cookie", "..."); request.append_header("Host", "..."); let mut response = http_client.send(request).await?;
额外检查项
- 确认CA证书有效性:确保
/tmp/ca.pem是Burp导出的根CA证书(而非服务器证书或中间证书),证书的issuer和subject应完全一致(对应openssl输出中depth=1的证书)。 - 移除不必要的危险配置:当CA信任正确后,
danger_accept_invalid_hostnames和danger_accept_invalid_certs可以移除,避免降低安全性。 - 依赖版本验证:确保
async-native-tls和native-tls使用最新稳定版,旧版本可能存在证书处理逻辑的bug。
内容的提问来源于stack exchange,提问作者Huckle
相关产品推荐
相关产品推荐

