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

如何避免Android App的HTTPS API被抓包工具捕获?

如何防止Android应用的SSL API被抓包工具捕获

嘿,这个问题我太熟悉了——很多开发者都会碰到这种情况:自己的App装了用户的第三方CA证书后,HTTPS流量就被Fiddler、Charles这类工具扒得一干二净,而有些大厂App却能防住。核心原因就是那些App做了**证书固定(Certificate Pinning)**和其他防护措施,下面我给你拆解具体怎么做,结合你用Let's Encrypt的情况来优化:

1. 核心手段:实施证书固定

这是最有效的防抓包方法,简单说就是让你的App只认你指定的Let's Encrypt证书,不管系统里装了什么第三方CA。

两种实现方式,按需选择:

  • 静态固定(适合小团队/快速落地):把Let's Encrypt证书的哈希值(或者公钥哈希)硬编码到App里。每次发HTTPS请求时,App会自动核对服务器返回的证书哈希是否和硬编码的一致,不一致就直接断开连接。
    比如用OkHttp的话,代码大概是这样:
    CertificatePinner certificatePinner = new CertificatePinner.Builder()
        .add("your-domain.com", "sha256/这里替换成你的Let's Encrypt证书公钥哈希")
        .build();
    
    OkHttpClient client = new OkHttpClient.Builder()
        .certificatePinner(certificatePinner)
        .build();
    
    👉 划重点:Let's Encrypt的证书是90天有效期的,如果你固定的是证书哈希,到期后App就连不上服务器了!所以更推荐固定公钥哈希——Let's Encrypt renew证书时公钥不会变,这样就不用每次证书更新都发版本了。
  • 动态固定(适合有服务器能力的团队):从你的后端服务器定期获取合法证书的哈希,更新到App里。这种方式能避免静态固定的有效期问题,但要注意更新过程本身得是安全的,别被攻击者篡改了更新内容。

2. 让App只信任你指定的证书

默认情况下,Android App会用系统的信任存储,里面包含了用户装的第三方CA。你可以让App完全用自己内置的信任存储,只放Let's Encrypt的根证书/中间证书,这样就算用户装了Fiddler的证书,App也不认它。

还是用OkHttp举例子,代码大概是这样:

// 把Let's Encrypt的根证书放到raw资源文件夹里
InputStream certInputStream = getResources().openRawResource(R.raw.lets_encrypt_root_cert);
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
X509Certificate letsEncryptCert = (X509Certificate) certFactory.generateCertificate(certInputStream);
certInputStream.close();

// 创建自己的信任存储
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("lets_encrypt", letsEncryptCert);

// 初始化TrustManager
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);

// 配置SSLContext
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);

// 给OkHttp设置自定义的SSL套接字工厂
OkHttpClient client = new OkHttpClient.Builder()
    .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) tmf.getTrustManagers()[0])
    .build();

3. 检测并阻止代理连接

抓包工具必须依赖代理才能截获流量,所以你可以在App里加个检测逻辑,如果发现用户开了系统代理或者App代理,就拒绝发起请求,或者给用户提示。

检测代理的代码示例:

String httpProxyHost = System.getProperty("http.proxyHost");
int httpProxyPort = Integer.parseInt(System.getProperty("http.proxyPort", "-1"));
String httpsProxyHost = System.getProperty("https.proxyHost");
int httpsProxyPort = Integer.parseInt(System.getProperty("https.proxyPort", "-1"));

if ((httpProxyHost != null && httpProxyPort != -1) || (httpsProxyHost != null && httpsProxyPort != -1)) {
    // 检测到代理,这里可以弹出警告、终止请求或者直接退出
    Toast.makeText(this, "检测到代理配置,无法正常连接服务器", Toast.LENGTH_LONG).show();
    return;
}

4. 加固App,提高逆向成本

  • 确保发布版本的App禁用调试模式:Android Studio的release构建默认会把AndroidManifest.xml里的android:debuggable设为false,别手动改回来。
  • 用ProGuard/R8做代码混淆:把你的代码打乱,让攻击者很难逆向分析出证书固定的逻辑,也就不容易绕过了。

5. 升级TLS配置,减少漏洞

让你的服务器和App只支持TLS 1.3和强加密套件,降低被破解的风险。比如在OkHttp里指定TLS版本:

ConnectionSpec modernTlsSpec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
    .tlsVersions(TlsVersion.TLS_1_3)
    .build();

OkHttpClient client = new OkHttpClient.Builder()
    .connectionSpecs(Collections.singletonList(modernTlsSpec))
    .build();

最后提醒

这些措施都是提高攻击门槛,没办法完全阻止有经验的攻击者(比如他们可以逆向修改App代码绕过证书固定),但对付普通的抓包场景已经足够了。另外,证书固定一定要测试到位,别因为配置错了哈希导致用户连不上服务器!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 08:37:28