nflog 是一种类似client/server的架构,需要进行nflog通信时,需要先启server。然后客户端才能发送数据给server。
server的工作
创建nfulnl_instance实体
nfulnl_recv_config--NFULNL_CFG_CMD_BIND--》instance_create
主要关注group号,这个是通信的基础,client必须通过group号和server通信
对用libnetfilter_log库里面提供了nflog_bind_group来绑定group。其他参数可见下面示例程序所示。
server示例代码如下:
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <libnetfilter_log/libnetfilter_log.h>
#include <libnfnetlink/libnfnetlink.h>
void main()
{
struct nflog_handle *h;
struct nflog_g_handle *gh;
h = nflog_open();
if(h==NULL)
{
printf("open nflog failed\n");
return;
}
if (nflog_bind_pf(h, AF_INET) < 0)
{
printf("bind nflog failed\n");
return;
}
gh = nflog_bind_group(h, 80); // bind group 80
if(gh==NULL)
{
printf("bind nflog group failed\n");
return;
}
if(nflog_set_mode(gh, NFULNL_COPY_PACKET, 0xFFFF) < 0)
{
printf("can't set packet_copy mode\n");
return;
}
if (nflog_set_qthresh(gh, 1) < 0) // set threshold =1
{
printf("NFLOG netlink queue threshold can't be set to 1\n");
return;
}
if (nflog_set_timeout(gh, 10) < 0) //set timeout = 10S
{
printf("NFLOG netlink queue timeout can't be set to 10\n");
return;
}
struct timeval timev;
timev.tv_sec = 1;
timev.tv_usec = 0;
int fd = nflog_fd(h);
if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev)) == -1) {
printf("can't set socket timeout: %s", strerror(errno));
return;
}
char buf[1024]={0};
int rv;
while (1) {
rv = recv(fd, buf, 1024, 0);
if (rv < 0) {
printf("recive data fail \n");
continue;
}
printf("recive data :%c %c %c %c %c %c %c %c %c %c!\n",
buf[0],buf[1],buf[2],buf[3],buf[4],
buf[5],buf[6],buf[7],buf[8],buf[9]);
memset(buf,0,1024);
}
}
程序编译
程序编译需要安装libnetfilter_log(以ubuntu系统为例)
apt-get install -y libnetfilter_log_dev
编译指令
gcc -o nflog nflog_test.c -lnetfilter_log
tcpdump抓包
可以通过tcpdump抓包nflog包,但是此时server程序不能启,不然group号被server占用了,tcpdump就抓不了对应group号的nflog了。
抓所有nflog:
tcpdump -i nflog -w /home/test.pcap
抓指定group号的nflog:
tcpdump -i nflog:80 -n
client的工作
内核中 通过netfilter hook收包,
创建nf_loginfo
li.type = NF_LOG_TYPE_ULOG; // 配置nf_loginfo为NFLOG
li.u.ulog.copy_len = 0;
li.u.ulog.group = 80; //group和server创建的一致
li.u.ulog.qthreshold = 10;
li.u.ulog.flags = 0;
调用nf_log_packet发送包。
nf_log_packet(net,state->pf,state->hook, skb, state->in,state->out, &li, "SESSION");
nf_log_packet最终调用用nfulnl_log_packet