1.前言
在14.0的系统rom定制化开发中,在system中netd网络模块这块的产品需要中,在系统中会要求设置屏蔽ip地址之内的功能,
liunx中iptables命令也是比较重要的,接下来就来在IOemNetd这块实现屏蔽ip黑名单的的相关功能,就是在
app中只能屏蔽某个网址,就是除了这个网址,其他的都能上网,最后在framework自定义服务中实现接口调用
2. 系统限制上网系列之iptables用IOemNetd实现屏蔽ip黑名单功能的实现的核心类
system\netd\server\binder\com\android\internal\net\IOemNetd.aidl
system\netd\server\OemNetdListener.cpp
system\netd\server\OemNetdListener.h
3. 系统限制上网系列之iptables用IOemNetd实现屏蔽ip黑名单功能的实现的核心功能分析和实现
在android原生系统中,iptables是在网络过滤包模块非常重要的,Iptabels是与Linux内核集成的包过滤防火墙系统,linux和android都会包含Iptables的功能。
如果 Linux 系统连接到因特网或 LAN、服务器或连接 LAN 和因特网的代理服务器, 则Iptables有利于在 Linux 系统上更好地控制 IP 信息包过滤和防火墙配置。
netfilter/iptables的另一个重要优点是,它使用户可以完全控制防火墙配置和信息包过滤。您可以定制自己的规则来满足您的特定需求
iptables 常用命令如下:
命令 说明
-L --list <链名> 查看iptables规则列表
-A --append <链名> 在规则列表的最后增加1条规则
-I --insert <链名> 在指定的位置插入1条规则
-D --delete <链名> 从规则列表中删除1条规则
-F --flush <链名> 删除表中所有规则
-X --delete-chain <链名> 删除自定义链
“五链”是指内核中控制网络的NetFilter定义的五个规则链,分别为
PREROUTING, 路由前
INPUT, 数据包流入口
FORWARD, 转发管卡
OUTPUT, 数据包出口
POSTROUTING, 路由后
防火墙处理数据包的四种方式
ACCEPT 允许数据包通过
DROP 直接丢弃数据包,不给任何回应信息
REJECT 拒绝数据包通过,必要时会给数据发送端一个响应的信息
屏蔽ip黑名单的命令如下:
iptables -A OUTPUT -d 192.168.1.1 -j DROP
在上述的system/netd的模块中给,在上述的IOemNetd中的相关iptables的命令中,通过增加iptables的使用规则来实现屏蔽ip黑名单的相关功能
接下来就在IOemNetd中增加屏蔽ip黑名单的接口来实现功能
3.1 IOemNetd.aidl中增加屏蔽ip黑名单的接口
/** {@hide} */
interface IOemNetd {
/**
* Returns true if the service is responding.
*/
boolean isAlive();
/**
* Register oem unsolicited event listener
*
* @param listener oem unsolicited event listener to register
*/
void registerOemUnsolicitedEventListener(IOemNetdUnsolicitedEventListener listener);
+ void setBlackIpList(const ::std::string& addr);// add core
}
在system/netd下的 IOemNetd.aidl的增加屏蔽ip黑名单的接口中,通过上述的方法可以看出,在这里增加屏蔽ip黑名单的接口,
setBlackIpList(const ::std::string& addr);来实现功能,在这里framework可以通过binder通讯的方式,实现屏蔽ip黑名单的调用
,在这里framework可以通过binder通讯的方式,实现屏蔽ip黑名单的接口的调用规则来实现功能
3.2 OemNetdListener.h中增加屏蔽ip黑名单的接口
namespace com {
namespace android {
namespace internal {
namespace net {
class OemNetdListener : public BnOemNetd {
public:
using OemUnsolListenerMap = std::map<const ::android::sp<IOemNetdUnsolicitedEventListener>,
const ::android::sp<::android::IBinder::DeathRecipient>>;
OemNetdListener() = default;
~OemNetdListener() = default;
static ::android::sp<::android::IBinder> getListener();
::android::binder::Status isAlive(bool* alive) override;
::android::binder::Status registerOemUnsolicitedEventListener(
const ::android::sp<IOemNetdUnsolicitedEventListener>& listener) override;
+ ::android::binder::Status setBlackIpList(const ::std::string& addr) override;
private:
std::mutex mMutex;
std::mutex mOemUnsolicitedMutex;
::android::sp<::android::IBinder> mIBinder GUARDED_BY(mMutex);
OemUnsolListenerMap mOemUnsolListenerMap GUARDED_BY(mOemUnsolicitedMutex);
::android::sp<::android::IBinder> getIBinder() EXCLUDES(mMutex);
void registerOemUnsolicitedEventListenerInternal(
const ::android::sp<IOemNetdUnsolicitedEventListener>& listener)
EXCLUDES(mOemUnsolicitedMutex);
void unregisterOemUnsolicitedEventListenerInternal(
const ::android::sp<IOemNetdUnsolicitedEventListener>& listener)
EXCLUDES(mOemUnsolicitedMutex);
};
} // namespace net
} // namespace internal
} // namespace android
} // namespace com
#endif // NETD_SERVER_OEM_NETD_LISTENER_H
在system/netd下的 IOemNetd的增加屏蔽ip黑名单的接口的模块中,在IOemNetd.aidl的接口中增加对外调用IOemNetd的接口,而具体在OemNetdListener.cpp中具体实现IOemNetd.aidl的接口的功能的实现,接下来就需要在OemNetdListener.h中增加::android::binder::Status setBlackIpList(const ::std::string& addr) override;来定义
屏蔽ip黑名单接口,然后实现屏蔽ip黑名单功能
3.3 OemNetdListener.cpp中增加屏蔽ip黑名单的接口中
#define LOG_TAG "OemNetd"
#include "OemNetdListener.h"
namespace com {
namespace android {
namespace internal {
namespace net {
::android::sp<::android::IBinder> OemNetdListener::getListener() {
static OemNetdListener listener;
return listener.getIBinder();
}
::android::sp<::android::IBinder> OemNetdListener::getIBinder() {
std::lock_guard lock(mMutex);
if (mIBinder == nullptr) {
mIBinder = ::android::IInterface::asBinder(this);
}
return mIBinder;
}
::android::binder::Status OemNetdListener::isAlive(bool* alive) {
*alive = true;
return ::android::binder::Status::ok();
}
::android::binder::Status OemNetdListener::registerOemUnsolicitedEventListener(
const ::android::sp<IOemNetdUnsolicitedEventListener>& listener) {
registerOemUnsolicitedEventListenerInternal(listener);
listener->onRegistered();
return ::android::binder::Status::ok();
}
//add core start
::android::binder::Status OemNetdListener::setBlackIpList(const ::std::string& addr) {
ALOGD("OemNetdListener:setBlackIpList addr=%s",addr.c_str());
int res = -1;
IptablesTarget target = V4V6;
std::string command = "*filter\n";
std::stringstream ss(addr);
std::string ipAddr;
while(std::getline(ss, ipAddr, '-')) {
::android::base::StringAppendF(&command, "-A %s -d %s -j DROP\n", "OUTPUT", ipAddr.c_str());
}
::android::base::StringAppendF(&command, "-A %s -j ACCEPT\n", "OUTPUT");
::android::base::StringAppendF(&command, "COMMIT\n");
res = execIptablesRestore(target, command.c_str());
ALOGD("OemNetdListener:command=%s,res=%d",command.c_str(),res);
if(res == 0) {
return ::android::binder::Status::ok();
} else {
return ::android::binder::Status::fromServiceSpecificError(res,
::android::String8::format("OemNetdListener:setBlackIpList error: %d", res));
}
}
//add core end
在system/netd下的 IOemNetd的增加屏蔽ip黑名单的接口模块中,在IOemNetd.aidl的接口中增加对外调用IOemNetd的接口,
而具体在OemNetdListener.cpp中具体实现IOemNetd.aidl的接口的功能的实现,所以在OemNetdListener.cpp中
增加::android::binder::Status OemNetdListener::setBlackIpList(const ::std::string& addr)来具体实现屏蔽ip黑名单的功能,
所以&command拼接iptables的命令,然后调用execIptablesRestore(target, command.c_str());来
执行屏蔽ip黑名单的功能,然后可以根据返回的res值来得知执行命令的结果
3.4 在创建的自定义服务中,来调用增加屏蔽ip黑名单的功能
在上述的IOemNetd的增加屏蔽ip黑名单的接口模块中,根据iptables相关的规则,需要在native netd中添加,可以参考其他的controller中的实现。
增加接口,需要在framework的NetworkManagementService或者自定义服务中添加;也需要在native层的INetd.aidl/IOemNetd.aidl中添加,
在native为了方便区分系统自带的接口和自定义接口,统一放在IOemNetd.aidl这里添加便可以。上层通过获取netd服务,调用接口
IOemNetd.Stub.asInterface(mNetdService.getOemNetd());
得到IOemNetd的实例OemNetdListener,再调用具体接口。实现IOemNetd.aidl的iptables的相关调用具体实现如下:
//add core start
import android.os.INetworkManagementService;
import com.android.internal.net.IOemNetd;
import android.net.util.NetdService;
import android.content.pm.ApplicationInfo;
import java.net.InetAddress;
import android.content.pm.PackageManager;
private IOemNetd mIoemNetd;
try {
mIoemNetd = IOemNetd.Stub.asInterface(NetdService.getInstance().getOemNetd());
//Log.d(TAG,"mIoemNetd:"+mIoemNetd);
} catch (Exception e) {
e.printStackTrace();
}
private InetAddress[] getInetAddress(String address) {
InetAddress[] inetAddresses = null;
try {
inetAddresses = InetAddress.getAllByName(address);
} catch (UnknownHostException e) {
// e.printStackTrace();
return null;
}
return inetAddresses;
}
//add core end
在自定义服务中,实现增加屏蔽ip黑名单的接口功能中,通过创建IOemNetd mIoemNetd的实例,然后在framework中的自定义服务中,
在通过binder通讯的方式调用在IOemNetd中增加的增加的屏蔽ip黑名单的的功能,接下来来实现这个功能
//add core start
private Runnable mThreadRunnable = new Runnable() {
@Override
public void run() {
try {
InetAddress[] inetAddresses = getInetAddress("www.hupu.com");
String ipAr="";
if (inetAddresses != null) {
for (int i=0;i< inetAddresses.length;i++ ) {
InetAddress inetAddress = inetAddresses[i];
String hostAddress = inetAddress.getHostAddress();
if(i==inetAddresses.length-1){
ipAr+=hostAddress;
}else{
ipAr+=hostAddress+"-";
}
}
}
Log.d(TAG,"ipAr:"+ipAr);
if(!TextUtils.isEmpty(ipAr)){
mIoemNetd.setBlackIpList(ipAr);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
//add core end
在自定义服务中,实现增加屏蔽ip黑名单的接口中,通过创建IOemNetd mIoemNetd的实例后,就可以调用mIoemNetd.setBlackIpList(ipAr);
来实现IOemNetd中屏蔽ip黑名单的功能