基于Netfilter的arp记录

发布于 2022-09-18 16:43:36 字数 15763 浏览 19 评论 0

测试环境
  CentOS5.3   2.6.18
测试结果:

  1. [root@nfs-client arp]# insmod arp.ko
  2. [root@nfs-client arp]# cat /proc/o_arp
  3. [root@nfs-client arp]# arp -a
  4. [root@nfs-client arp]# ping 202.114.85.31
  5. PING 202.114.85.31 (202.114.85.31) 56(84) bytes of data.
  6. 64 bytes from 202.114.85.31: icmp_seq=1 ttl=128 time=3.35 ms
  7. --- 202.114.85.31 ping statistics ---
  8. 1 packets transmitted, 1 received, 0% packet loss, time 0ms
  9. rtt min/avg/max/mdev = 3.351/3.351/3.351/0.000 ms
  10. [root@nfs-client arp]# arp -a
  11. localhost (192.168.238.2) at 00:50:56:FA:70:2A [ether] on eth0
  12. [root@nfs-client arp]# cat /proc/o_arp
  13. 192.168.238.2 192.168.238.180 ARPOP_REPLY IN
  14. 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中

  1.       #define NF_ARP                0
  2.      /* ARP Hooks */
  3.     #define NF_ARP_IN        0
  4.     #define NF_ARP_OUT        1
  5.     #define NF_ARP_FORWARD        2
  6.     #define NF_ARP_NUMHOOKS        3
  7.   

复制代码

  NF_ARP_IN和NF_ARP_OUT不用说,NF_ARP_FORWARD可能是arp代理之类的吧,我也不是很清楚 ,知道这个了,就可以写钩子了

  1. static struct nf_hook_ops arp_ops[] = {
  2.         {
  3.                 .hook                = arphook_rcv,
  4.                 .owner                = THIS_MODULE,
  5.                 .pf                = NF_ARP,
  6.                 .hooknum        = NF_ARP_IN,
  7.         },
  8.         {
  9.                 .hook                = arphook_snd,
  10.                 .owner                = THIS_MODULE,
  11.                 .pf                = NF_ARP,
  12.                 .hooknum        = NF_ARP_OUT,
  13.         },
  14. };

复制代码

把所有的arp包都放在一个List里,用户空间通过/proc/o_arp来读取...

上代码

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/init.h>
  4. #include <linux/netfilter.h>
  5. #include <linux/netfilter_ipv4.h>
  6. #include <linux/netfilter_arp.h>
  7. #include <linux/if_arp.h>
  8. #include <net/arp.h>
  9. #include <linux/skbuff.h>
  10. #include <linux/ip.h>
  11. #include <linux/netdevice.h>
  12. #include <linux/if_ether.h>
  13. #include <linux/if_packet.h>
  14. #include <net/tcp.h>
  15. #include <net/udp.h>
  16. #include <net/icmp.h>
  17. #include <linux/spinlock.h>
  18. #include <linux/timer.h>
  19. #include <linux/list.h>
  20. #include <linux/jiffies.h>
  21. #include <linux/proc_fs.h>
  22. #include <linux/sched.h>
  23. MODULE_LICENSE("GPL");
  24. MODULE_AUTHOR("kenthy@163.com");
  25. #define   ARP_OUT     0
  26. #define   ARP_IN      1
  27. #define    ARP_EXIST         0
  28. #define    ARP_NOT_EXIST     1
  29.   
  30. typedef struct o_arp
  31. {
  32.         struct list_head list;
  33.         u32 dip;
  34.         u32 sip;
  35.         u16 arpop;
  36.         int type; // in or out
  37. }O_ARP;
  38. static LIST_HEAD(arplist);
  39. static spinlock_t wa_lock = SPIN_LOCK_UNLOCKED;
  40. static void ip_add(O_ARP* node)
  41. {
  42.         unsigned long flags;
  43.         
  44.   spin_lock_irqsave(&wa_lock, flags);
  45.   list_add(&node->list,&arplist);
  46.         spin_unlock_irqrestore(&wa_lock, flags);
  47. }
  48. /*return 1--exist    0---not exist
  49. * if exist then update it
  50. */
  51. static int ip_exist(u32 sip, u32 dip, int type)
  52. {
  53.   struct list_head *p,*n;
  54.         unsigned long flags;
  55.   
  56.   O_ARP* node;
  57.   int exists= ARP_NOT_EXIST;
  58.   
  59.   spin_lock_irqsave(&wa_lock, flags);
  60.         list_for_each_safe(p,n,&arplist)
  61.    {
  62.      node=list_entry(p, O_ARP, list);
  63.            if(node->sip==sip && node->dip==dip && node->type==type)
  64.       {
  65.        exists=ARP_EXIST;
  66.            break;
  67.             }
  68.          }
  69.   
  70.   spin_unlock_irqrestore(&wa_lock, flags);
  71.   return (exists);
  72. }
  73. void free_list(void)
  74. {
  75.   struct list_head *p,*n;
  76.   O_ARP *node;
  77.         unsigned long flags;
  78.   
  79.   spin_lock_irqsave(&wa_lock, flags);
  80.         list_for_each_safe(p,n,&arplist)
  81.         {
  82.     node=list_entry(p, O_ARP,list);
  83.           list_del(&(node->list));
  84.     kfree(node);
  85.          }
  86.   spin_unlock_irqrestore(&wa_lock, flags);               
  87. }       
  88.        
  89.        
  90. void skb_fun(struct sk_buff* skb, int flag)
  91. {
  92.         struct arphdr *arp;
  93.         struct net_device * dev;
  94.         unsigned char * arp_ptr;
  95.         u32 sip,dip;
  96.         unsigned short arpop;
  97.         O_ARP* node = NULL;
  98.        
  99.         dev= skb->dev;
  100.         arp = skb->nh.arph;
  101.         arp_ptr= (unsigned char *)(arp+1);
  102.         arp_ptr += dev->addr_len;
  103.         memcpy(&sip, arp_ptr, 4);
  104.         arp_ptr += 4;
  105.         arp_ptr += dev->addr_len;
  106.         memcpy(&dip, arp_ptr, 4);
  107.         arpop=ntohs(arp->ar_op);
  108.   if(ip_exist(sip, dip, ARP_IN) == ARP_NOT_EXIST)
  109.    {
  110.     node = kmalloc(sizeof(O_ARP),GFP_ATOMIC);
  111.     if(node == NULL)
  112.     {
  113.      printk("%s\n", "kmalloc node error");
  114.      return;       
  115.             }
  116.     node->sip=sip;
  117.     node->dip=dip;
  118.     node->arpop = arpop;
  119.       node->type=flag;
  120.     ip_add(node);
  121.          }
  122. }
  123.        
  124. unsigned int arphook_rcv(unsigned int hooknum,
  125.                          struct sk_buff **skb,
  126.                          const struct net_device *in,
  127.                          const struct net_device * out,
  128.                          int (*okfn)(struct sk_buff*))
  129. {
  130.         skb_fun(*skb, ARP_IN);
  131.         return NF_ACCEPT;
  132. }
  133. unsigned int arphook_snd(unsigned int hooknum,
  134.                          struct sk_buff **skb,
  135.                          const struct net_device *in,
  136.                          const struct net_device *out,
  137.                          int (*okfn)(struct sk_buff*))
  138. {
  139.         skb_fun(*skb, ARP_OUT);
  140.         return NF_ACCEPT;
  141. }
  142. static int arp_read(char *page, char **start, off_t off,int count, int *eof, void *data)
  143. {
  144.   int len = 0;
  145.   struct list_head *p,*n;
  146.   O_ARP *node;
  147.         unsigned long flags;
  148.   
  149.   spin_lock_irqsave(&wa_lock, flags);
  150.         list_for_each_safe(p,n,&arplist)
  151.         {
  152.     node=list_entry(p, O_ARP,list);
  153.           len += sprintf(page+len,NIPQUAD_FMT" "NIPQUAD_FMT" %s %s %lu\n",
  154.                        NIPQUAD(node->sip),NIPQUAD(node->dip),
  155.                        node->arpop==ARPOP_REQUEST?"ARPOP_REQUEST ":"ARPOP_REPLY",
  156.                        node->type==ARP_OUT?"OUT":"IN",
  157.                        node->time_stamp);
  158.    }
  159.          
  160.   spin_unlock_irqrestore(&wa_lock, flags);               
  161.       
  162.   if (len <= off+count) *eof = 1;
  163.   *start = page + off;
  164.   len -= off;
  165.   if (len>count) len = count;
  166.   if (len<0) len = 0;
  167.   
  168.   return len;
  169. }
  170. static struct nf_hook_ops arp_ops[] = {
  171.         {
  172.                 .hook                = arphook_rcv,
  173.                 .owner                = THIS_MODULE,
  174.                 .pf                = NF_ARP,
  175.                 .hooknum        = NF_ARP_IN,
  176.         },
  177.         {
  178.                 .hook                = arphook_snd,
  179.                 .owner                = THIS_MODULE,
  180.                 .pf                = NF_ARP,
  181.                 .hooknum        = NF_ARP_OUT,
  182.         },
  183. };
  184. static int __init init(void)
  185. {
  186.     int ret;
  187.     struct proc_dir_entry *entry;
  188.     ret = nf_register_hooks(arp_ops, ARRAY_SIZE(arp_ops));
  189.     if (ret < 0) {
  190.         printk("http detect:can't register arp_ops hook!\n");
  191.         return ret;
  192.     }
  193.   
  194.     entry = create_proc_entry("o_arp", 0444, &proc_root);
  195.     if(entry == 0)
  196.     {
  197.         printk(KERN_ERR "create_proc_entry failed!\n");
  198.         return -1;
  199.     }
  200.     entry->mode = S_IFREG | 0444;
  201.     entry->size = 0;
  202.     entry->read_proc = arp_read;
  203.     printk("insmod arp_ops module\n");
  204.     return 0;
  205. }
  206. static void __exit fini(void)
  207. {
  208.     nf_unregister_hooks(arp_ops, ARRAY_SIZE(arp_ops));
  209.     free_list();
  210.     remove_proc_entry("o_arp", &proc_root);
  211.     printk("remove arp_ops hook.\n");
  212. }
  213. module_init(init);
  214. module_exit(fini);

复制代码

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

不念旧人 2022-09-25 16:43:36

准确讲,NF_IP_XXX 这些 hook 点只能处理 L3 以上的数据
对应的用户态程序是 iptables
当然,netfilter 在 ARP、BRIDGE 上都有 hook,在不同的位置上处理不同的事物

谎言月老 2022-09-25 16:43:36

嗯,ARP的相关操作可以考虑使用二层的hook来做

北陌 2022-09-25 16:43:36

嗯,ARP的相关操作可以考虑使用二层的hook来做
Godbach 发表于 2010-01-19 00:00

    能不能说具体点,谢谢了,最好给个最简单的例子

另外楼主的代码在ubuntu9.10下无法编译通过

难如初 2022-09-25 16:43:36

iptable,ebtable,arptable各有各的用途,但原理都差不多,只是要找准其hook点,弄清其应用空间的操作,没有太大的本质差别。

生死何惧 2022-09-25 16:43:36

netfilter能够直接获得带以太包头的包吗?

十雾 2022-09-25 16:43:36

NF 是可以截获完整的数据包的,包括链路层头部

旧时模样 2022-09-25 16:43:36

另外楼主的代码在ubuntu9.10下无法编译通过

LZ 的代码是在内核 2.6.18 上编译的,确认一下你的内核版本

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文