您的位置:首页 > 移动开发 > Android开发

Android防火墙功能实现与原理分析

2017-01-16 16:05 2176 查看
针对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;
}


流程结构:



如果平台没有提供这些接口,请查看Android应用网络限制功能实现,自己添加代码实现。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: