libnetfilter_queue修改的数据包无法到达目标端问题排查
修改IP头TTL后数据包无法到达目标端,调用nfq_udp_mangle_ipv4后恢复正常的原因
我尝试使用libnetfilter_queue为特定数据包的IP头添加自定义选项,先做了个测试:修改libnetfilter_queue文档中的示例程序nf-queue.c,将IP头的TTL值从默认64改为88。修改后的数据包能在Wireshark中捕获到,但无法到达目标端。
修改后的回调函数
static int queue_cb(const struct nlmsghdr *nlh, void *data) { struct nfqnl_msg_packet_hdr *ph = NULL; struct nlattr *attr[NFQA_MAX+1] = {}; uint32_t id = 0, skbinfo; int queue_num; struct nfgenmsg *nfg; uint16_t plen; void *payload; struct pkt_buff *pktb; uint8_t new_ttl = 88; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh_verdict; struct nlattr *nest; /* Parse netlink message received from the kernel, the array of * attributes is set up to store metadata and the actual packet. */ if (nfq_nlmsg_parse(nlh, attr) < 0) { perror("problems parsing"); return MNL_CB_ERROR; } nfg = mnl_nlmsg_get_payload(nlh); if (attr[NFQA_PACKET_HDR] == NULL) { fputs("metaheader not set\n", stderr); return MNL_CB_ERROR; } /* Access packet metadata, which provides unique packet ID, hook number * and ethertype. See struct nfqnl_msg_packet_hdr for details. */ ph = mnl_attr_get_payload(attr[NFQA_PACKET_HDR]); id = ntohl(ph->packet_id); queue_num = ntohs(nfg->res_id); /* Access actual packet data length. */ plen = mnl_attr_get_payload_len(attr[NFQA_PAYLOAD]); /* Access actual packet data */ payload = mnl_attr_get_payload(attr[NFQA_PAYLOAD]); /* Copy to packet buffer with extra space for mangling */ pktb = pktb_alloc(AF_INET, payload, plen, 255); /* Change TTL */ nfq_ip_mangle( pktb, 0, offsetof(struct iphdr, ttl), sizeof(((struct iphdr *)0)->ttl), &new_ttl, sizeof(new_ttl) ); /* Accept mangled packet */ nlh_verdict = nfq_nlmsg_put(buf, NFQNL_MSG_VERDICT, ntohs(nfg->res_id)); if (pktb_mangled(pktb)) { nfq_nlmsg_verdict_put_pkt(nlh_verdict, pktb_data(pktb), pktb_len(pktb)); } nfq_nlmsg_verdict_put(nlh_verdict, id, NF_ACCEPT); if (mnl_socket_sendto(nl, nlh_verdict, nlh_verdict->nlmsg_len) < 0) { perror("mnl_socket_send"); exit(EXIT_FAILURE); } return MNL_CB_OK; }
测试配置与步骤
nftables入队规则
nft add table inet test-table nft add chain inet test-table test-chain '{ type filter hook output priority 0; }' nft add rule inet test-table test-chain counter queue
测试命令
- 接收端:
nc -u -l -p 4444 - 发送端:
nc -u localhost 4444 <<< Hello
现象
Wireshark能捕获到修改TTL后的数据包,但接收端nc无输出。即使将TTL改回原值64,现象依然相同。
更新与疑问
添加nfq_udp_mangle_ipv4调用(即使未修改任何数据)后,接收端能正常接收并打印消息。查看该函数源码,发现其仅调用nfq_ip_mangle并更新UDP校验和,为何此调用是必要的?
内容的提问来源于stack exchange,提问作者fzybunny
相关产品推荐
相关产品推荐

