Is it possible to modify the output device/interface of a received packet in a libnetfilter_queue script run in userspace? How would one do this, with libmnl
calls or otherwise? The desired result is to return an ACCEPT verdict and have the kernel forward the packet but through the new output interface, instead of that it
Hooking into NFQUEUE at POSTROUTING -t mangle
if that has any significance. I’ve tried working with two different examples:
- nf-queue.c on the library’s website, which passes verdict into the netlink socket through
libmnl
calls:
https://netfilter.org/projects/libnetfilter_queue/doxygen/html/nf-queue_8c_source.html
This one I’ve tried modifying the callback as such:
// /* example to set the connmark. First, start NFQA_CT section: */
// nest = mnl_attr_nest_start(nlh, NFQA_CT);
// /* then, add the connmark attribute: */
// mnl_attr_put_u32(nlh, CTA_MARK, htonl(42));
// /* more conntrack attributes, e.g. CTA_LABELS could be set here */
// /* end conntrack section */
// mnl_attr_nest_end(nlh, nest);
mnl_attr_put_u32(nlh, NFQA_IFINDEX_OUTDEV, htonl(intf_id));
where intf_id
is a user input uint_32
and set to the desired interface ID upon setup.
But when run, it looks to have no effect on the output device according to nft monitor trace
output. In fact, I don’t see any difference in the output that indicates CONNMARK is being set when the given script is run as is.
- and this one, which instead passes a
pkt_buff
directly tonfq_set_verdict
:
https://www.apriorit.com/dev-blog/598-linux-mitm-nfqueue
This example I’ve gotten to successfully modify the payload. However, in the case of pkt_buff
, it doesn’t look like the INDEV or OUTDEV fields are within reach, unlike a proper SKB, which has it as a field. https://netfilter.org/projects/libnetfilter_queue/doxygen/html/pktbuff_8c_source.html
libnetfilter_queue
offers a getter for indev/outdev that fetches through netlink (https://www.netfilter.org/projects/libnetfilter_queue/doxygen/html/group__Parsing.html#gae8b3bec8898ec7e2464fef059b00d231), but I don’t know how/if it’s possible to set the indev/outdev in an outgoing packet (e.g. by mangling the pkt_buff
).
I lack any prior knowledge in netlink or SKB or other internal networking things, so please let me know if I’m missing something obvious in either of these cases. There seem to be little to no examples available for these libraries and I wouldn’t know where to start/what greater context is relevant. Thank you!