iptables 在 Android 抓包中的妙用

news2024/10/10 10:31:03

本文介绍一种在 Andorid 中实现单应用、全局、优雅的抓包方法。

此文于去年端午节编写,由于种种原因,当时藏拙并未发布。现删除一些敏感信息后分享出来,希望对各位有所启发。

背景

昨天在测试一个 Android APK 的时候发现使用 WiFi 的 HTTP 代理无法抓到包,在代理的日志中没有发现任何 SSL Alert,因此可以判断不是证书问题;另外 APP 本身仍可以正常收发数据,这说明代理设置被应用绕过了。

根据我们前一篇文章(终端应用安全之网络流量分析)中所介绍的,遇到这种情况时就可以使用路由抓包方法,确保接管所有流量。但是因为端午放假被封印在家,且用于抓包的树莓派放在了公司,因此只有另谋他路。

本来接着考虑装个 DroidProxy 去试一下,但突然间灵光一闪,为什么不直接用 iptables 去修改流量呢?于是,就有了这篇小记。

iptables 101

iptables 应该大家都不会陌生,说起来这也是我入门 “黑客” 时就接触的命令,因为我的网络安全入门第一战就是使用 aircrack 去破解邻居的 WiFi 密码。多年以前还写过一篇Linux内核转发技术,介绍 iptables 的常用操作,但当时年幼无知,很多概念自己并没有完全理解。其实介绍 iptables 最好的资料就是官方的 man-pages,因此这里也就不做一个无情的翻译机器人了,只简单介绍一些关键的概念。

basic

首先是我们作为系统管理员最为关心的命令行参数,在坊间流传的各类防火墙、WiFi 热点、流控 shell 脚本中,充斥着各种混乱而难以理解的 iptables 命令,但实际上其命令行参数非常优雅,可以概况为以下表述:

iptables [-t table] {-A|-C|-D} chain rule-specification

rule-specification = [matches...] [target]
match = -m matchname [per-match-options]
target = -j targetname [per-target-options]

一个 table 中有多个 chain,除了内置的 chain,用户也可以自己新建(比如 DOCKER 链)。常用的 table 及其包含的 chain 有以下这些:

  • filter
    • INPUT
    • FORWARD
    • OUTPUT
  • nat
    • PREROUTING
    • INPUT
    • OUTPUT
    • POSTROUTING
  • mangle
    • PREROUTING
    • OUTPUT
    • INPUT
    • FORWARD
    • POSTROUTING
  • raw
    • PREROUTING
    • OUTPUT

其中有的表比其他表包含更多的 chain,这是其定位决定的。正如其名字而言,filter 主要用于流量过滤,nat 表主要用于网络地址转换,mangle 表用于数据包修改,而 raw 表则用于网络包更早期的配置。除此之外还有 security 表用于权限控制,不过用得不多。

虽然看起来各个表各司其职,但实际中也没有强制的差异。比如 mangle 表虽然用来修改流量,但也可以用来做网络地址转换,filter 表也是同理。在日常中设置 iptables 规则的时候主要考虑的是数据包的时序,而这和 chain 的关系更大一些。

上面提到的这些常见 chain,不管在哪个表中,其含义都是类似的:

  • INPUT: 表示数据包从远端发送到本地;
  • OUTPUT: 表示数据包在本地生成,并准备发送到远端;
  • PREROUTING: 接收到数据包的第一时间,在内核进行路由之前;
  • POSTROUTNG: 表示数据包准备离开的前一刻;
  • FOWARD: 本机作为路由时正要准备转发的时刻;

table 结合对应的 chain,网络数据包在 iptables 中的移动路径如下图所示:

flow

extensions

对于 iptables 而言重点无疑是其中的规则定义,上文提到的参数无非就是将自定义的规则加入到对应 CHAIN 之中,比如 -A 是将规则插入到链的末尾(append),-I 是插入到链的头部(insert),-D 是删除对应规则(delete),等等。

而规则又分为两个部分,即数据包匹配以及匹配之后的操作,分别通过 -m-j 来指定。这其中就引入了成百的命令行参数,以至于社区还就此产生了不少段子:

Overheard: “In any team you need a tank, a healer, a damage dealer, someone with crowd control abilities and another one who knows iptables”

— Jérome Petazzoni (@jpetazzo) June 27, 2015

不过实际上社区对 iptables 的抱怨更多是在多用户系统中规则配置冲突以及由此引发的艰难调试之旅,在没有冲突的情况下,配置规则也是比较简单的。定义 iptables 规则的参考主要是 iptables-extensions(8),其中定义了一系列 匹配拓展(MATCH EXTENSIONS) 以及 目标拓展(TARGET EXTENSIONS)

match

先看匹配拓展,一般我们使用 iptables 都是根据 ip 或者端口进行匹配,比如 -m tcp --dport 22。但其中也有一些比较有趣的匹配规则,比如上一篇文章中介绍过的 Android 单应用抓包方法:

$ iptables -A OUTPUT -m owner --uid-owner 1000 -j CONNMARK --set-mark 1
$ iptables -A INPUT -m connmark --mark 1 -j NFLOG --nflog-group 30 
$ iptables -A OUTPUT -m connmark --mark 1 -j NFLOG --nflog-group 30 
$ dumpcap -i nflog:30 -w uid-1000.pcap

用到了两个匹配拓展,一个是 owner 拓展,使用 --uid-owner 参数表示创建当前数据包的应用 UID。但是这样只能抓到外发的包,而服务器返回的包由于并不是本地进程创建的,因此没有对应的 UID 信息,因此 owner 拓展只能应用于 OUTPUT 或者 POSTROUTING 链上。为了解决这个问题,上面使用了另一个拓展 connmark,用来匹配 tcp 连接的标志,这个标志是在第一条命令中的外发数据中进行设置的。

还有个值得一提的匹配拓展是 bpf,支持两个参数,可以使用 --object-pinned 直接加载编译后的 eBPF 代码,也可以通过 --bytecode 直接指定字节码。直接指定的字节码格式类似于 tcpdump -ddd 的输出结果,第一条是总指令数目。

例如以下 bpf 指令 (ip proto 6):

4               # number of instructions
48 0 0 9        # load byte  ip->proto
21 0 1 6        # jump equal IPPROTO_TCP
6 0 0 1         # return     pass (non-zero)
6 0 0 0         # return     fail (zero)

实际调用时候需用用逗号分隔每条指令,且不支持注释等其他符号:

iptables -A OUTPUT -m bpf --bytecode '4,48 0 0 9,21 0 1 6,6 0 0 1,6 0 0 0' -j ACCEPT

对于其他遇到的匹配拓展,可以在官方文档中查看其详细用法。

target

target 表示数据包匹配之后要执行的操作,一般使用大写表示。标准操作有 ACCEPT/DROP/RETURN 这三个,其他都定义在 target extensions 即目标拓展中。

比如我们前面提到的 CONNMARK 就是其中一个拓展,其作用是对当前链接进行打标,这样 TCP 请求的返回数据也会带上我们的标记。类似的还有 MARK 拓展,表示对当前数据包设置标志,主要用于后续 table/chain 的识别。

前面用到的另一个拓展是 NFLOG,表示 netfilter logging,规则匹配后内核会将其使用对应的日志后端进行保存,通常与 nfnetlink_log 一起使用,通过多播的方式将获取到的数据包发送到 netlink 套接字中,从而可以让用户态的抓包程序获取并进行进一步分析。

其他常用的拓展还有 SNAT/DNAT 用于修改数据包的源地址和目的地址,LOG 可以使内核 dmesg 打印匹配的数据包信息,TRACE 可以使内核打印规则信息用于调试分析等。

Android Proxy

