iptables是Linux的一个命令行工具,通过设置一些规则可以直接把指定uid或网址的数据包从ip层过滤掉,从而实现网络防火墙的功能,这部分已经比较成熟,android或厂商只是对iptables命令进行了封装,让android app可以通过iptables命令进行防火墙设置,iptables有很多复杂的功能,我们主要看看怎么设置白名单只让指定的uid app可以联网和设置黑名单让指定的uid app不能联网,我们通过代码流程来分析,代码是mtk android8.1。
root后通过adb shell iptables -L可以查看当前的规则列表,Chain INPUT,OUTPUT就是控制数据包的输入输出,没做任何设置前应该张下面这个样子,Chain OUTPUT的数据包通过Chain fw_OUTPUT控制, Chain fw_OUTPUT的规则是空的,所以当前对网络不做限制。
$ adb shell iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
bw_INPUT all -- anywhere anywhere
fw_INPUT all -- anywhere anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
oem_fwd all -- anywhere anywhere
fw_FORWARD all -- anywhere anywhere
bw_FORWARD all -- anywhere anywhere
natctrl_FORWARD all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
oem_out all -- anywhere anywhere
firewall all -- anywhere anywhere
fw_OUTPUT all -- anywhere anywhere
st_OUTPUT all -- anywhere anywhere
bw_OUTPUT all -- anywhere anywhere
Chain fw_FORWARD (1 references)
target prot opt source destination
Chain fw_INPUT (1 references)
target prot opt source destination
Chain fw_OUTPUT (1 references)
target prot opt source destination
//android app层
INetworkManagementService networkService = INetworkManagementService.Stub.asInterface(ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
public void WhiteListMode(INetworkManagementService networkService) {
FireWallUtils.setFirewallEnabled(networkService, true);//白名单模式
FireWallUtils.setFirewallUidRule(networkService, 0, 1016, 0); //重置vpn uid rule
FireWallUtils.setFirewallUidRule(networkService, 0, 1016, 1); //设置vpn uid为白名单
FireWallUtils.setFirewallUidRule(networkService, 0, 0, 0); //重置root uid rule
FireWallUtils.setFirewallUidRule(networkService, 0, 0, 1); //设置root uid为白名单
// List<String> whitelistApp = new ArrayList<>();
// whitelistApp.add("com.nuts.extremspeedup");
// PackageManager pm = mContext.getPackageManager();
// for (String pkgName : whitelistApp) {
// int uid = FireWallUtils.getUidFromPackageName(pm, pkgName);
// if (uid > 0) {
// FireWallUtils.setFirewallUidRule(networkService, 0, uid, 0); //重置 uid rule
// FireWallUtils.setFirewallUidRule(networkService, 0, uid, 1); //设置白名单
// }
// }
}
public void BlackListMode(INetworkManagementService networkService) {
FireWallUtils.setFirewallEnabled(networkService, false); //黑名单模式
List<String> whitelistApp = new ArrayList<>();
whitelistApp.add("com.iflytek.inputmethod");//com.iflytek.inputmethod
PackageManager pm = getPackageManager();
for (String pkgName : whitelistApp) {
int uid = FireWallUtils.getUidFromPackageName(pm, pkgName); //获取app的uid
if (uid > 0) {
FireWallUtils.setFirewallUidRule(networkService, 0, uid, 0); //重置 uid rule
FireWallUtils.setFirewallUidRule(networkService, 0, uid, 2); //设置uid为黑名单
}
}
}
public void DisableMobileMode(INetworkManagementService networkService) {
FireWallUtils.setFirewallEnabled(networkService, false); //黑名单模式
List<String> whitelistApp = new ArrayList<>();
whitelistApp.add("com.iflytek.inputmethod");//com.iflytek.inputmethod
PackageManager pm = getPackageManager();
for (String pkgName : whitelistApp) {
int uid = FireWallUtils.getUidFromPackageName(pm, pkgName);
if (uid > 0) {
FireWallUtils.setFirewallUidChainRule(networkService, uid, 0, false); //(networkType == 1) ? WIFI : MOBILE; , 禁止此uid连mobile
}
}
}
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.INetworkManagementService;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
public class FireWallUtils {
private static final String TAG = "FireWallUtils";
public static void setFirewallEnabled(INetworkManagementService networkService, boolean enable) {
try {