Android关于Iptable和BPF的切换

最近在做一个项目,发现修改FIREWALL_CHAIN_POWERSAVE里调用enableFirewallChainUL,却打印iptables信息时完全没有相关信息。

 

1、NetworkManagementService.java里通过setFirewallUidRules设置防火墙规则,三条现有规则如下:

FIREWALL_CHAIN_POWERSAVE:

    mNetdService.firewallReplaceUidChain("fw_powersave", true, uids)

FIREWALL_CHAIN_STANDBY:

    mNetdService.firewallReplaceUidChain("fw_standby", false, uids)

FIREWALL_CHAIN_DOZABLE:

    mNetdService.firewallReplaceUidChain("fw_dozable", true, uids)

 

2、在执行iptables -L指令时,却找不到fw_powersave、fw_standby、fw_dozable等信息,只有fw_INPUT、fw_FORWARD、fw_OUTPUT等chain。但Doze对网络的限制却是真实有效的,到底是哪里起作用了?

Android关于Iptable和BPF的切换

 

3、在跟进到netd服务时,发现setupIptablesHooks创建了这三条chain:

    res |= createChain(LOCAL_DOZABLE, getFirewallType(DOZABLE));
    res |= createChain(LOCAL_STANDBY, getFirewallType(STANDBY));
    res |= createChain(LOCAL_POWERSAVE, getFirewallType(POWERSAVE));

 

4、FirewallController.cpp里enableChildChains发现调用的是bpf,而不是传统的iptables

    if (mUseBpfOwnerMatch != BpfLevel::NONE) {
        return gCtls->trafficCtrl.toggleUidOwnerMap(chain, enable);   //在这里被bpf截胡了
    }

    std::string command = "*filter\n";
    for (const char *parent : { LOCAL_INPUT, LOCAL_OUTPUT }) {
        StringAppendF(&command, "%s %s -j %s\n", (enable ? "-A" : "-D"), parent, name);   //这里的iptable命令没有被执行
    }
    StringAppendF(&command, "COMMIT\n");

 

5、总结:Android前几个 版本就已经上了bpf要逐渐替代iptable了,bpf在这里通过hook android的代码无缝切换,虽然iptable方式仍然有效,但对于海量的规则来说,iptable越来越无力,使用bpf是必然的。

 

6、附一些关于bpf的学习链接:

https://blog.csdn.net/f2006116/article/details/89058601

https://source.android.google.cn/devices/tech/datausage/ebpf-traffic-monitor

https://lwn.net/Articles/747504/?from=timeline