复习完 iptables 的基础后,我们继续回到文章开头的问题,有什么办法可以在不设置代理的基础上代理所有流量呢?

这个问题可以从两方面去考虑,即:

  1. 如何匹配目标数据包;
  2. 匹配之后如何转发到代理地址;

第一个问题比较简单,我们需要匹配从本地发出的,目的端口是 80/443 的 tcp 流量,因此匹配规则可以写为:

-p tcp -m tcp --dport 443

在不确定目标 web 服务器端口的情况下,可以将 dport 指定为 0:65535,对所有端口都进行劫持转发;当然也可以直接不写 match,默认就是匹配所有 tcp 包。不过可以稍微过滤一下目的地址,比如 ! -d 127.0.0.1,以免本地的 RPC 请求也被误拦截。

或者,更优雅的方案是使用 multiport 来一次性指定多个端口:

-m multiport --dports 80,443

第二个问题,既然我们需要将流量转发到代理工具,那么可以选择透明代理模式,上篇文章也有提到过。因此一个最简单的方法是使用 DNAT 修改目的地址。查阅文档可知,DNAT 只能用在 nat 表中的 PREROUTINGOUTPUT 链。再根据上文中的流程图,如果代理地址在本地,那只能使用 OUTPUT、如果是远程地址,那么两个链任选一个即可。

综上所述,假设 HTTP 透明代理监听在 127.0.0.1:8080,那么可以直接用以下方法设置代理并进行抓包:

iptables -t nat -A OUTPUT -p tcp ! -d 127.0.0.1 -m multiport --dports 80,443 -j DNAT --to-destination 127.0.0.1:8080

更进一步

通过这么一条 iptables 命令,配合上透明代理就可以实现全局的 HTTPS 抓包了。所以就这样了吗?回忆一下之前我们其实是可以通过 owner target 去进行 UID 匹配的,只不过之前是使用 NFLOG 配合 tcpdump 进行抓包。因此我们其实也可以通过类似的方式实现基于 UID 的透明代理。

转发规则并没有太大变化,只需要在匹配规则上新增一个约束。

iptables -t nat -A OUTPUT -p tcp ! -d 127.0.0.1 -m owner --uid-owner 2000 -m multiport --dports 80,443 -j DNAT --to-destination 127.0.0.1:8080

这样,不需要额外的路由抓包设备,甚至不需要引入 VPN Service 等其他应用,只需要一行命令即可实现针对单个 Android 应用的全局 HTTP/HTTPS 抓包。

elegant

总结

本文主要介绍了 iptables 规则的配置方法,并且实现了一种在 Android 中全局 HTTP(S) 抓包的方案,同时借助 owner 拓展实现应用维度的进一步过滤,从而避免手机中其他应用的干扰。

相比于传统的 HTTP 代理抓包方案,该方法的优势是可以实现全局抓包,应用无法通过禁用代理等方法绕过;而相比于 Wireshark 等抓包方案,该方法基于透明代理,因此可以使用 BurpSuite、MITMProxy 等成熟的 HTTP/HTTPS 网络分析工具来对流量进行快速的可视化、拦截/重放,以及脚本分析等操作,这些优势是传统抓包方案所无法比拟的。

参考链接

  • iptables(8) — Linux manual page
  • iptables-extensions(8) — Linux manual page
  • Iptables Tutorial 1.2.2
  • Iptables packet flow (and various others bits and bobs)
  • 终端应用安全之网络流量分析

版权声明: 自由转载-非商用-非衍生-保持署名 (CC 4.0 BY-SA)
原文地址: https://evilpan.com/2023/01/30/android-iptables/
微信订阅: 『有价值炮灰』
TO BE CONTINUED.


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软考高级系统架构师背诵要点---质量属性与架构评估

质量属性与架构评估 质量属性: 1.性能:指系统的响应能力,即要经过多长时间才能对某个事件做出响应,或者在某段时间内系统所能处理的事件个数 代表参数:响应时间、吞吐量 设计策略:优先级调度、资源调度…

【MyBatis】| MyBatis查询语句专题(核心知识)

目录 一&#xff1a;MyBatis查询语句专题 1. 返回Car对象 2. 返回List<Car> 3. 返回Map 4. 返回List<Map> 5. 返回Map<String,Map> 6. resultMap结果映射 7. 返回总记录条数 一&#xff1a;MyBatis查询语句专题 前期准备&#xff1a; 模块名&#xf…

为什么计算机需要操作系统?

当计算机只运行一个程序时&#xff0c;只需将所有的资源(CPU、内存、磁盘等)分配给这一个程序就行&#xff1b;当计算机同时运行2个或以上程序时&#xff0c;操作系统就需要充当一下角色&#xff1a; 资源分配器资源隔离与秩序维护者细节屏蔽者 一. 资源分配器 计算机的硬件…

Springboot整合第三方技术及整合案例

Springboot整合第三方技术一、Springboot整合Junit1、步骤2、classes属性二、整合Mybatis1、步骤2、常见问题三、整合Mybatis-plus1、步骤2、常见配置四、整合Druid1、步骤五、整合案例-数据层&#xff08;基础的CRUD&#xff09;1、创建springboot项目手工导入starter坐标2、配…

【正点原子FPGA连载】第二十六章gpio子系统简介 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Linux开发指南

1&#xff09;实验平台&#xff1a;正点原子MPSoC开发板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id692450874670 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第二十六章gpio子…

NVDLA Xilinx FPGA Mapping

Lei WangLeiWang1999要当世界第一&#xff01;78357联系我常用的链接1. 1. 硬件系统设计概述1.1. 1.1 RTL 生成1.2. 1.2 IP Package1.2.1. 1.2.1 csb2apb1.2.2. 1.2.2 关闭 Clock Gating1.2.3. 1.2.3 IP Package1.3. 1.3 Block Design1.4. 1.4 Generate Bit HDF1.5. 1.5 Sanity…

java基础一JVM之JRE、JDK、解释器、编译器详解

1.JVM、JRE和JDK区别 1.JVM&#xff08; Java Virtual Machine &#xff09;&#xff1a; Java虚拟机&#xff0c;它是整个 Java 实现跨平台的最核心的部分&#xff0c;所有的 Java 程序会首先被编译为 .class 的类文件&#xff0c;这种类文件可以在虚拟机上执行&#xff0c;…

3.10-动态规划-01背包问题

问题描述&#xff0c;给定n种物品和一个背包。物品 i 的重量是 wi &#xff0c;其价值为 vi &#xff0c;背包的容量为 c &#xff0c;问应该如何选择装入背包中的物品&#xff0c;使得装入背包的物品总价值最大&#xff1f; 写在前面 dp数组的含义--dp[i][j]表述容量为j 已经…

【计算机体系结构-03】ISA (Instruction Set Architecture) 指令集架构特性

1. 指令的类型 上一篇文章里主要介绍了几种机器模型&#xff0c;有机器模型后需要知道计算机有什么样的基本指令&#xff0c;接下来就来看看指令都有哪些类型。 [注]&#xff1a;以下指令主要为 MIPS 指令。 类型指令数据传输LD、ST、MFC1、MTC1、MFC0、MTC0计算ADD、SUB、AN…

Vue3和Vue2的slot-scope插槽用法

目录 &#x1f9e8;&#x1f9e8;&#x1f9e8;第一种插槽&#xff08;匿名插槽&#xff09; &#x1f9e8;&#x1f9e8;&#x1f9e8;第二种插槽&#xff08;具名插槽&#xff09;以及插槽简写 具名插槽的使用 &#x1f9e8;&#x1f9e8;&#x1f9e8;第三种插槽(作用域插…

使用HTTP代理后,网速反而变慢是什么原因?

如今越来越多的人利用HTTP代理开展业务&#xff0c;但在实际使用时&#xff0c;经常会有用户发现使用了HTTP代理后&#xff0c;网速非但没有变快&#xff0c;反而还更慢了。我们今天就来说说&#xff0c;这是什么原因造成的&#xff0c;从根本入手对于我们能更有利的解决问题。…

2.Spring IOC

目录 一.如何进行注册 二、如何进行注入 三、扫描注解的原理 反射文件操作 四、什么是IOC/DI&#xff1f; 五、演示使用Spring开发的案例&#xff1a;用户管理|登陆、注册 五、常见错误总结 1、注解使用Repository 2、UserController的构造方法注入&#xff1a; 3、…

【FreeRTOS】第一章:介绍

FreeRTOS是什么&#xff1f; Free和RTOS,Free就是免费的、自由的意思&#xff0c;RTOS 全称是 Real Time Operating System。中文名就是实时操作系统。可以看出FreeROTS 就是一个免费的 RTOS 类系统。这里要注意&#xff0c;RTOS 不是指某一个确定的系统&#xff0c;而是指一类…

联想电脑安装ubuntu18.04双系统超详细教程(23年最新教程,99%成功率)

文章目录前言电脑配置制作系统盘安装ubuntu系统更新显卡驱动安装wifi驱动完成前言 ubtuntu的长期支持版本现在应该已经出道21.04版本了&#xff0c;如果你对于版本没有要求的话&#xff0c;建议直接安装最新版ubuntu&#xff0c;因为新版的系统驱动都会进行更新&#xff0c;也…

自学 Java 怎么入门?

玩Java多年的老司机带你上车全面系统学习Java&#xff0c;并且还能教你如何学习才能在今年拿到一份不错的offer。 说到系统全面&#xff0c;就是以目前绝大部分公司招聘要求的知识内容为基准&#xff0c;毕竟我们学习Java都是为了高薪工作&#xff0c;《史记》中说”天下熙熙皆…

2.【SpringBoot源码】SpringBoot核心启动流程

目录 一、简介 二、创建SpringApplication对象 1)、推导出当前启动的项目的类型 2)、设置Initializer初始化器 3)、初始化Listener监听器 4)、反推出main方法所在的Class对象 三、运行SpringApplication#run(java.lang.String...)方法 1)、获取运行监听器 2)、发布…

unity使用对象池实现冲锋留下的残影效果

目录 效果展示 实现思路 残影代码 对象池代码 控制冲刺产生残影 CD冷却图标 效果展示 实现思路 对象池&#xff0c;有想要用的物体时可以从池子里取&#xff0c;用完再放回去。 因为在生成残影再销毁&#xff0c;这个过程中创建和销毁都需要耗费大量资源&#xff0c;因此…

shell 条件测试详解

目录 shell条件测试 一&#xff0c;条件测试的基本语法 1&#xff0c;test 2&#xff0c;[ ] 3&#xff0c;[[ ]] 二&#xff0c;文件测试表达式 1&#xff0c;判断目录是否存在&#xff1a; 2&#xff0c;判断文件file1是否有写的权限&#xff0c;结果为有 3&#xf…

重学MySQL基础(一)

文章目录重学MySQL基础&#xff08;一&#xff09;MySQL 连接管理MySQL字符编码InnoDB 记录存储结构InnoDB 表的主键生成策略&#xff1a;InnoDB 数据页结构页目录页的效验和索引事务报错记录在MySQL中创建函数时出现这种错误恶补SQL语句SQL中的条件语句SQL中的字符串函数SQL中…

python调用go语言踩坑记录

目录 基本操作 1 在go文件中加注释&#xff0c;设置为导出方法,导出C依赖 2 导出so文件&#xff08;mac或者linux下只需要so&#xff09; 3 进行调用 报错记录 踩坑1 关于结构体 2 cannot use (_Cfunc_CString)("12345") (value of type *_Ctype_char) as ty…