文章目录
mac_filter
功能简介
通过内核模块的方式向netfilter框架注册钩子函数,由于mac在ip层以下,常规的做法是在二层设备进行mac地址过滤的(比如交换机),这里我们在ip层分析mac层数据,达到过滤效果。
网络接口层(MAC)
网络接口层在发送端将上层的IP数据报封装成帧后发送到网络上;数据帧通过网络到达接收端时,该结点的网络接口层对数据帧拆封,并检查帧中包含的MAC地址。如果该地址就是本机的MAC地址或者是广播地址,则上传到网络层,否则丢弃该帧。
简单点讲就是mac层,通常我们称之为二层,比如交换机就属于二层设备,而路由器属于三层设备(ip路由)。
netfilter注册钩子函数
这里我们将hooknum设置为NF_INET_FORWARD
static struct nf_hook_ops mac_filter_ops[] __read_mostly = {
{
.hook = mac_filter_hook,
.pf = PF_INET,
.hooknum = NF_INET_FORWARD,
.priority = NF_IP_PRI_FILTER + 1,
},
};
static int __init mac_filter_init(void)
{
printk("mac filter....init\n");
nf_register_net_hooks(&init_net, mac_filter_ops, ARRAY_SIZE(mac_filter_ops));
return 0;
}
mac过滤钩子函数分析
源码
static u_int32_t mac_filter_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{
u_int8_t smac[ETH_ALEN] = {0};
struct ethhdr *ethhdr = NULL;
u_int8_t filter_mac_buf[32] = "00:0C:29:F1:34:8F";
u_int8_t mac_buf[32] = {0};
ethhdr = eth_hdr(skb);
if (!ethhdr)
{
return NF_ACCEPT;
}
memcpy(smac, ethhdr->h_source, ETH_ALEN);
if (!skb->dev){
return NF_ACCEPT;
}
printk("dev=%s, source mac = %02X:%02X:%02X:%02X:%02X:%02X\n",
skb->dev->name, smac[0], smac[1], smac[2], smac[3], smac[4], smac[5]);
if (0== memcmp(skb->dev->name, "br", 2)){
sprintf(mac_buf, "%02X:%02X:%02X:%02X:%02X:%02X", smac[0], smac[1], smac[2], smac[3], smac[4], smac[5]);
if (0 == strcmp(mac_buf, filter_mac_buf)){
printk("----drop dev=%s, source mac = %02X:%02X:%02X:%02X:%02X:%02X\n",
skb->dev->name, smac[0], smac[1], smac[2], smac[3], smac[4], smac[5]);
return NF_DROP;
}
}
return NF_ACCEPT;
}
分析
- 获取以太网头部信息ethhdr
虽然netfilter hook已经处于ip层,但skb保存了所有头部信息,可以通过指针偏移获取到以太网头部,从而获取到源mac地址 - 判断数据的方向
这里只对lan侧设备mac地址进行匹配,也就是从桥接口上来的数据才进行分析
编译运行
参考前面章节
insmod mac_filter.ko
测试结果
root@OpenWrt:/fros# insmod mac_filter.ko
root@OpenWrt:/fros# <4>[38235.271118] mac filter....init
root@OpenWrt:/fros# <4>[38241.873151] dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38241.876006] ----drop dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38242.896581] dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38242.899173] ----drop dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38245.374032] dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38245.376519] ----drop dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38246.978437] dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38246.979705] ----drop dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38248.264021] dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38248.265541] ----drop dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38249.425204] dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38249.426521] ----drop dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38250.592095] dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38250.593375] ----drop dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38251.827786] dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38251.829108] ----drop dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38252.874176] dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38252.876592] ----drop dev=br-lan, source mac = 00:0C:29:F1:34:8F
<4>[38253.905311] dev=br-lan, source mac = 00:0C:29:F1:34:8F
作者简介
OpenWrt应用过滤插件作者(应用过滤用于控制app联网,可以过滤游戏、视频、聊天等几百款app)
从事嵌入式Linux开发近10年,主要负责路由器网通产品研发,精通OpenWrt系统,包括luci、消息机制、内核模块等。擅长模块:路由器上网行为管理、智能流控、上网认证、防火墙、虚拟服务器、多wan负载均衡等
开源作品地址:
https://github.com/destan19/OpenAppFilter
源码和文档
关注微信公众号可以获取更多技术文档、固件、源码等
微信扫码关注: