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

使用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?;

额外检查项

  1. 确认CA证书有效性:确保/tmp/ca.pem是Burp导出的根CA证书(而非服务器证书或中间证书),证书的issuer和subject应完全一致(对应openssl输出中depth=1的证书)。
  2. 移除不必要的危险配置:当CA信任正确后,danger_accept_invalid_hostnames和danger_accept_invalid_certs可以移除,避免降低安全性。
  3. 依赖版本验证:确保async-native-tls和native-tls使用最新稳定版,旧版本可能存在证书处理逻辑的bug。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 05:50:11