目录
安卓framework只有对后台流量的限制.这里不赘述了,有兴趣的可以参考
言归正传:我们要加的防火墙 分为两种
1.允许/不允许 xx进程 使用wifi网络
2.允许/不允许 xx进程 使用移动网络
1.在netd中增加接口.
接下来要往framework走
第三方调用可以重新封装接口,或者反射,不过多赘述.
安卓framework只有对后台流量的限制.这里不赘述了,有兴趣的可以参考
https://www.jianshu.com/p/5940ba4debf3?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
原理就是根据uid设置黑白名单,名单的存放位置在:
data/system/netpolicy.xml
注意: 这里有一个很重要的概念 : uid(不多说了.不了解的自己查),安卓所有的网络策略都是根据这个来的. 所以,如果一个应用和别人共享了uid,那么你们的流量就分不开了,都会计算在一起.
言归正传:我们要加的防火墙 分为两种
1.允许/不允许 xx进程 使用wifi网络
2.允许/不允许 xx进程 使用移动网络
这里截屏华为的效果图如下:这就是我们想要的效果.
//我们在这里备注下 代码实际上执行的指令:
(全部网络)
adb shell iptables -t filter -D OUTPUT -m owner --uid-owner=10077 -j DROP(wlan0网络)
adb shell iptables -t filter -D OUTPUT -o wlan0 -m owner --uid-owner=10077 -j DROP (移动网络,这里xxx是泛指,需要查下)
adb shell iptables -t filter -D OUTPUT -o xxx -m owner --uid-owner=10077 -j DROP
代码分为几块:
1.在netd中增加接口.
在system/netd/server目录下的FirewallController.h中定义:
class FirewallController { public: . . . //addint initIptableFirewall(void);int setMobileDataUidRule(int, FirewallRule); int setWifiDataUidRule(int, FirewallRule); //add. . .
}
system/netd/server目录下的FirewallController.cpp实现:
#include <cutils/properties.h>
//add by xiaoxsen
const char* op_3g;
const char* op_wifi;
. . .
int FirewallController::initIptableFirewall(void) { int res = 0; op_3g = "ccmni+"; //网络端口op_wifi = "wlan0";//wifi网络端口 //查看网络端口的方法://1.输入adb shell //2.输入netcfg// 新建一个drop_wall链表 res |= execIptables(V4V6, "-w", "-N", "drop_wall", NULL); // 把新建的drop_wall链表添加到OUTPUT链表目录下 res |= execIptables(V4V6, "-w", "-A", "OUTPUT", "-j", "drop_wall", NULL);
}
int FirewallController::setMobileDataUidRule(int uid, FirewallRule rule) { char uidStr[16]; sprintf(uidStr, "%d", uid); const char* op; if (rule == ALLOW) { op = "-D";// 删除链表中的规则 } else { op = "-A";// 添加规则到链表 } int res = 0; res |= execIptables(V4V6, "-w", op, "drop_wall", "-o", op_3g, "-m", "owner", "--uid-owner", uidStr, "-j", "REJECT", NULL); return res;
} int FirewallController::setWifiDataUidRule(int uid, FirewallRule rule) { char uidStr[16]; sprintf(uidStr, "%d", uid); const char* op; if (rule == ALLOW) { op = "-D";// 删除链表中的规则 } else { op = "-A";// 添加规则到链表 } int res = 0; res |= execIptables(V4V6, "-w", op, "drop_wall", "-o", op_wifi, "-m", "owner", "--uid-owner", uidStr, "-j", "REJECT", NULL); return res;
}
初始化:
CommandListener::CommandListener() :FrameworkListener("netd", true) {//add sFirewallCtrl->initIptableFirewall();// 开机初始化//add .......}
在 system/netd/server目录下int CommandListener::FirewallCmd::runCommand()中添加监听:
if (!strcmp(argv[1], "set_mobile_data_uid_rule")) { if (argc != 4) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: firewall set_mobile_data_uid_rule <1000> <allow|deny>", false); return 0; } int uid = atoi(argv[2]); FirewallRule rule = parseRule(argv[3]); int res = sFirewallCtrl->setMobileDataUidRule(uid, rule); return sendGenericOkFail(cli, res); }
if (!strcmp(argv[1], "set_wifi_data_uid_rule")) { if (argc != 4) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: firewall set_wifi_data_uid_rule <1000> <allow|deny>", false); return 0; } int uid = atoi(argv[2]); FirewallRule rule = parseRule(argv[3]); int res = sFirewallCtrl->setWifiDataUidRule(uid, rule); return sendGenericOkFail(cli, res); }
至此netd部分完成.
接下来要往framework走
我们需要把我们控制网络的方法声明在
frameworks/base/core/Java/android/os/INetworkManagementService.aidl中:
interface INetworkManagementService
{
……
void setMobileDataUidRule(int uid, boolean allow);void setWifiDataUidRule(int uid, boolean allow);
……
}
在frameworks/base/services/core/java/com/android/server目录下的.java中实现我们声明的两个方法:
public void setMobileDataUidRule(int uid, boolean allow) { enforceSystemUid();//checktry { final String rule = allow ? "allow" : "deny";mConnector.execute("firewall", "set_mobile_data_uid_rule", uid, rule); } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } } public void setWifiDataUidRule(int uid, boolean allow) { enforceSystemUid(); try { final String rule = allow ? "allow" : "deny";mConnector.execute("firewall", "set_wifi_data_uid_rule", uid, rule); } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } }
最后是framework调用:
networkManagementService = INetworkManagementService.
Stub.asInterface(ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)); if (networkManagementService != null) { networkManagementService. setMobileDataUidRule (10038,true);networkManagementService. setWifiDataUidRule (10048, true); }
获取uid的方式
List<AppdataInfo> installApplictionList = new ArrayList<AppdataInfo>();
pm = mContext.getPackageManager();
List<ApplicationInfo> installedApplications = pm.getInstalledApplications(PackageManager.GET_META_DATA);for (ApplicationInfo applicationInfo : installedApplications) {if (applicationInfo != null && PackageManager.PERMISSION_GRANTED == pm.checkPermission(Manifest.permission.INTERNET,applicationInfo.packageName)) {//这样就能获取到有网络权限应用的uidint uid = applicationInfo.uid