ip6tables中nflog的使用

来源:互联网 发布:python 图像卷积 编辑:程序博客网 时间:2024/05/18 00:01
一、前言
    iptables中有个非常有用的功能:log。通过log我们可以在内核特定位置抓取我们想要的数据包,之后由用户层的程序接收数据包的log并做相应处理。iptables中的log target主要有以下三种:
    1、log
    log target会把匹配到的数据包的部分信息输出到dmesg和syslogd中,之后用户可以直接用dmesg或者到log文件中查看,属于比较简单的log方式。这种方式至多记录数据包的头部信息。
    2、ulog
    ulog target会把匹配的数据包以netlink广播的形式广播到制定netlink组。用户可以自己编写neilink接收程序或者使用ulogd软件接收数据包。ulog功能要比log强大的多,可以获取数据包任意范围的数据。具体的ulog使用可以参见我写的另一篇文章:http://blog.csdn.net/l1902090/article/details/25911877
    3、nflog
    其实对于抓取数据包来讲,ulog已经够用了,但是可惜的是ip6tables(iptables的ipv6版本)不支持ulog,而仅仅支持nflog,所以要抓取ipv6数据包就只能用nflog了。nflog比ulog功能要更加强大,ulog有的功能nflog全都有。下面就详细介绍下如何利用nflog抓取ipv6数据包。
二、ip6tables中nflog target的使用
    要想抓取数据包,最先要做的就是添加iptables规则。例如:
        ip6tables -A INPUT -p TCP --dport 22 -j NFLOG --nflog-group 2 --nflog-prefix "test" --nflog-range 100
    上面的规则实现在INPUT链中将所有tcp协议端口号为22的数据包的前100字节发送到组号为2的netlink组中,prefix "test" 则是指为log添加“test”前缀,以帮助我们分析。
三、nflog用户层接收程序的编写
    添加完规则后,iptables就会不停地将符合规则的数据包发送到netlink组了。但是我们还需要一个用户层程序来接收数据包。
    编写nflog接收程序最简单的方式就是使用libnetfilter_log库,这个库中封装了很多简单易用的函数供我们使用。如果你还没有这个库,可以直接使用yum install安装。下面通过一个简单的例子介绍nflog程序的编写:
//这个头文件包含了libnetfilter_log需要的宏和函数定义
#include <libnetfilter_log/libnetfilter_log.h>
//首先是三个非常重要的数据结构
static int lb_nflog_fd;
static struct nflog_handle *handle;
static struct nflog_g_handle *group_handle;
//然后是nflog的初始化
handle = nflog_open();//打开一个nflog
nflog_bind_pf(handle,AF_INET6);//绑定地址族
group_handle = nflog_bind_group(handle, group);//绑定netlink组
nflog_set_mode(group_handle, NFULNL_COPY_PACKET, LOG_CP_RANGE) ;//设置拷贝的数据包范围
nflog_set_qthresh(group_handle,1); //设置数据包缓存数量,即内核会凑齐这个数量的数据包后再讲数据包发送到用户层程序
nflog_callback_register(group_handle, &handle_packet, NULL); //设置回调函数,当收到数据包后会直接调用handle_packet函数对数据包进行处理,如果一次接收了多条数据包log,那么回调函数会被调用多次
lb_nflog_fd = nflog_fd(handle);//获取接收nflog的文件描述符
//然后是nflog的接收
 char buf[MAX_MSG_SIZE];//设置接收缓冲区
 res = recv(lb_nflog_fd, buf, sizeof(buf), 0);//接收一组数据包,数据存储在buf中,返回接收到的数据长度
 nflog_handle_packet(handle, buf, res);// 由回调函数处理这组数据包
//回调函数的编写
static int
handle_packet(struct nflog_g_handle *gh, struct nfgenmsg *nfmsg,struct nflog_data *nfa, void *data)
//注意上边的函数定义是定死的
{
nflog_get_nfmark(nfa);//获取数据包的元数据,这里是mark值,还能获取时间戳、接口等信息,在此不再敖述,感兴趣的可以自己去看头文件
char *payload;
nflog_get_payload(nfa, &payload);//获取数据包的载荷,也就是真正的IP数据包了
//获取的载荷指针存储在payload,在这之后我们就可以通过payload指针对数据包进行分析了。例如:struct //ip6_hdr *ip6h=(struct ip6_hdr *)payload;获取ipv6头
……
}
四、总结
    可以看到,iptables中nflog使用的难点在于接收程序的编写,但是通过libnetfilter_log库编写这个接收程序也不难。

0 0