I'm trying to use libnetfilter_queue to add custom options to the IP headers of certain packets.
As a test, I've tried modifying the sample program from the libnetfilter_queue documentation (nf-queue.c) to change the TTL value in the header. The packets appear in Wireshark with the modified contents, but they don't seem to actually reach the destination.
This is the modified callback function from the libnetfilter_queue example. It changes the TTL value from the default 64 to 88.
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; } To test, I've set up an nftables rule to queue packets like this:
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 Then I run the program and use nc to send UDP packets like this:
- Receiver: nc -u -l -p 4444
- Sender: nc -u localhost 4444
Источник: https://stackoverflow.com/questions/780 ... estination