linux下使用iptables ulog+netlink在内核中抓取特定数据包
来源:互联网 发布:阿里云服务器能干嘛 编辑:程序博客网 时间:2024/05/16 08:22
前言
iptables有三种log记录形式,分别是log、ulog、nflog。log用于将匹配的数据包记录到系统的syslog中去,用户也可以直接通过dmesg命令查看。log命令只记录包头的一些。ulog通过netlink套接字将数据包多播到指定netlink多播组,这样任何感兴趣的进程都可以通过建立netlink套接字来接受内核中的数据包信息。ulog可以将整个数据包拷贝并发送给应用程序,当然也可以指定发送方数据包的字节数。nflog类似于ulog,但是功能更加强大。nflog不仅可以接受来自iptables的数据,还可以向iptables通过netlink套接字发送控制数据。本文重点讲ulog。
一、iptables中的ulog设定
可以使用--ulog在某个链上添加ulog规则。
例如:iptables -A INPUT -p TCP --dport 22 -j ULOG --ulog-nlgroup 2
在input链上把所有目的端口号为22的数据包发送到netlink多播组2中。
ulog还有以下几个选项:
--ulog-nlgroup:指定向哪个netlink组发送包,比如-- ulog-nlgroup 5。一个有32个netlink组,它们被简单地编号位1-32。默认值是1。
--ulog-prefix:指定记录信息的前缀,以便于区分不同的信息。使用方法和 LOG的prefix一样,只是长度可以达到32个字符。
--ulog-cprange:指定每个包要向“ULOG在用户空间的代理”发送的字节数, 如--ulog-cprange 100,表示把整个包的前100个字节拷贝到用户空间记录下来,其 中包含了这个包头,还有一些包的引导数据。默认值是0,表示拷贝整个包,不管它有多大。
--ulog-qthreshold:告诉ULOG在向用户空间发送数据以供记录之前,要在内核里 收集的包的数量(译者注:就像集装箱),如--ulog-qthreshold 10。这表示先在 内核里积聚10个包,再把它们发送到用户空间里,它们会被看作同一个netlink的信息,只是由好几部分组 成罢了。默认值是1,这是为了向后兼容,因为以前的版本不能处理分段的信息。
二、netlink应用层程序的编写
写完iptbales规则后,还需要对应的应用层程序才能得到iptbales发来的数据包。ulogd程序可以非常方便的接受iptables发来的ulog并将数据记录在文件或者MySQL中。但是笔者更喜欢自己写程序按照自己的需求接受并分析iptables发来的数据包。
在写应用层程序之前我们首先添加iptables规则:
iptables -A INPUT -p icmp -j ULOG --ulog-nlgroup 6 --ulog-prefix "ulog-test" --ulog-cprange 100
这条规则会将所有发送到本机的icmp数据包多播到netlink组6。下面开始写程序:
首先要创建一个netlink套接字:
int sockaddr_nl_len=sizeof(struct sockaddr_nl); struct sockaddr_nl local; //创建netlink地址结构体,该结构体在linux/netlink.h中 struct sockaddr_nl kpeer; int nf_sock=socket(AF_NETLINK, SOCK_RAW, NETLINK_NFLOG); if(nf_sock<0){ perror("nf_sock create error:"); return -1; } memset(&kpeer, 0, sizeof(kpeer)); memset(&local, 0, sizeof(local)); local.nl_family = AF_NETLINK; local.nl_pid = getpid(); local.nl_groups = 6;//这里填上之前iptables规则中写的组号
之后绑定套接字:
if(bind(nf_sock, (struct sockaddr *)&local, sizeof(local)) != 0){ perror("nf_sock bind() error:"); return -1; }
需要注意的是因为默认情况下用户层netlink只允许监听组号为1的组,所以这里还需要设置套接字选项使得我们的套接字可以监听组号为6的netlink组。
int group=6; setsockopt(nf_sock,270,NETLINK_ADD_MEMBERSHIP, &group, sizeof(group));
设置为套接字后就可以接受数据了:
ret = recvfrom(nf_sock, buf, 2048,0, (struct sockaddr*)&kpeer, &sockaddr_nl_len); if(!ret){ perror("recv form kerner:"); exit(-1); }
iptables发送的netlink数据包有两个包头,分别是nlmsghdr和ulog_packet_msg_t,要解析iptables的ulog数据包首先要分析这两个包头。
任何netlink数据都会有一个nlmsghdr头,该数据结构在linux/netlink.h中定义,感兴趣的可以自己去看头文件:
struct nlmsghdr *nlmh; 将nlmh指针指向数据缓存,这样可以读取nlmsghdr头的内容 nlmh=(struct nlmsghdr *)buf; printf("**************recv %d msg:\n nlmsg_len:%d,nlmsg_type:%d \n",ret,nlmh->nlmsg_len,nlmh->nlmsg_type); 接着是由iptables专门为ulog定义的ulog_packet_msg_t结构包头,该结构在<linux/netfilter_ipv4/ipt_ULOG.h>中定义<span style="font-family: 微软雅黑; font-size: 14px;">(注意:如果提示找不到宏IFNAMSIZ,则可以添加包含头文件<linux/netdevice.h>)</span>: nlmh++; //跳过nlmh包头,直接定位到下一个包头即ulog_packet_msg_t包头 ulog_packet_msg_t * ulog_msg; ulog_msg=(ulog_packet_msg_t *)nlmh; //将ulog_msg指针指向ulog_packet_msg_t包头在数据包缓存中的位置 printf("mark:%d,timestamp_sec:%ld,prefix:%s\n",ulog_msg->mark,ulog_msg->timestamp_sec,ulog_msg->prefix); //timestamp代表时间戳,prefix则是之前在规则中写的前缀
ulog包头中的payload指针指向我们真正要抓取到的IP数据包。可以通过以下代码得到ip包的包头,剩下的就是常规的ip数据包分析了,如果对ip数据包分析感兴趣的人可以参看我的另一篇博文http://blog.csdn.net/l1902090/article/details/25913351:
struct iphdr *iph=(struct iphdr *)ulog_msg->payload; struct in_addr saddr; saddr.s_addr=iph->saddr; printf("saddr:%s,ihl:%d\n",inet_ntoa(saddr),iph->ihl); printf("protocol:"); switch(iph->protocol) { case IPPROTO_TCP:printf("TCP\n");break; case IPPROTO_UDP:printf("UDP\n");break; case IPPROTO_ICMP:printf("ICMP\n");break; default:printf("unknown protocol\n"); } if(iph->protocol==IPPROTO_TCP||iph->protocol==IPPROTO_UDP) { struct tcphdr *tcph; tcph=(struct tcphdr *)((void *)iph+4*(iph->ihl)); printf("dest port:%d,source port:%d\n",ntohs(tcph->dest),tcph->source); }
0 0
- linux下使用iptables ulog+netlink在内核中抓取特定数据包
- iptables中ULOG和NFLOG实现分析
- iptables中ULOG和NFLOG实现分析
- 在2.6.24及以后版本的Linux内核中使用netlink
- Linux内核中netlink协议族的实现(下)
- linux中如何抓取数据包
- Linux-3.2.0.24中内核的Netlink测试使用
- 应用程序使用RAW socket从内核中抓取指定协议的数据包流程分析;
- Linux使用tcpdump抓取网络数据包示例
- Linux使用tcpdump抓取网络数据包示例
- Linux使用tcpdump抓取网络数据包示例
- Linux使用tcpdump抓取网络数据包示例
- Linux使用tcpdump抓取网络数据包示例
- Linux使用tcpdump抓取网络数据包示例
- Linux下通过iptables抓取tcp连接
- Android中使用Tcpdump抓取网络数据包
- Android中使用tcpdump抓取网络数据包
- 在 Linux 下用户空间与内核空间数据交换的方式 --- Netlink技术
- Android作为客户端,PC作为服务端:实现网络通信
- 【MongoDB】1、MongoDB for Java
- 栈的基本操作——2,8,16进制的入栈(头文件)
- 黑马程序员_整个文件夹复制
- apk的包名为AndroidManifest.xml文件中的package设置的名字
- linux下使用iptables ulog+netlink在内核中抓取特定数据包
- Android中LinearLayout、RelativeLayout、TableLayout、AbsoluteLayout容器的使用
- PAT 1010. 一元多项式求导
- objective-c和多继承
- python3自动爬笑话
- 2014UC笔试(广州)软件开发:客户端方向(1)
- 详细介绍创建并使用一个系统调用
- [JPA] javax.persistence.EntityNotFoundException: Unable to find XXXX with id 0 问题原因
- 下载客户端向csdn博客中传代码