如何禁止某个应用联网

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

results matching ""

    No results matching ""