个人邮箱:xiaokeweng@gmail.com 欢迎大家直接发邮件给我共同交流学
在学习android6.0时,发现在netd中引入了StrictController这个module,并且在运行android 6.0的设备中出现了很多StrictController相关的iptables rules如下详细学习了下关于StrictController的知识:
Chain st_OUTPUT (1 references)
target prot opt source destination
Chain st_clear_caught (2 references)
target prot opt source destination
Chain st_clear_detect (0 references)
target prot opt source destination
REJECT all -- anywhere anywhere connmark match 0x2000000/0x2000000 reject-withicmp-port-unreachable
RETURN all -- anywhere anywhere connmark match 0x1000000/0x1000000
CONNMARK tcp -- anywhere anywhere u32"0x0>>0x16&0x3c@0xc>>0x1a&0x3c@0x0&0xffff0000=0x16030000&&0x0>>0x16&0x3c@0xc>>0x1a&0x3c@0x4&0xff0000=0x10000"CONNMARK or 0x1000000
CONNMARK udp -- anywhere anywhere u32"0x0>>0x16&0x3c@0x8&0xffff0000=0x16fe0000&&0x0>>0x16&0x3c@0x14&0xff0000=0x10000"CONNMARK or 0x1000000
RETURN all -- anywhere anywhere connmark match 0x1000000/0x1000000
st_clear_caught tcp -- anywhere anywhere state ESTABLISHED u32"0x0>>0x16&0x3c@0xc>>0x1a&0x3c@0x0&0x0=0x0"
st_clear_caught udp -- anywhere anywhere
Chain st_penalty_log (0 references)
target prot opt source destination
CONNMARK all -- anywhere anywhere CONNMARK or 0x1000000
NFLOG all -- anywhere anywhere
Chain st_penalty_reject (0 references)
target prot opt source destination
CONNMARK all -- anywhere anywhere CONNMARK or 0x2000000
NFLOG all -- anywhere anywhere
REJECT all -- anywhere anywhere reject-with icmp-port-unreachable
[StrictMode 是什么]
要了解Netd/server/StrcitController,先粗略了解下什么是StrictMode:从Android 2.3(API Level 9)开始,Android提供了一个app程序性能诊断工具,它就是StrictMode,StrictMode的能力与限制包括:
1.基于线程的对磁盘读写,网络操作,以及自定义耗时操作等的监控;
2.基于VM进程的对对象泄露(Activity对象,SQLite对象,未反注册对象,未关闭对象)的监控;
3.可以检测到跨进程的耗时操作(当然必须是同步操作);
4.当前不支持在jni中发生的网络与磁盘操作。
随着Android的进化,StrictMode的功能也将越来越强大。当StrictMode检测到指定的事件发生时,它以指定的方式通知你:崩溃,弹出对话框,闪屏,logcat,dropbox。简言StrictMode是开发者对app的性能测试工具,通过在app中调用相应的API,来针对性诊断,所以app调用StrictMode只应出现在程序的开发版中。而在android6.0中StrictMode再次扩展,引入本文主题---检测app运行网络通信是否进行SSL/TLS数据加密,暂称为[non-SSL/TLSdetect]
[AOSP non-SSL/TLS detect]
如下是在android6.0中关于[non-SSL/TLSdetect]的全部扩展的改动代码,有兴趣可以了解一下,不过可能需要翻墙。涉及framework/native/sepolicy/iptable的lib,我们只重点关注netd的iptables rule那部分。
https://android-review.googlesource.com/#/q/message:18335678
Subject | Owner | Project | Updated |
Jan 17,2015 | |||
Jan 16,2015 | |||
Jan 16,2015 | |||
Jan 16,2015 | |||
Jan 16,2015 | |||
Jan 16,2015 | |||
Jan 16,2015 |
[non-SSL/TLS detect iptables rules]
涉及的module和ndc cmd如下:
netd
└── server
├── StrictController.cpp
└── StrictController.h
Cmd | Args |
strict | enable/disable |
strict | set_uid_cleartext_policy<uid><accept|log|reject> |
strictmode在android6.0中是system ready后默认enable的,就部署文首列出的全部rules,但这些strictmode链(st_clear_detect/ st_clear_detect/st_penalty_reject/ st_penalty_log/ st_clear_caught)没有接入到数据包规则匹配流程中,所以不会工作。 也许你会问,既然non-SSL/TLS strictmode还没有开始工作,为什么先把部分iptables rules设置?其实这样设计的目的是,在真正在app需要non-SSL/TLS strictmode时再建立v4v6约30几条iptables花费时间较多,影响效率。全部链布局如下图:
-N st_OUTPUT
-N st_clear_caught
-N st_clear_detect
-N st_penalty_log
-N st_penalty_reject
-A OUTPUT -j st_OUTPUT
新建st相关链,将st_OUPUT接到OUTPUT链上:
-A st_clear_detect-m connmark --mark 0x2000000/0x2000000 -j REJECT --reject-withicmp-port-unreachable
-A st_clear_detect-m connmark --mark 0x1000000/0x1000000 -j RETURN
-A st_clear_detect-p tcp -m u32 --u32"0x0>>0x16&0x3c@0xc>>0x1a&0x3c@0x0&0xffff0000=0x16030000&&0x0>>0x16&0x3c@0xc>>0x1a&0x3c@0x4&0xff0000=0x10000"-j CONNMARK --set-xmark 0x1000000/0x1000000
-A st_clear_detect-p udp -m u32 --u32"0x0>>0x16&0x3c@0x8&0xffff0000=0x16fe0000&&0x0>>0x16&0x3c@0x14&0xff0000=0x10000"-j CONNMARK --set-xmark 0x1000000/0x1000000
-A st_clear_detect-m connmark --mark 0x1000000/0x1000000 -j RETURN
-A st_clear_detect-p tcp -m state --state ESTABLISHED -m u32 --u32"0x0>>0x16&0x3c@0xc>>0x1a&0x3c@0x0&0x0=0x0"-j st_clear_caught
-A st_clear_detect-p udp -j st_clear_caught
-A st_penalty_log-j CONNMARK --set-xmark 0x1000000/0x1000000
-A st_penalty_log-j NFLOG
-A st_penalty_reject -j CONNMARK --set-xmark 0x2000000/0x2000000
-A st_penalty_reject -j NFLOG
-A st_penalty_reject -j REJECT --reject-with icmp-port-unreachable
以上规则就是[non-SSL/TLS detect]的精髓了:
-A st_clear_detect -p tcp -m u32 --u32"0x0>>0x16&0x3c@0xc>>0x1a&0x3c@0x0&0xffff0000=0x16030000&&0x0>>0x16&0x3c@0xc>>0x1a&0x3c@0x4&0xff0000=0x10000"-j CONNMARK --set-xmark 0x1000000/0x1000000
这条rule通过使用iptables的U32扩展,检索ip数据报文中tcp报文段的SSL数据段在handshake协议过程中client_hello数据被置位,并标记整条socket链接为0x1000000/0x1000000。详细分解分析:
(1)-p tcp 针对tcp报文
(2)-m u32 –u32 "0x0 >> 0x16&0x3c@0xc >>0x1a&0x3c@0x0&0xffff0000=0x16030000&&0x0 >> 0x16&0x3c@0xc>> 0x1a&0x3c@0x4&0xff0000=0x10000"
简单的讲,u32 match就是一个算式,该算式是一个由&&拼起来的多个子match的集合,每一个子match可以理解成一个标准的iptables match比如-p udp,--dport 1194之类的。每一个子match有4个运算符可以用,分别是:
& :按位与操作。该操作可以过滤出一个IP数据报中我们需要的最多四个字节。
<< :左移操作。该操作的含义和C语言一致。
>> :右移操作。同上
@ :向前推进操作。该操作允许你将匹配向前skip掉你不感兴趣的字节数
【0x0 >> 0x16&0x3c】
以上ipv4包头的0x0字节处,共4字节,32位,右移>>动0x16=22位,剩余的10位,位操作&上0x3c=00111100,得到的是ip包中ip头长度字段IHL的4倍,这里的4倍是为了后续按照IHL继续移位的便捷,IHL中记录的是ip报头长度是多少个字节,也就是Byte的4倍,参考下图:(https://tools.ietf.org/rfc/rfc791.txt)
【IHL@0xc >> 0x1a&0x3c】
将上述的IHL的4倍作为相对偏移,加上绝对偏移0xc=12,取出32位,右移0x1a=26位,剩余6位,位操作&上0x3c=00111100,得到tcp的数据偏移Data_Offset的4倍数,参考下图:(https://tools.ietf.org/rfc/rfc793.txt):
【Data_Offset@0x0&0xffff0000=0x16030000】
将上述的Data_Offset的4作为相对偏移,0x0为绝对偏移,到达tcp包含的数据部分,取前32位,位操作&上0xffff0000并判断是否=0x16030000。这里就是判断tcp报文data部分是否为SSL/TLS报文协议中的握手协议handshake(0x16),SSL_version为0x03,参考TLS的rfc(https://tools.ietf.org/rfc/rfc6101.txt)中附录A:(具体的协议规范内容不再叙述)
【&&0x0 >> 0x16&0x3c@0xc >>0x1a&0x3c@0x4&0xff0000=0x10000】
并列的&&条件,同样0x0 >> 0x16&0x3c=IHL×4,@0xc >> 0x1a&0x3c=Data_Offset×4,接下来0x4&0xff0000=0x10000,相对偏移4字节取32位,位操作&上0xff0000判断是否=0x10000,这里检索的是SSL的握手协议中的client_hello是否置位。(https://tools.ietf.org/rfc/rfc6101.txt)
(3)-j CONNMARK --set-xmark 0x1000000/0x1000000
将该报文所在的整条连接做连接0x1000000/0x1000000。
[strictmode policy 用例]
上述的链关系和流程粗略理解是st_clear_detect链标价检测经过数据包所在链接是否SSL/TLS加密,捕获到未加密的packet定向到st_clear_caught,并根据上层的debug策略再次选路到st_penalty_log或st_penalty_reject。以reject为例子,在UID=10038的app中triger【non-SSL/TLS detect】,流程如下,经过framework (ActivityMangeràNetworkManagementService)到达netd的命令为:
“strict set_uid_cleartext_policy 10038 reject”
执行后,iptable中新增加两条规则:
-A st_OUTPUT -m owner --uid-owner 10038 -jst_clear_detect
-A st_clear_caught -m owner --uid-owner 10038 -jst_penalty_reject
最终流程如下
参考:
strict mode 简介:http://jimpai.blogspot.tw/2012/02/androidstrictmode.html
iptables中CONNMARK的使用:http://blog.chinaunix.net/uid-10167808-id-26001.html
iptables中u32扩展的使用:http://blog.csdn.net/dog250/article/details/9258607
SSL体系结构:http://www.cnblogs.com/xuanhun/archive/2012/06/23/2559607.html
SSL v3 RFC:https://tools.ietf.org/rfc/rfc6101.txt