系统: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 =