在这里插入图片描述

在Android系统中,为了进行网络权限控制、流量统计等,需要将网络连接(如Socket)与发起该连接的应用UID关联起来。这种关联通常在内核中建立,并在用户空间通过一些接口进行查询。

1. 内核中的实现基础

Linux内核中,每个Socket都有一个关联的struct sock结构。在该结构中,有一个字段用于存储用户ID(UID):

struct sock {// ...kuid_t sk_uid; // 存储创建该socket的进程的UID// ...
};

当应用创建一个Socket时,内核会将该进程的UID(即进程的有效UID)记录在sock->sk_uid中。
该字段在 Socket 创建时由内核自动填充(通过 current_uid() 获取当前进程 UID)。

2. 用户空间查询连接UID的方法

在用户空间,Android系统提供了几种方式来获取网络连接的UID:

(1) 使用/proc/net文件系统

Linux内核通过/proc/net下的文件(如/proc/net/tcp、/proc/net/udp等)暴露TCP和UDP连接的信息。这些文件中包含的每一行代表一个连接,其中有一列是UID(在Android中,该列是第7列,索引从0开始计数)。例如:

sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
0: 0100007F:1770 00000000:0000 0A 00000000:00000000 00:00000000 00000000 10086        0 123456

这里,UID为10086。

在Android系统中,系统服务(如NetworkStatsService)会解析这些文件以获取每个连接的UID,从而进行流量统计。

(2) 使用Netlink Socket

更高效的方式是使用Netlink Socket(具体为NETLINK_INET_DIAG)来查询Socket信息。Android系统使用NetlinkSocket类(位于frameworks/base/core/jni/android_net_Netlink.cpp)来发送查询请求并解析响应。

在NetlinkSocket的请求中,可以指定查询条件(如协议、状态等),内核会返回匹配的Socket信息,其中就包括UID。

例如,在NetworkStatsService中,通过netlink方式收集Socket信息:

// 在Java层,通过调用Native方法
// frameworks/base/services/core/java/com/android/server/net/NetworkStatsService.java
private void readNetworkStatsDev() {// ...mNetworkDevStats = new NetworkStats(SystemClock.elapsedRealtime(), 6);mNetworkDevStats = NetworkStatsService.nativeReadNetworkDevStats();// ...
}

在Native层(frameworks/base/services/core/jni/com_android_server_net_NetworkStatsService.cpp)中,最终会调用netlink相关函数来获取信息。

或通过 Netlink Socket 发送 inet_diag_req 请求,内核返回 inet_diag_msg 结构体,其中包含 idiag_uid 字段:

struct inet_diag_msg {__u8    idiag_family;__u8    idiag_state;// ...__u32   idiag_uid;    // 连接的 UID__u32   idiag_inode;  // Socket 的 inode
};

这是 NetworkStatsService 等系统服务内部使用的机制

(3) 系统API:TrafficStats.getUidRxBytes(int uid)等

Android提供了TrafficStats类,其中包含一些静态方法,如:

getUidRxBytes(int uid)
getUidTxBytes(int uid)

这些方法允许应用获取指定UID的流量统计。其内部实现也是通过读取/proc/net文件或使用netlink,然后按UID聚合统计信息。

  • 系统 API(隐藏 API)
    Android 框架中部分类提供内部方法,如:
// 示例:通过 Socket 文件描述符获取 UID
int uid = android.os.Process.getUidForSocket(int socketFd);

实际实现通过 JNI 调用到 libcore 中的 native 方法

(4) 系统服务中的连接跟踪

在Android系统服务中,如ConnectivityService、NetworkStatsService等,会定期扫描网络连接,并记录每个连接的UID。这些信息可以用于防火墙规则(如根据UID阻止网络访问)或网络统计。

3. 具体实现:getConnectionOwnerUid的类似功能

如果我们要实现一个getConnectionOwnerUid函数,其功能是给定一个本地地址和端口(或远程地址和端口),返回该连接的UID,那么可以通过以下步骤:

查询/proc/net文件:遍历/proc/net/tcp和/proc/net/udp等文件,查找匹配本地地址和端口的行,然后提取UID列。
使用netlink查询:构造一个inet_diag_req请求,设置查询条件(如本地地址和端口),然后发送请求并解析响应,从响应中获取UID。
4. 示例:通过/proc/net/tcp获取UID
以下是一个简化的示例,展示如何从/proc/net/tcp中获取指定本地地址和端口的连接的UID:

public static int getConnectionOwnerUid(String protocol, String localAddr, int localPort) {String procFile = "/proc/net/" + protocol; // 如 "tcp" 或 "udp"try (BufferedReader reader = new BufferedReader(new FileReader(procFile))) {String line;// 跳过标题行reader.readLine();while ((line = reader.readLine()) != null) {// 按空格分割,注意可能有多个连续空格String[] tokens = line.trim().split("\\s+");if (tokens.length < 10) continue;// 本地地址和端口在第二个字段(索引1)String local = tokens[1];// 解析本地地址和端口String[] localParts = local.split(":");if (localParts.length != 2) continue;// 将16进制字符串形式的地址和端口转换为可读格式String addr = parseHexAddress(localParts[0]);int port = Integer.parseInt(localParts[1], 16);// 比较是否匹配if (addr.equals(localAddr) && port == localPort) {// UID在第8个字段(索引7)return Integer.parseInt(tokens[7]);}}} catch (IOException e) {e.printStackTrace();}return -1; // 未找到
}private static String parseHexAddress(String hex) {// 处理IPv4地址:4字节,小端序long addr = Long.parseLong(hex, 16);return String.format("%d.%d.%d.%d",(addr & 0xff),((addr >> 8) & 0xff),((addr >> 16) & 0xff),((addr >> 24) & 0xff));
}

注意:上述代码仅为示例,实际应用中需要考虑IPv6、性能优化(避免频繁读取proc文件)以及权限问题(需要root权限才能读取/proc/net文件)。

5. 权限要求

读取/proc/net下的文件需要root权限,因为普通应用无法访问这些文件。
使用netlink也需要root权限,因为创建NETLINK_INET_DIAG类型的socket需要CAP_NET_ADMIN能力。

6. 在Android系统中的应用

在Android系统内部,如NetworkStatsService、NetworkManagementService等系统服务中,会使用这些机制来跟踪每个连接的UID,以便进行流量统计和网络策略管理。

Android 版本差异

  • Android 7.0+ 强化了 UID 隔离,/proc/net 文件权限更严格。
  • Android 10+ 引入 CONNTRACK_UID 模块替代部分旧机制。

总结

Android系统通过内核记录每个Socket的创建者UID。
用户空间可以通过读取/proc/net下的文件或使用netlink机制来查询活跃连接的UID。
这些查询通常需要root权限,因此主要用于系统服务内部。
普通应用无法直接使用这些方法,但可以通过系统API(如TrafficStats)获取按UID聚合的流量统计信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/93185.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/93185.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/93185.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源 Arkts 鸿蒙应用 开发(十)通讯--Http数据传输

文章的目的为了记录使用Arkts 进行Harmony app 开发学习的经历。本职为嵌入式软件开发&#xff0c;公司安排开发app&#xff0c;临时学习&#xff0c;完成app的开发。开发流程和要点有些记忆模糊&#xff0c;赶紧记录&#xff0c;防止忘记。 相关链接&#xff1a; 开源 Arkts …

net8.0一键创建支持(RabbitMQ)

Necore项目生成器 - 在线创建Necore模板项目 | 一键下载 RabbitMQController.cs using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using RabbitMQ.Client; using RabbitMQ.Client.Events; using System.Text; using System.Threading.Tasks; using UnT.Tem…

Rust 泛型与特性

Rust 泛型与特性 引言 Rust 语言以其安全性和高效性在编程语言中独树一帜。Rust 的泛型和特性是其核心特性之一,它们使得开发者能够编写更加通用、灵活且安全的代码。本文将深入探讨 Rust 中的泛型和特性,包括其概念、用法以及在实际开发中的应用。 泛型简介 概念 泛型是…

LangChain学习——结构化输出和数据解析

LangChain 本指南全面介绍LangChain中结构化输出生成和数据解析的核心功能&#xff0c;包括Pydantic BaseModel构造、各种输出解析器的使用&#xff0c;以及高级错误处理机制。 详细测试样例和代码可参考如下两个链接&#xff1a; test_output_parserstest_pydantic_base_mo…

基于华为ENSP的BGP的状态机深入浅出

本篇技术博文摘要 &#x1f31f; 本文章主要探讨BGP状态机如何控制BGP连接的建立与维护&#xff0c;以及BGP协议在运行过程中如何交换路由信息并确保网络的稳定性 引言 &#x1f4d8; 在这个快速发展的技术时代&#xff0c;与时俱进是每个IT人的必修课。我是肾透侧视攻城狮&…

Android 15中的16KB大页有何优势?

deepseek回答&#xff1a; Android 15引入的16KB大内存页是系统性能优化的关键变革&#xff0c;其核心优势体现在以下方面&#xff1a; ⚡ 一、性能全面提升 系统整体加速 配置16KB页面的设备整体性能提升5%-10%&#xff0c;通过减少内存管理开销释放更多资源用于应用运行。…

Gis数据的A*算法规划航线

1.1 用到的技术栈geotools JTSJgrapht1.2 实现思路// 定义栅格网格参数private static final double CELL_SIZE_DEGREES 0.005;private static int gridWidth 0;//格子高度 index 1private static int gridHeight 0;//格子宽度// 1. 读取GeoJSON文件File geoJsonFile new …

Spring Boot 默认使用 CGLIB,但CGLIB 无法代理 final 类或 final 方法

那么当这两件事冲突时&#xff0c;Spring Boot 是怎么“解决”的呢&#xff1f;答案是&#xff1a;它不解决&#xff0c;也无法解决。当这种情况发生时&#xff0c;你的应用程序会直接启动失败。这不是 Spring Boot 的疏忽&#xff0c;而是由 CGLIB 的底层原理和 Java 语言的规…

cuda编程笔记(10)--memory access 优化

全局内存访问优化&#xff08;Coalesced Access&#xff09; 什么是 Coalesced Access&#xff1f; 定义&#xff1a;一个 warp&#xff08;32 个线程&#xff09;在同一指令中访问全局内存时&#xff0c;如果这些访问请求可以合并成尽可能少的内存事务&#xff08;通常是 32…

闲庭信步使用图像验证平台加速FPGA的开发:第三十一课——车牌识别的FPGA实现(3)车牌字符分割预处理

&#xff08;本系列只需要modelsim即可完成数字图像的处理&#xff0c;每个工程都搭建了全自动化的仿真环境&#xff0c;只需要双击top_tb.bat文件就可以完成整个的仿真&#xff0c;大大降低了初学者的门槛&#xff01;&#xff01;&#xff01;&#xff01;如需要该系列的工程…

电子电气架构 --- 汽车软件全生命周期

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…

力扣面试150(41/150)

7.25 56. 合并区间 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 我的思路&#xff1a; 左端点升序…

【隧道篇 / IPsec】(7.6) ❀ 01. 利用向导快速建立IPsec安全隧道 (点对点) ❀ FortiGate 防火墙

【简介】相信很多人已经习惯利用导向快速创建VPN了&#xff0c;而且已经有部分尝鲜者已经用上了FortiOS 7.6&#xff0c;但是会发现FortiOS 7.6下的VPN向导改变了很多&#xff0c;一时无法下手&#xff0c;下面我们来看看最常见的点对点是如何配置的。环境介绍在配置IPsec VPN之…

PLLIP核

。1 号红色框内的速度等级代表着设备的速度 等级&#xff0c;保存默认就好&#xff1b;2 号红色框内设置输入频率&#xff1b;3 号红色框选择 PLL 的工作模式。我们 开发板用的晶振是 50MHz 的&#xff0c;故在 2 号红色框内我们填写 50MHz&#xff1b;我们在 3 号红色框内选正…

1.1 Deep learning?pytorch ?深度学习训练出来的模型通常有效但无法解释合理性? 如何 解释?

DL 是什么&#xff0c;你如何理解DL模型&#xff1f; DL 对于我而言&#xff0c;就是人类试图想通过数学语言描述人类学习过程的一门技术&#xff0c;或者说学科。 因此 DL 模型 相当于 数学 的 一个 funciton &#xff0c;有输入&#xff0c;通过function处理&#xff0c;得…

java实现在工具类中注入其他对象方式

方案1&#xff1a; Slf4j Component public class ChatdocApiClient {Value("${chatdoc.app-id}")private String appId;Value("${chatdoc.secret}")private String secret;Value("${chatdoc.domain}")private String domain;private final Rest…

electron中IPC 渲染进程与主进程通信方法解析

electron中ipcRenderer.invoke、ipcRenderer.on、ipcRenderer.send、ipcRenderer.sendSync作用与区别 IPC 渲染进程与主进程通信方法解析 ipcRenderer 的这几个方法作用不完全相同&#xff0c;它们适用于不同的通信场景&#xff0c;核心区别在于通信方向、是否需要响应以及同步…

epoll_event 事件类型详解

epoll_event 事件类型详解 epoll_event 是 Linux epoll I/O 多路复用机制的核心结构体&#xff0c;其中的事件类型决定了 epoll 监控的行为和触发条件。以下是各种事件类型的详细解析&#xff1a; epoll_event 结构体 #include <sys/epoll.h>typedef union epoll_data {v…

设计自己的小传输协议 导论与概念

设计自己的小传输协议 导论与概念 1&#xff1a;聊一聊协议头设计 ​ 早在《TCP/IP详解》中的第一句话中&#xff0c;我们就知道协议的含义是这样的&#xff1a;协议是通信双方共同遵守的一套规则&#xff0c;提供格式定义、语义解释等&#xff0c;使不同设备或软件能够正确交…

iOS —— 天气预报仿写总结

在iOS中&#xff0c;最常见的网络请求方式是NSURLSession&#xff0c;它是苹果推荐的现代API&#xff0c;简单安全且易于拓展。一次完整的网络请求流程&#xff1a;构造 NSURL 对象创建 NSURLSessionDataTask发起请求&#xff08;resume&#xff09;在回调中解析数据回到主线程…