使用libnetfilter_queue的简单程序不起作用
simple program using libnetfilter_queue isn't working
我想学习如何使用libnetfilter_queue。我已经编译了库提供的示例。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <linux/types.h>
#include <linux/netfilter.h> /* for NF_ACCEPT */
#include <libnetfilter_queue/libnetfilter_queue.h>
/* returns packet id */
static u_int32_t print_pkt (struct nfq_data *tb)
{
int id = 0;
struct nfqnl_msg_packet_hdr *ph;
struct nfqnl_msg_packet_hw *hwph;
u_int32_t mark,ifi;
int ret;
char *data;
ph = nfq_get_msg_packet_hdr(tb);
if (ph) {
id = ntohl(ph->packet_id);
printf("hw_protocol=0x%04x hook=%u id=%u ",
ntohs(ph->hw_protocol), ph->hook, id);
}
hwph = nfq_get_packet_hw(tb);
if (hwph) {
int i, hlen = ntohs(hwph->hw_addrlen);
printf("hw_src_addr=");
for (i = 0; i < hlen-1; i++)
printf("%02x:", hwph->hw_addr[i]);
printf("%02x ", hwph->hw_addr[hlen-1]);
}
mark = nfq_get_nfmark(tb);
if (mark)
printf("mark=%u ", mark);
ifi = nfq_get_indev(tb);
if (ifi)
printf("indev=%u ", ifi);
ifi = nfq_get_outdev(tb);
if (ifi)
printf("outdev=%u ", ifi);
ifi = nfq_get_physindev(tb);
if (ifi)
printf("physindev=%u ", ifi);
ifi = nfq_get_physoutdev(tb);
if (ifi)
printf("physoutdev=%u ", ifi);
ret = nfq_get_payload(tb, &data);
if (ret >= 0)
printf("payload_len=%d ", ret);
fputc('n', stdout);
return id;
}
static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
struct nfq_data *nfa, void *data)
{
u_int32_t id = print_pkt(nfa);
printf("entering callbackn");
return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
}
int main(int argc, char **argv)
{
struct nfq_handle *h;
struct nfq_q_handle *qh;
int fd;
int rv;
char buf[4096] __attribute__ ((aligned));
printf("opening library handlen");
h = nfq_open();
if (!h) {
fprintf(stderr, "error during nfq_open()n");
exit(1);
}
printf("unbinding existing nf_queue handler for AF_INET (if any)n");
if (nfq_unbind_pf(h, AF_INET) < 0) {
fprintf(stderr, "error during nfq_unbind_pf()n");
exit(1);
}
printf("binding nfnetlink_queue as nf_queue handler for AF_INETn");
if (nfq_bind_pf(h, AF_INET) < 0) {
fprintf(stderr, "error during nfq_bind_pf()n");
exit(1);
}
printf("binding this socket to queue '0'n");
qh = nfq_create_queue(h, 1, &cb, NULL);
if (!qh) {
fprintf(stderr, "error during nfq_create_queue()n");
exit(1);
}
printf("setting copy_packet moden");
if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) {
fprintf(stderr, "can't set packet_copy moden");
exit(1);
}
fd = nfq_fd(h);
while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0) {
printf("pkt receivedn");
nfq_handle_packet(h, buf, rv);
}
printf("unbinding from queue 0n");
nfq_destroy_queue(qh);
#ifdef INSANE
/* normally, applications SHOULD NOT issue this command, since
* it detaches other programs/sockets from AF_INET, too ! */
printf("unbinding from AF_INETn");
nfq_unbind_pf(h, AF_INET);
#endif
printf("closing library handlen");
nfq_close(h);
exit(0);
}
启动可执行文件,它没有收到任何东西。我也跟着这个线程,并试图使用netcat来产生流量,但我没有看到任何数据包也许我错过了一些真正与过滤器队列交互的东西?
是的,你有。如果防火墙允许数据包通过规则,就不会发生任何事情,数据包也不会离开内核空间。但是,如果您设置了一些将数据包发送到用户空间的规则,您的程序就可以工作了。
iptables -A INPUT -i eth0 -j NFQUEUE --queue-num 0
这一行将把所有数据包从带有——in-interface eth0的INPUT发送到用户空间。
libnetfilter_queue就像它的名字一样,是一个过滤器。这意味着,它会根据您创建和打开队列时提供的设置过滤流量。
如果您不通过此过滤器发送任何流量,则过滤器没有任何工作。您必须在iptable中设置通过此过滤器的流量的大小(类型)。
Iptable作为防火墙进入、通过或从退出您的系统。Libnetfilter_queue允许您控制如何处理过滤后的流量。
阅读线程,我发现我没有添加iptables规则…添加这些规则就会有效果。
所以我总是需要设置iptables规则来使用netfilter库获取数据包?
相关文章:
- GDB 8.1 无法在单线程简单程序中跟踪 std::string 变量的值
- 令牌之前的简单程序预期标识符'('
- 带有类和链表的简单C++程序
- 引发未经处理的异常:简单 C++ 程序中的读取访问冲突,动态增加数组长度以存储数字
- C++链表简单程序崩溃
- 简单程序中的意外推力错误
- 未经GCC优化而编译的简单C++程序不会产生预期的结果
- 运行简单 c++ 程序时出现权限被拒绝错误
- 为什么我的简单C++程序使用队列和 fstream 错误到无效指针
- QT创建者:简单程序未解决的外部符号和外部符号错误
- 在VS2017上调试简单程序时访问冲突(RtlActivateActivationContextUnsafeFast)
- 无法为简单程序运行 docker 容器
- 布尔程序返回错误,即使应该是正确的.简单程序
- C++:帮助解释简单程序的行为
- 在使用小数的简单c++程序中遇到问题
- 简单程序的输入/输出问题
- 我在C中简单程序中的内存故障
- 简单程序没有输出和崩溃.我的解决方案有什么问题
- 简单C++程序上的多个未声明标识符
- C++,Visual Studio 2012和错误4700,用于简单程序中的类变量