framework层和native层实现联网控制(iptable方式)

本文介绍了一种在没有Root权限的情况下实现控制应用程序联网功能的方法。通过利用系统的NetworkManagementService,作者实现了针对特定应用的数据流量控制。文章详细介绍了如何在不使用Root权限的情况下,通过修改系统服务来实现这一功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近工作中,需要开发一个功能----联网控制,这个功能其实用过root的安卓机应该都知道,禁止某个应用连接移动网络或者wifi。

root后,通过su去执行iptable的命令就可以根据uid去控制应用联网权限

但是由于公司是做手机系统开发,手机生产出来不允许带有root权限,所以我们完成这个功能也是不可以使用root权限去实现的。

由于第一次做这种功能,刚开始我居然天真的以为系统中带有这种控制权限的接口,然后只有个Internet权限,无法区分数据流量和wifi。

嗯,直接上最终实现的方式。

当时发现手机上有个功能是限制应用后台数据流量,该功能如其所述就是限制应用在后台状态下无法使用流量。通过代码追溯,找到其调用到的是一个 NetworkManagementService.java 这个Service,方法就是下面这个,里面的mConnector就是用来封装发送命令的类。有兴趣的可以自己去看一下 ---> NativeDaemonConnector.java

 

    @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();
            }
        }
    }

 

通过搜索addnaughtyapps这个关键字,在 CommandListener.cpp 这个类中找到了解析这个命令的地方,

   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;
    }

最终在BandwidthController.cpp这个类中执行操作iptable的命令,

Ok,既然这个Service拥有直接执行iptable的权限,那么我们就直接在里面添加我们需要的方法不就OK了吗。

 

因此,

1. 在CommandListener.cpp 中加入过滤关键字的判断,

2. 在NetworkManagementService.java中加入接口去发送命令,

3. 最终实现在BandwidthController.cpp 中进行。

第三步主要就是iptable的操作了,如何使用网上很多,不过当时我还真是看了好久才弄懂iptable的操作......用到的主要就是 -I 和 -D 命令。

其实比起这些,我更好奇netd 进程是如何拥有执行root命令的权限的。等有空了一定要研究下。

目前只知道在init.rc中可以配置以root权限去启动service。

 

转载于:https://www.cnblogs.com/oscar1011/p/5243877.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值