Iptables netfilter队列nfq_set_decision_标记(nfq_set_decistic2)不';我好像没在申请分数

Iptables netfilter队列nfq_set_decision_标记(nfq_set_decistic2)不';我好像没在申请分数,c,linux,networking,iptables,netfilter,C,Linux,Networking,Iptables,Netfilter,我在使用iptables时遇到了一些问题,一组新的眼球可能会看到问题所在 我正在尝试使用netfilter队列在mangle表的预路由链中标记数据包(通过nfq_set_revidence_mark——旧文档称使用nfq_set_revidence2,但该函数似乎不再位于头或库中)。然后,数据包应该移动到nat表的预路由链,在这里我有规则读取标记并相应地重定向。事实上,这在早期的测试中是有效的,但现在不是 下面是我简化测试的回调函数-它只是用0xFFFFFFFF标记并接受: static int

我在使用iptables时遇到了一些问题,一组新的眼球可能会看到问题所在

我正在尝试使用netfilter队列在mangle表的预路由链中标记数据包(通过nfq_set_revidence_mark——旧文档称使用nfq_set_revidence2,但该函数似乎不再位于头或库中)。然后,数据包应该移动到nat表的预路由链,在这里我有规则读取标记并相应地重定向。事实上,这在早期的测试中是有效的,但现在不是

下面是我简化测试的回调函数-它只是用0xFFFFFFFF标记并接受:

static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
          struct nfq_data *nfa, void *data)
{
    uint32_t id = print_pkt(nfa); // from example code
    printf("marking packet...\n");
    return nfq_set_verdict_mark(qh,id,NF_ACCEPT,0xFFFFFFFF,0,NULL);
}
以下是我正在使用的iptable规则:

// Using queue -- not working
iptables -t mangle -A PREROUTING -p tcp --dport 80 -j QUEUE
iptables -t nat -A PREROUTING -p tcp --dport 80 -m mark --mark 0xFFFFFFFF -j REDIRECT --to-ports 9009
我还使用
conntrack--flush
重置连接状态,以确保数据包遇到nat表。我使用0xFFFFFF来防止可能的字节排序问题。数据包清楚地进入队列并被接受(“标记数据包…”已打印,浏览器可以访问端口80上的内容)。但是,重定向不会发生

如果我直接设置mark而不是在队列中,则重定向会起作用。就好像队列中没有添加标记一样。这肯定是标记之前,我没有改变图书馆版本或任何东西

// Without queue -- redirection happens
iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK --set-mark 0xFFFFFFFF
iptables -t nat -A PREROUTING -p tcp --dport 80 -m mark --mark 0xFFFFFFFF -j REDIRECT --to-ports 9009
以下是print_pkt for good Measures-不是我写的,但取自netfilter_队列示例,尚未更改,以前一直有效:

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;
}
int main(int argc, char **argv)
{
        struct nfq_handle *h;
        struct nfq_q_handle *qh;
        struct nfnl_handle *nh;
        int fd;
        int rv;
        char buf[4096] __attribute__ ((aligned));

        printf("opening library handle\n");
        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_INET\n");
        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,  0, &cb, NULL);
        if (!qh) {
                fprintf(stderr, "error during nfq_create_queue()\n");
                exit(1);
        }

        printf("setting copy_packet mode\n");
        if (nfq_set_mode(qh, NFQNL_COPY_META, 0xffff) < 0) {
                fprintf(stderr, "can't set packet_copy mode\n");
                exit(1);
        }

        fd = nfq_fd(h);

        while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0) {
                printf("pkt received\n");
                nfq_handle_packet(h, buf, rv);
        }

        printf("unbinding from queue 0\n");
        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_INET\n");
        nfq_unbind_pf(h, AF_INET);
