Android系统中iptables的应用(二)BandwidthController

来源:互联网 发布:我的淘宝店铺怎么注销 编辑:程序博客网 时间:2024/05/21 08:10
个人邮箱:xiaokeweng@gmail.com  欢迎大家直接发邮件给我共同交流学习
      BandwidthController字面意思是带宽控制,实际模块实现的是监控系统数据流量使用情况的,主要分为流量阈值提醒(alert),流量使用上限(limite),限制app后台流量等。因android系统演进,最初设计的命令和相关功能已经不再使用,所以,如下是在android5.0系统中,据framework层保留在用的API,得出全部在用的bandwidth相关Netd cmd
bandwidth       enable|disableremoveiquota|riq<iface>setiquota|sq<interface><bytes>addnaughtyapps|ana<appUid...>removenaughtyapps|rna<appUid...>setgolbalalert|sga<bytes>cd ..setinterfacealert|sia<iface><bytes>removeinterfacealert|ria<iface>gettetherstats|gts<iface0><iface1>
      接下来根据系统启动,到相关功能使用时code运行流程和iptables规则的改动来分析,只对相关功能的enable进行分析,相对应的disable的反向操作省略。
(1)Netd.CommanderListener初始化后
    createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT);     createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD);     createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);     sBandwidthCtrl->setupIptablesHooks();     sBandwidthCtrl->enableBandwidthControl(false); 
filter表:
  //分别创建3条子链,位置正是filter表可挂的INPUT/OUTPUT/FORWARD三条链
  -N bw_FORWARD
  -N bw_INPUT
  -N bw_OUTPUT

  //创建3条子链,costly表付费iface一般就是常规的数据流量,
  //happy_box与penalty_box规则就是针对限制app的UID的黑白名单规则,
  //happy_box已不再使用,shared这条链原本是用做各条costly_[iface]链汇总路线
 
  -N bw_costly_shared

  -N bw_happy_box
  -N bw_penalty_box

  //添加默认jump规则,保证创建的子链中的规则被遍历
  -A INPUT -j bw_INPUT
  -A FORWARD -j bw_FORWARD
  -A OUTPUT -j bw_OUTPUT
  //tracking rule没啥作用
  -A bw_INPUT -m owner --socket-exists
  -A bw_OUTPUT -m owner --socket-exists

mangle表:

  //tracking rule
  -N bw_mangle_POSTROUTING
  -A POSTROUTING -j bw_mangle_POSTROUTING
  -A bw_mangle_POSTROUTING -m owner –socket-exists

raw表:

  //tracking rule
  -N bw_raw_PREROUTING
  -A PREROUTING -j bw_raw_PREROUTING
  -A bw_raw_PREROUTING -m owner --socket-exists
(2)Framework SystemReady后
    sBandwidthCtrl->enableBandwidthControl(true);    sBandwidthCtrl->setGlobalAlert([argv]);
会在filter表新增2条规则:
-A bw_INPUT -m quota2 ! --name globalAlert  --quota 2097152
-A bw_OUTPUT -m quota2 ! --name globalAlert  --quota 2097152

   默认2M(2097152)的alert流量计数,动态记录在/proc/net/xt_quota/globalAlert中,随经过该链的的数据包增加计数递减,减到0后触发netlink事件,netd来handle并上报给framework,触发framework去pollstate并重新更新规则中的alert计数,这两条规则的意义并不是策略性,只是循环触发framework和native的相关记录func的update。
(3)开启手机的流量:
    sBandwidthCtrl->setInterfaceQuota([iface], [java.Long.MAX_value = 9223372036854775807]);                                                        
在filter表中新增加表&规则:
-N bw_costly_ccmni0
-A bw_FORWARD -o ccmni0 -j bw_costly_ccmni0
-A bw_INPUT -i ccmni0 -j bw_costly_ccmni0
-A bw_OUTPUT -o ccmni0 -j bw_costly_ccmni0
-A bw_costly_ccmni0 -j bw_penalty_box
-A bw_costly_ccmni0 -m quota2 ! --name ccmni0  --quota 9223372036854775807  -j REJECT --reject-with icmp-port-unreachable

    以上新增加的规则实现了,经过ccmni0的数据统计,要经过链bw_penalty_box ,为实现黑名单的功能铺垫经过ccmni0的数据超过 9223372036854775807,将会直接reject掉数通过该链的所有据包。这个计数记录在/proc/net/xt_quota/ccmni0中,是int64最大值,很难到达,而且计数会一直被framework来更新回2的64方,所以不用担心reject被触发。
(4)在setting设置界面开启流量超值提醒(alert):
    sBandwidthCtrl->setGlobalAlert([argv]);
在filter表中新增加规则:
-A bw_INPUT -m quota2 ! --name globalAlert  --quota 131072
-A bw_OUTPUT -m quota2 ! --name globalAlert  --quota 131072

   只是更改了globalAlert的数值,从默认的2M改为经过逻辑计算后的数值,以setting中选择的值为输入,经过如下framework中的逻辑MathUtils.constrain(setting_val/1000,128KB,2MB)转换后,写入globalAlert中。例如设置20M超值提醒,globalAlert设置为128K,设置1G提醒,globalAlert设为1M。计算的逻辑是设置恰当的阈值节点触发framework和native中相关记录的循环update。在update的过程中framework会去比较setting中设置的流量阈值和当前流量使用值(记录在/proc/net/xt_qtaguid下)
(5)在setting设置界面开启流量超值提醒(limite):
    sBandwidthCtrl->setInterfaceQuota([iface], argv));
在filter表中新增加规则:
-A bw_costly_ccmni1 -m quota2 ! --name ccmni1  --quota 25694376  -j REJECT --reject-with icmp-port-unreachable
                                                        
    加入流量上限规则,本例中设置25M上限,超过后流量不可以使用,任何经过该链的数据包都会被reject掉,具体是将封包protocal改为icmp的port-unreachable并返回给发送端。
(6)在setting中禁用个别应用的后台流量(naughtapps):
        sBandwidthCtrl->addNaughtyApps([appUids]...);
在filter表中新增加规则:
    -A bw_penalty_box -m owner --uid-owner 10023 -j REJECT --reject-with icmp-port-unreachable

      这里针对一个或者多个UID参数来禁用个别应用的后台数据使用,关于所有应用的UID信息可以在package.xml中查:/data/system/packages.xml,注意,以上这条规则是禁用全部由UID=10023数据流量请求,那么关于应用是否处于foreground/background是由framework进行判断的,也就是当应用处于foreground的时候,这条规则会被remove掉,不用担心应用无法使用流量。
关于android的扩展match功能可以quota2的帮助文档,参考如下手册:
$ adb shell iptables -m -quota2 -h
quota match options:
    --grow           provide an increasing counter
    --no-change      never change counter/quota value for matching packets
    --name name      name for the file in sysfs
[!] --quota quota    initial quota (bytes or packets)
    --packets        count packets instead of bytes

$ adb shell iptables -m owner -h
owner match options:
[!] --uid-owner userid[-userid]      Match local UID
[!] --gid-owner groupid[-groupid]    Match local GID
[!] --socket-exists                  Match if socket exists
0 0
原创粉丝点击