Android防火墙原理分析

来源:互联网 发布:linux开机动画 编辑:程序博客网 时间:2024/06/08 01:07

针对Android手机防火墙需求,本人对android防火墙原理进行浅析,如有错误,请多多指教,谢谢。
前提:了解Android系统网络连接功能介绍,了解Netd相关知识,Android iptables常用命令

防火墙实现原理:
Framwork中NetworkManagementService通过NativeDaemonConnector的excute()方法向Netd发送命令(由socket来完成)Netd中CommandListener.cpp中持有该连接的socket进行通信,代码如下:

 public void setFirewallUidChainRule(int uid, int networkType, boolean allow) {        //enforceSystemUid();        final String MOBILE = "mobile";        final String WIFI = "wifi";        final String rule = allow ? "allow" : "deny";        final String chain = (networkType == 1) ? WIFI : MOBILE;        try {            mConnector.execute("firewall", "set_uid_fw_rule", uid, chain, rule);        } catch (NativeDaemonConnectorException e) {            throw e.rethrowAsParcelableException();        }    }

System/netd/server/Main.Cpp

int main() {/*实例化一个命令监听示例,监听Framework命令,处理完成返回结果到Framework层*/    CommandListener *cl;     if (!(nm = NetlinkManager::Instance())) {        ALOGE("Unable to create NetlinkManager");        exit(1);    };    cl = new CommandListener();    nm->setBroadcaster((SocketListener *) cl);

/开启监听内核网络事件线程/

if (nm->start()) {        ALOGE("Unable to start NetlinkManager (%s)", strerror(errno));        exit(1);    }

/cl 开启线程,监听 framework 层下发的命令,并调用相关函数处理 /

  if (cl->startListener()) {        ALOGE("Unable to start CommandListener (%s)", strerror(errno));        exit(1);    }

CommandListener.cpp

注册各种命令

CommandListener::CommandListener() :                 FrameworkListener("netd", true) {    registerCmd(new InterfaceCmd());    registerCmd(new IpFwdCmd());    registerCmd(new TetherCmd());    registerCmd(new NatCmd());    registerCmd(new ListTtysCmd());    registerCmd(new PppdCmd());    registerCmd(new SoftapCmd());    registerCmd(new BandwidthControlCmd());    registerCmd(new IdletimerControlCmd());    registerCmd(new ResolverCmd());    registerCmd(new FirewallCmd());    registerCmd(new ClatdCmd());    registerCmd(new NetworkCommand());    registerCmd(new StrictCmd());    registerCmd(new Ipv6FwdCmd());    registerCmd(new IPv6TetherCmd());    registerCmd(new ThroughputCmd());    registerCmd(new PPPOEctlCmd());    registerCmd(new NetInfoCmd());

//创建防火墙规则链

/* When enabled, DROPs all packets except those matching rules. */    sFirewallCtrl->setupIptablesHooks();

//处理framwork发下来的命令

int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,        char **argv) {    if (argc < 2) {        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);        return 0;    }   ......   if (!strcmp(argv[1], "set_uid_fw_rule")) {        if (argc != 5) {            cli->sendMsg(ResponseCode::CommandSyntaxError,                         "Usage: firewall set_uid_fw_rule <uid> <mobile|wifi> <allow|deny>",                         false);            return 0;        }        int uid = atoi(argv[2]);        FirewallChinaRule chain = parseChain(argv[3]);        FirewallRule rule = parseRule(argv[4]);        int res = sFirewallCtrl->setUidFwRule(uid, chain, rule);        return sendGenericOkFail(cli, res);    }    ......}

首先判断参数个数是否正确,匹配framework中mConnector.execute(“firewall”, “set_uid_fw_rule”, uid, chain, rule)方法。
然后解析uid和防火墙规则,在调用FirewallController的setUidFwRule()方法生成iptables规则实现防火墙功能。
初始化iptables,建立iptables规则链:

int FirewallController::setupIptablesHooks(void) {    /*********************************************************************    * mtk03594: Support tencent firewall    * mount child chain,FIREWALL_MOBILE and FIREWALL_WIFI, to FIREWALL    *********************************************************************/    int res = 0;    res |= execIptables(V4V6, "-F", FIREWALL, NULL);    res |= execIptables(V4V6, "-A", FIREWALL, "-o", "ppp+", "-j", FIREWALL_MOBILE, NULL);    res |= execIptables(V4V6, "-A", FIREWALL, "-o", "ccmni+", "-j", FIREWALL_MOBILE, NULL);    res |= execIptables(V4V6, "-A", FIREWALL, "-o", "ccemni+", "-j", FIREWALL_MOBILE, NULL);    res |= execIptables(V4V6, "-A", FIREWALL, "-o", "usb+", "-j", FIREWALL_MOBILE, NULL);    res |= execIptables(V4V6, "-A", FIREWALL, "-o", "cc2mni+", "-j", FIREWALL_MOBILE, NULL);    res |= execIptables(V4V6, "-A", FIREWALL, "-o", "wlan+", "-j", FIREWALL_WIFI, NULL);    // child chains are created but not attached, they will be attached explicitly.    FirewallType firewallType = getFirewallType(DOZABLE);    res |= createChain(LOCAL_DOZABLE, LOCAL_INPUT, firewallType);    firewallType = getFirewallType(STANDBY);    res |= createChain(LOCAL_STANDBY, LOCAL_INPUT, firewallType);    return res;}

通过uid向规则链中添加iptables规则:

int FirewallController::setUidFwRule(int uid, FirewallChinaRule chain, FirewallRule rule) {    char uidStr[16];    int res = 0;    const char* op;    const char* fwChain;    sprintf(uidStr, "%d", uid);    if (rule == ALLOW) {        op = "-I";    } else {        op = "-D";    }    if(chain == MOBILE) {        fwChain = "mobile";    }else{        fwChain = "wifi";    }    res |= execIptables(V4, op, fwChain, "-m", "owner", "--uid-owner", uidStr,            "-j", "REJECT", "--reject-with", "icmp-net-prohibited", NULL);    res |= execIptables(V6, op, fwChain, "-m", "owner", "--uid-owner", uidStr,            "-j", "REJECT", "--reject-with", "icmp6-adm-prohibited", NULL);    return res;}

流程结构:
这里写图片描述

1 0
原创粉丝点击