#endif

        printf("closing library handle\n");
        nfq_close(h);

        exit(0);
}
static u_int32_t print_pkt(struct nfq_data*tb)
{
int id=0;
结构nfqnl_msg_packet_hdr*ph;
结构nfqnl_msg_packet_hw*hwph;
国际货币基金组织国际货币基金组织;
int ret;
字符*数据;
ph=nfq\u get\u msg\u packet\u hdr(tb);
如果(ph){
id=ntohl(ph->packet\u id);
printf(“hw_协议=0x%04x挂钩=%u id=%u”,
ntohs(ph->hw_协议),ph->hook,id);
}
hwph=nfq_get_packet_hw(tb);
如果(hwph){
inti,hlen=ntohs(hwph->hw_addrlen);
printf(“hw_src_addr=”);
对于(i=0;ihw_addr[i]);
printf(“%02x”,hwph->hw_addr[hlen-1]);
}
mark=nfq\u get\u nfmark(tb);
如果(标记)
printf(“标记=%u”,标记);
ifi=nfq_get_indev(tb);
国际单项体育联合会
printf(“indev=%u”,ifi);
ifi=nfq_get_out dev(tb);
国际单项体育联合会
printf(“outdev=%u”,ifi);
ifi=nfq\U get\U physindev(tb);
国际单项体育联合会
printf(“物理指标=%u”,ifi);
ifi=nfq\U get\U physoutdev(tb);
国际单项体育联合会
printf(“physoutdev=%u”,ifi);
ret=nfq\U get\U有效负载(tb和数据);
如果(ret>=0)
printf(“有效载荷长度=%d”,ret);
fputc('\n',stdout);
返回id;
}
另外,主要功能(也取自示例代码,并且以前一直在工作):

int main(int argc,char**argv)
{
结构nfq_句柄*h;
结构nfq_q_句柄*qh;
结构nfnl_句柄*nh;
int-fd;
int-rv;
char buf[4096]uuu属性_uuu((对齐));
printf(“打开库句柄”);
h=nfq_open();
如果(!h){
fprintf(标准,“nfq_打开时出错()\n”);
出口(1);
}
printf(“为AF_INET(如果有)解除现有nf_队列处理程序的绑定)\n”);
if(nfq_unbind_pf(h,AF_INET)<0){
fprintf(标准,“nfq_unbind_pf()\n期间出错”);
出口(1);
}
printf(“将nfnetlink_队列绑定为AF_INET的nf_队列处理程序\n”);
if(nfq\u bind\u pf(h,AF\u INET)<0){
fprintf(stderr,“nfq_bind_pf()\n期间出错”);
出口(1);
}
printf(“将此套接字绑定到队列“0”\n”);
qh=nfq_创建_队列(h,0,&cb,NULL);
if(!qh){
fprintf(stderr,“nfq_创建_队列()期间出错”);
出口(1);
}
printf(“设置复制\数据包模式”);
如果(nfq设置模式(qh,NFQNL复制元,0xffff)<0){
fprintf(stderr,“无法设置数据包\u复制模式”);
出口(1);
}
fd=nfq_fd(h);
而((rv=recv(fd,buf,sizeof(buf),0))&&rv>=0){
printf(“已收到pkt\n”);
nfq_手柄_包(h、buf、rv);
}
printf(“从队列0解除绑定\n”);
nfq_销毁_队列(qh);
#如果你疯了
/*通常,应用程序不应发出此命令,因为
*它还可以从AF_INET上分离其他程序/套接字*/
printf(“从AF_INET解除绑定”);
nfq_unbind_pf(h,AF_INET);
#恩迪夫
printf(“关闭库句柄”);
nfq_关闭(h);
出口(0);
}
重定向是我的测试代码中的预期行为,但它没有发生。缺失的环节是什么?我在这个问题上花了好几个小时(之前的工作和预期的一样),但没有结果。救命

旧文档说要使用nfq_set_dedict2,但该函数似乎不再位于标题或库中

也许您使用的是过时版本的libnetfilter\u队列hdrs+lib?
版本1.0.2(netfilter.org)似乎是最新版本,并且具有此功能。

是的,对于最新的libnetfilter\u队列,您应该以以下方式仅使用nfq\u set\u decistic2功能

 nfq_set_verdict2(handle,
                  packet_id,
                  NF_AXXEPT,
                  nfq_get_nfmark(nfa) | 0xFFFFFFFF,
                  0,
                  NULL);
这对我有用