nf_queue改包

本文介绍了在CentOS 7系统中如何使用libnetfilter_queue模块处理iptables NF_QUEUE规则的数据包。通过在NAT表上设置DNAT和SNAT规则,以及在MANGLE表FORWARD链上创建NF_QUEUE,实现数据包的转发和修改。主要内容包括安装libnetfilter_queue、示例规则、数据包处理代码、多线程读取数据以及TCP/UDP数据的校验更新。
摘要由CSDN通过智能技术生成

系统:centos 7

准备:安装libnetfilter_queue模块,可以yum安装,也可以网上下载rpm包安装

简介:使用iptables在NAT表上创建DNAT与SNAT规则,对数据包进行转发;在MANGLE表上的FORWARD链上创建NF_QUEUE规则对数据进行勾取并修改;(iptables只有mangle表可以修改数据)

 

示例规则:

//把到本机 50.24  8889端口的数据包,nat到50.4的8889端口
iptables -t nat -A PREROUTING -p udp -d 192.168.50.24 --dport 8889 -j DNAT --to 192.168.50.4  
iptables -t nat -A POSTROUTING -p udp -d 192.168.50.4 --dport 8889 -j SNAT --to 192.168.50.24

//把目的地址50.4,目的端口8889的数据包,入队列 1
iptables -t mangle -A FORWARD -d 192.168.50.4 -p udp --dport 8889  -j NFQUEUE --queue-num 1


示例代码:

主线程DoListenIptablesThread负责对QUEUE队列数据的读取,读取到的数据通过回调PacketHandler方法解析处理,传入参数为  queue的 ID号

复制代码
static void *DoListenIptablesThread(void *pData)
{
    struct nfq_handle *h;
    struct nfq_q_handle *qh;
    struct nfnl_handle *nh;
    int fd;
    int rv;
    int i;
    pthread_t RecvPth[PthNUM];
    char buf[QUEUE_BUFSIZE];
    TCLEANFUNCT struTmp;
    int nTmpError = -1;
    int nNum = *(int *)pData;
   free(pData);
    pthread_detach(pthread_self());
memset(&struTmp, 0, sizeof(struTmp)); zlog_debug(cat,"opening library handle, nNum[%d]", nNum); h = nfq_open(); if (!h) { nTmpError = errno; zlog_debug(cat,"error during nfq_open(), nNum[%d]", nNum); zlog_debug(cat,"nfq_open() errno[%d][%s]", nTmpError, strerror(nTmpError)); pthread_exit(0); } zlog_debug(cat,"unbinding existing nf_queue handler for AF_INET (if any), nNum[%d]", nNum); if (nfq_unbind_pf(h, AF_INET) < 0) { nTmpError = errno; zlog_debug(cat,"error during nfq_unbind_pf(), nNum[%d]", nNum); zlog_debug(cat,"nfq_unbind_pf() errno[%d][%s]", nTmpError, strerror(nTmpError)); nfq_close(h); pthread_exit(0); } zlog_debug(cat,"binding nfnetlink_queue as nf_queue handler for AF_INET, nNum[%d]", nNum); if (nfq_bind_pf(h, AF_INET) < 0) { nTmpError = errno; zlog_debug(cat,"error during nfq_bind_pf(), nNum[%d]", nNum); zlog_debug(cat,"nfq_bind_pf() errno[%d][%s]", nTmpError, strerror(nTmpError)); nfq_close(h); pthread_exit(0); } zlog_debug(cat,"binding this socket to queue [%d]", nNum); qh = nfq_create_queue(h, nNum, &PacketHandler, &nNum); if (!qh) { nTmpError = errno; zlog_debug(cat,"error during nfq_create_queue(), nNum[%d]", nNum); zlog_debug(cat,"nfq_create_queue() errno[%d][%s]", nTmpError, strerror(nTmpError)); nfq_close(h); pthread_exit(0); } zlog_debug(cat,"setting copy_packet mode, nNum[%d]", nNum); if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) { nTmpError = errno; zlog_debug(cat,"can't set packet_copy mode, nNum[%d]", nNum); zlog_debug(cat,"nfq_set_mode() errno[%d][%s]", nTmpError, strerror(nTmpError)); nfq_destroy_queue(qh); nfq_close(h); pthread_exit(0); } nh = nfq_nfnlh(h); fd = nfnl_fd(nh); struTmp.qh =
priority_queue是C++标准库中的一个容器适配器,它基于堆结构实现了一个优先级队列。默认情况下,priority_queue使用std::less作为比较规则,即元素按照从大到小的顺序排列。如果你想修改比较规则,可以通过自定义比较函数或者重载元素的比较运算符来实现。 方法一:自定义比较函数 你可以定义一个自定义的比较函数,该函数接受两个参数,并返回一个bool值,表示两个参数的比较结果。比如,如果你想要按照从小到大的顺序排列元素,可以定义一个比较函数如下: ```cpp bool compare(int a, int b) { return a > b; } ``` 然后在创建priority_queue对象时,将该比较函数作为第二个参数传入: ```cpp priority_queue<int, vector<int>, decltype(compare)*> pq(compare); ``` 方法二:重载元素的比较运算符 如果元素是自定义的类对象,你可以重载该类的比较运算符来修改比较规则。比如,如果你想要按照自定义类对象的某个成员变量从小到大的顺序排列,可以在类中重载小于号运算符(<): ```cpp class MyObject { public: int value; // 其他成员变量和函数 bool operator<(const MyObject& other) const { return value < other.value; } }; ``` 然后在创建priority_queue对象时,指定元素类型为MyObject即可: ```cpp priority_queue<MyObject> pq; ``` 这样,priority_queue会根据MyObject类中重载的小于号运算符来进行比较和排序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值