溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

framework層和native層實(shí)現(xiàn)聯(lián)網(wǎng)控制(iptable方式)

發(fā)布時(shí)間:2020-06-17 16:32:13 來源:網(wǎng)絡(luò) 閱讀:660 作者:張立達(dá) 欄目:網(wǎng)絡(luò)安全

最近工作中,需要開發(fā)一個(gè)功能----聯(lián)網(wǎng)控制,這個(gè)功能其實(shí)用過root的安卓機(jī)應(yīng)該都知道,禁止某個(gè)應(yīng)用連接移動(dòng)網(wǎng)絡(luò)或者wifi。

root后,通過su去執(zhí)行iptable的命令就可以根據(jù)uid去控制應(yīng)用聯(lián)網(wǎng)權(quán)限

但是由于公司是做手機(jī)系統(tǒng)開發(fā),手機(jī)生產(chǎn)出來不允許帶有root權(quán)限,所以我們完成這個(gè)功能也是不可以使用root權(quán)限去實(shí)現(xiàn)的。

由于第一次做這種功能,剛開始我居然天真的以為系統(tǒng)中帶有這種控制權(quán)限的接口,然后只有個(gè)Internet權(quán)限,無法區(qū)分?jǐn)?shù)據(jù)流量和wifi。

嗯,直接上最終實(shí)現(xiàn)的方式。

當(dāng)時(shí)發(fā)現(xiàn)手機(jī)上有個(gè)功能是限制應(yīng)用后臺(tái)數(shù)據(jù)流量,該功能如其所述就是限制應(yīng)用在后臺(tái)狀態(tài)下無法使用流量。通過代碼追溯,找到其調(diào)用到的是一個(gè) NetworkManagementService.java 這個(gè)Service,方法就是下面這個(gè),里面的mConnector就是用來封裝發(fā)送命令的類。有興趣的可以自己去看一下 ---> NativeDaemonConnector.java

 

framework層和native層實(shí)現(xiàn)聯(lián)網(wǎng)控制(iptable方式)

    @Override    public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);        // silently discard when control disabled        // TODO: eventually migrate to be always enabled
        if (!mBandwidthControlEnabled) return;        synchronized (mQuotaLock) {            final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false);            if (oldRejectOnQuota == rejectOnQuotaInterfaces) {                // TODO: eventually consider throwing
                return;
            }            try {
                mConnector.execute("bandwidth",
                        rejectOnQuotaInterfaces ? "addnaughtyapps" : "removenaughtyapps", uid);                if (rejectOnQuotaInterfaces) {
                    mUidRejectOnQuota.put(uid, true);
                } else {
                    mUidRejectOnQuota.delete(uid);
                }
            } catch (NativeDaemonConnectorException e) {                throw e.rethrowAsParcelableException();
            }
        }
    }

framework層和native層實(shí)現(xiàn)聯(lián)網(wǎng)控制(iptable方式)

 

通過搜索addnaughtyapps這個(gè)關(guān)鍵字,在 CommandListener.cpp 這個(gè)類中找到了解析這個(gè)命令的地方,

framework層和native層實(shí)現(xiàn)聯(lián)網(wǎng)控制(iptable方式)

   if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {        if (argc < 3) {
            sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");            return 0;
        }        int rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2);
        sendGenericOkFail(cli, rc);        return 0;
    }

framework層和native層實(shí)現(xiàn)聯(lián)網(wǎng)控制(iptable方式)

最終在BandwidthController.cpp這個(gè)類中執(zhí)行操作iptable的命令,

Ok,既然這個(gè)Service擁有直接執(zhí)行iptable的權(quán)限,那么我們就直接在里面添加我們需要的方法不就OK了嗎。

 

因此,

1. 在CommandListener.cpp 中加入過濾關(guān)鍵字的判斷,

2. 在NetworkManagementService.java中加入接口去發(fā)送命令,

3. 最終實(shí)現(xiàn)在BandwidthController.cpp 中進(jìn)行。

第三步主要就是iptable的操作了,如何使用網(wǎng)上很多,不過當(dāng)時(shí)我還真是看了好久才弄懂iptable的操作......用到的主要就是 -I 和 -D 命令。

其實(shí)比起這些,我更好奇netd 進(jìn)程是如何擁有執(zhí)行root命令的權(quán)限的。等有空了一定要研究下。

目前只知道在init.rc中可以配置以root權(quán)限去啟動(dòng)service。


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI