如何禁止某个应用联网
DESCRIPTION]
JB5开始已经default有这部分代码,只需要参照该FAQ后面的使用说明和方法调用即可。
JB5之前的版本,可以按照下面完整的solution进行操作
[SOLUTION]
1.NetworkManagementService.java
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();
}
}
/**
* @internal Configure firewall rule by uid and chain
* @hide
*/
public void clearFirewallChain(String chain) {
enforceSystemUid();
try {
mConnector.execute("firewall", "clear_fw_chain", chain);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
}
2)INetworkManagementService.aidl中添加
void setFirewallUidChainRule(int uid, int networkType, boolean allow);
2.CommandListener.cpp中
1)最后一个类FirewallCmd的runCommand方法的
cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown 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]);
FirewallChainRule chain = parseChain(argv[3]);
FirewallRule rule = parseRule(argv[4]);
int res = sFirewallCtrl->setUidFwRule(uid, chain, rule);
return sendGenericOkFail(cli, res);
}
if (!strcmp(argv[1], "clear_fw_chain")) {
if (argc != 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
"Usage: firewall clear_fw_chain <chain>", false);
return 0;
}
const char* chain = argv[2];
int res = sFirewallCtrl->clearFwChain(chain);
return sendGenericOkFail(cli, res);
}
2)以下两个数组改成如下;
static const char* FILTER_INPUT[] = {
// Bandwidth should always be early in input chain, to make sure we
// correctly count incoming traffic against data plan.
BandwidthController::LOCAL_INPUT,
//APU: Support enhanced firewall @{
FirewallController::FIREWALL,
///@}
FirewallController::LOCAL_INPUT,
NULL,
};
static const char* FILTER_OUTPUT[] = {
OEM_IPTABLES_FILTER_OUTPUT,
// APU: Support enhanced firewall @{
FirewallController::FIREWALL,
///@}
FirewallController::LOCAL_OUTPUT,
BandwidthController::LOCAL_OUTPUT,
NULL,
};
3) 添加下面这个数组
static const char* FILTER_FIREWALL[] = {
FirewallController::FIREWALL_MOBILE,
FirewallController::FIREWALL_WIFI,
NULL,
};
4) CommandListener.cpp的构造函数CommandListener::CommandListener() :的
createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING);
createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
// Let each module setup their child chains
setupOemIptablesHook();
后添加
createChildChains(V4V6, "filter", "firewall", FILTER_FIREWALL);
5)CommandListener.cpp中添加函数parseChain
FirewallChainRule CommandListener::FirewallCmd::parseChain(const char* arg) {
if (!strcmp(arg, "mobile")) {
return MOBILE;
} else {
return WIFI;
}
}
6)CommandListener.h中parseRule后添加
static FirewallChainRule parseChain(const char* arg);
3.FirewallController.cpp里
1)加上以下两个函数
int FirewallController::setUidFwRule(int uid, FirewallChainRule chain, FirewallRule rule) {
char uidStr[16];
//char cmdStr[128];
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;
}
int FirewallController::clearFwChain(const char* chain) {
int res = 0;
if(chain != NULL){
if(strlen(chain) > 0){
res |= execIptables(V4V6, "-F", chain, NULL);
}else{
ALOGD("Clear all chain");
res |= execIptables(V4V6, "-F", NULL);
}
}else{
ALOGE("Chain is NULL");
}
return res;
}
2).FirewallController.cpp文件里面添加
const char* FirewallController::FIREWALL = "firewall";
const char* FirewallController::FIREWALL_MOBILE = "mobile";
const char* FirewallController::FIREWALL_WIFI = "wifi";
3).FirewallController.cpp文件下面这个方法改成如下;
int FirewallController::setupIptablesHooks(void) {
// mtk03594: Support enhanced 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);
//@}
return 0;
}
4.FirewallController.h里
加上以下两个函数定义
enum FirewallChainRule { MOBILE, WIFI };
int setUidFwRule(int, FirewallChainRule, FirewallRule);
int clearFwChain(const char* chain);
static const char* FIREWALL;
static const char* FIREWALL_MOBILE;
static const char* FIREWALL_WIFI;
JB5开始的版本可以从此开始进行修改:
完成以上代码添加后,可以在相应的APK里采用以下步骤使用添加的这些接口:
1.在相关的文件里import并且定义及获得NetworkManagementService
import android.os.INetworkManagementService;
private INetworkManagementService mNetworkService;
mNetworkService = INetworkManagementService.Stub.asInterface(
ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
2.调用mNetworkService.setFirewallUidChainRule or mNetworkService.clearFirewallChain设置和清空相应的APP的限制即可.
PS:1.每次重新开机,其Iptable都会被清空,如果下次重新开机时,需要重新下一遍command
2.setFirewallUidChainRule这个方法,针对同一个AP其allow和deny要成对出现
如果是要禁止掉某个APP访问网络的话,应该是要下allow,而不是下deny,deny是不禁止,allow是允许禁止
clearFirewallChain是重置规则,一般在APK reset的时候使用,它里面传的参数可以为wifi 或者mobile