如何检测Android应用发出的HTTP请求并获取请求域名?
解决方案
1. 结合StrictMode与DNS缓存映射反查域名
StrictMode触发时仅能获取IP,但你可以提前Hook系统的DNS解析方法,记录域名-IP的映射关系,当StrictMode检测到明文请求时,通过IP反向查找对应的域名。
实现思路:
- Hook
InetAddress.getAllByName()或InetAddress.getByName()方法(这是大部分应用/第三方库做DNS解析的核心入口),每次解析时把域名和对应的IP存入全局缓存(比如HashMap<String, List<String>>,键为域名,值为解析出的IP列表)。 - 在StrictMode的
onCleartextNetwork()回调中,拿到IP后遍历缓存,匹配对应的域名。
代码示例(以Xposed框架为例,无ROOT需求可改用ByteBuddy等字节码工具):
// Hook DNS解析方法 XposedHelpers.findAndHookMethod(InetAddress.class, "getAllByName", String.class, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { String domain = (String) param.args[0]; InetAddress[] addresses = (InetAddress[]) param.getResult(); if (addresses != null && addresses.length > 0) { List<String> ips = new ArrayList<>(); for (InetAddress addr : addresses) { ips.add(addr.getHostAddress()); } // 存入全局缓存 DnsCache.put(domain, ips); } } }); // StrictMode回调中反查域名 StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() .detectCleartextNetwork() .penaltyListener(ExecutorService.newSingleThreadExecutor(), violation -> { if (violation instanceof StrictMode.CleartextNetworkViolation) { String ip = ((StrictMode.CleartextNetworkViolation) violation).getHostAddress(); // 遍历缓存匹配对应域名 for (Map.Entry<String, List<String>> entry : DnsCache.entrySet()) { if (entry.getValue().contains(ip)) { Log.e("CleartextDetect", "第三方库明文请求域名:" + entry.getKey() + ",IP:" + ip); break; } } } }) .build());
2. 利用Android 10+的NetworkCallback监控网络连接
Android 10(API 29)及以上提供了更精细的网络连接监控能力,通过ConnectivityManager.NetworkCallback可以获取应用发起的网络连接详细信息,包括域名。
实现步骤:
- 创建
NetworkRequest,指定监听所有网络类型; - 注册
NetworkCallback,在onCapabilitiesChanged回调中检测NETWORK_CAPABILITY_CLEARTEXT标记,同时通过LinkProperties获取连接的域名信息。
代码示例:
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkRequest request = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .build(); cm.registerNetworkCallback(request, new ConnectivityManager.NetworkCallback() { @Override public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities capabilities) { super.onCapabilitiesChanged(network, capabilities); // 检测是否为明文连接 if (capabilities.hasCapability(NetworkCapabilities.NETWORK_CAPABILITY_CLEARTEXT)) { LinkProperties linkProperties = cm.getLinkProperties(network); if (linkProperties != null) { // 获取连接关联的域名(需根据实际场景调整解析逻辑) for (Uri uri : linkProperties.getHttpProxy().getPacUris()) { Log.e("CleartextDetect", "明文请求域名:" + uri.getHost()); } } } } });
3. 全局代理拦截(API 21+,无需ROOT)
通过设置全局HTTP代理,将所有应用的网络请求路由到本地代理服务,从而拦截并记录所有HTTP请求的完整URL,包括第三方库的请求。
实现思路:
- 创建本地代理服务(可基于OkHttp的
ProxyServer或自定义Socket服务); - 通过
Settings.Secure.putString()设置全局代理,指向本地服务; - 在代理服务中解析请求头,提取完整URL并记录。
注意事项:
- 需要申请
WRITE_SETTINGS权限,部分ROM可能限制第三方应用修改全局代理; - 若仅关注HTTP请求,无需处理HTTPS证书信任问题。
内容的提问来源于stack exchange,提问作者casolorz
相关产品推荐
相关产品推荐

