基于Netfilter的arp记录
测试环境
CentOS5.3 2.6.18
测试结果:
- [root@nfs-client arp]# insmod arp.ko
- [root@nfs-client arp]# cat /proc/o_arp
- [root@nfs-client arp]# arp -a
- [root@nfs-client arp]# ping 202.114.85.31
- PING 202.114.85.31 (202.114.85.31) 56(84) bytes of data.
- 64 bytes from 202.114.85.31: icmp_seq=1 ttl=128 time=3.35 ms
- --- 202.114.85.31 ping statistics ---
- 1 packets transmitted, 1 received, 0% packet loss, time 0ms
- rtt min/avg/max/mdev = 3.351/3.351/3.351/0.000 ms
- [root@nfs-client arp]# arp -a
- localhost (192.168.238.2) at 00:50:56:FA:70:2A [ether] on eth0
- [root@nfs-client arp]# cat /proc/o_arp
- 192.168.238.2 192.168.238.180 ARPOP_REPLY IN
- 192.168.238.180 192.168.238.2 ARPOP_REQUEST OUT
复制代码
列分别为 sip dop 请求还是应答 进还是出(其实上面两个好像一个概念^_^)
今天看bbs,居然有人说netfilter是处理l3,l4的,不能处理L2的!!!这是肯定不对的, mac是可以处理的要不ebtable从何而来...看了下发现netfilter有专门了arp钩子... linux/netfilter_arp.h中
- #define NF_ARP 0
- /* ARP Hooks */
- #define NF_ARP_IN 0
- #define NF_ARP_OUT 1
- #define NF_ARP_FORWARD 2
- #define NF_ARP_NUMHOOKS 3
复制代码
NF_ARP_IN和NF_ARP_OUT不用说,NF_ARP_FORWARD可能是arp代理之类的吧,我也不是很清楚 ,知道这个了,就可以写钩子了
- static struct nf_hook_ops arp_ops[] = {
- {
- .hook = arphook_rcv,
- .owner = THIS_MODULE,
- .pf = NF_ARP,
- .hooknum = NF_ARP_IN,
- },
- {
- .hook = arphook_snd,
- .owner = THIS_MODULE,
- .pf = NF_ARP,
- .hooknum = NF_ARP_OUT,
- },
- };
复制代码
把所有的arp包都放在一个List里,用户空间通过/proc/o_arp来读取...
上代码
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/netfilter.h>
- #include <linux/netfilter_ipv4.h>
- #include <linux/netfilter_arp.h>
- #include <linux/if_arp.h>
- #include <net/arp.h>
- #include <linux/skbuff.h>
- #include <linux/ip.h>
- #include <linux/netdevice.h>
- #include <linux/if_ether.h>
- #include <linux/if_packet.h>
- #include <net/tcp.h>
- #include <net/udp.h>
- #include <net/icmp.h>
- #include <linux/spinlock.h>
- #include <linux/timer.h>
- #include <linux/list.h>
- #include <linux/jiffies.h>
- #include <linux/proc_fs.h>
- #include <linux/sched.h>
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("kenthy@163.com");
- #define ARP_OUT 0
- #define ARP_IN 1
- #define ARP_EXIST 0
- #define ARP_NOT_EXIST 1
- typedef struct o_arp
- {
- struct list_head list;
- u32 dip;
- u32 sip;
- u16 arpop;
- int type; // in or out
- }O_ARP;
- static LIST_HEAD(arplist);
- static spinlock_t wa_lock = SPIN_LOCK_UNLOCKED;
- static void ip_add(O_ARP* node)
- {
- unsigned long flags;
- spin_lock_irqsave(&wa_lock, flags);
- list_add(&node->list,&arplist);
- spin_unlock_irqrestore(&wa_lock, flags);
- }
- /*return 1--exist 0---not exist
- * if exist then update it
- */
- static int ip_exist(u32 sip, u32 dip, int type)
- {
- struct list_head *p,*n;
- unsigned long flags;
- O_ARP* node;
- int exists= ARP_NOT_EXIST;
- spin_lock_irqsave(&wa_lock, flags);
- list_for_each_safe(p,n,&arplist)
- {
- node=list_entry(p, O_ARP, list);
- if(node->sip==sip && node->dip==dip && node->type==type)
- {
- exists=ARP_EXIST;
- break;
- }
- }
- spin_unlock_irqrestore(&wa_lock, flags);
- return (exists);
- }
- void free_list(void)
- {
- struct list_head *p,*n;
- O_ARP *node;
- unsigned long flags;
- spin_lock_irqsave(&wa_lock, flags);
- list_for_each_safe(p,n,&arplist)
- {
- node=list_entry(p, O_ARP,list);
- list_del(&(node->list));
- kfree(node);
- }
- spin_unlock_irqrestore(&wa_lock, flags);
- }
- void skb_fun(struct sk_buff* skb, int flag)
- {
- struct arphdr *arp;
- struct net_device * dev;
- unsigned char * arp_ptr;
- u32 sip,dip;
- unsigned short arpop;
- O_ARP* node = NULL;
- dev= skb->dev;
- arp = skb->nh.arph;
- arp_ptr= (unsigned char *)(arp+1);
- arp_ptr += dev->addr_len;
- memcpy(&sip, arp_ptr, 4);
- arp_ptr += 4;
- arp_ptr += dev->addr_len;
- memcpy(&dip, arp_ptr, 4);
- arpop=ntohs(arp->ar_op);
- if(ip_exist(sip, dip, ARP_IN) == ARP_NOT_EXIST)
- {
- node = kmalloc(sizeof(O_ARP),GFP_ATOMIC);
- if(node == NULL)
- {
- printk("%s\n", "kmalloc node error");
- return;
- }
- node->sip=sip;
- node->dip=dip;
- node->arpop = arpop;
- node->type=flag;
- ip_add(node);
- }
- }
- unsigned int arphook_rcv(unsigned int hooknum,
- struct sk_buff **skb,
- const struct net_device *in,
- const struct net_device * out,
- int (*okfn)(struct sk_buff*))
- {
- skb_fun(*skb, ARP_IN);
- return NF_ACCEPT;
- }
- unsigned int arphook_snd(unsigned int hooknum,
- struct sk_buff **skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff*))
- {
- skb_fun(*skb, ARP_OUT);
- return NF_ACCEPT;
- }
- static int arp_read(char *page, char **start, off_t off,int count, int *eof, void *data)
- {
- int len = 0;
- struct list_head *p,*n;
- O_ARP *node;
- unsigned long flags;
- spin_lock_irqsave(&wa_lock, flags);
- list_for_each_safe(p,n,&arplist)
- {
- node=list_entry(p, O_ARP,list);
- len += sprintf(page+len,NIPQUAD_FMT" "NIPQUAD_FMT" %s %s %lu\n",
- NIPQUAD(node->sip),NIPQUAD(node->dip),
- node->arpop==ARPOP_REQUEST?"ARPOP_REQUEST ":"ARPOP_REPLY",
- node->type==ARP_OUT?"OUT":"IN",
- node->time_stamp);
- }
- spin_unlock_irqrestore(&wa_lock, flags);
- if (len <= off+count) *eof = 1;
- *start = page + off;
- len -= off;
- if (len>count) len = count;
- if (len<0) len = 0;
- return len;
- }
- static struct nf_hook_ops arp_ops[] = {
- {
- .hook = arphook_rcv,
- .owner = THIS_MODULE,
- .pf = NF_ARP,
- .hooknum = NF_ARP_IN,
- },
- {
- .hook = arphook_snd,
- .owner = THIS_MODULE,
- .pf = NF_ARP,
- .hooknum = NF_ARP_OUT,
- },
- };
- static int __init init(void)
- {
- int ret;
- struct proc_dir_entry *entry;
- ret = nf_register_hooks(arp_ops, ARRAY_SIZE(arp_ops));
- if (ret < 0) {
- printk("http detect:can't register arp_ops hook!\n");
- return ret;
- }
- entry = create_proc_entry("o_arp", 0444, &proc_root);
- if(entry == 0)
- {
- printk(KERN_ERR "create_proc_entry failed!\n");
- return -1;
- }
- entry->mode = S_IFREG | 0444;
- entry->size = 0;
- entry->read_proc = arp_read;
- printk("insmod arp_ops module\n");
- return 0;
- }
- static void __exit fini(void)
- {
- nf_unregister_hooks(arp_ops, ARRAY_SIZE(arp_ops));
- free_list();
- remove_proc_entry("o_arp", &proc_root);
- printk("remove arp_ops hook.\n");
- }
- module_init(init);
- module_exit(fini);
复制代码
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
准确讲,NF_IP_XXX 这些 hook 点只能处理 L3 以上的数据
对应的用户态程序是 iptables
当然,netfilter 在 ARP、BRIDGE 上都有 hook,在不同的位置上处理不同的事物
嗯,ARP的相关操作可以考虑使用二层的hook来做
能不能说具体点,谢谢了,最好给个最简单的例子
另外楼主的代码在ubuntu9.10下无法编译通过
iptable,ebtable,arptable各有各的用途,但原理都差不多,只是要找准其hook点,弄清其应用空间的操作,没有太大的本质差别。
netfilter能够直接获得带以太包头的包吗?
NF 是可以截获完整的数据包的,包括链路层头部
LZ 的代码是在内核 2.6.18 上编译的,确认一下你的内核版本