Using libnetfilter_queue, a reinjected packet dosnt affect change, However inject copy of the packet succeeds. Why?
need to use NF_REPEAT verdict to reinject packet to the
same chain. Using NF_ACCEPT verdict injects packet to the subsequent
chain. But for this purpose you should mark packets to avoid loop,
i.e.:
iptables -t raw -A PREROUTING -p tcp -m tcp --dport 80 -m mark !
--mark 0x1/0x1 -m tcp -j NFQUEUE
iptables -t raw -A PREROUTING -p tcp -m tcp --dport 80 -m mark --mark
0x80/0x80 -m tcp ACCEPT # altered packets
iptables -t raw -A PREROUTING -p tcp -m tcp --dport 80 -m mark --mark
0x1/0x1 -m tcp ACCEPT # rest
The network packet is rejected if i make a change in it using libnetfilter_queue
If you change anything you have to update the checksum to prevent rejection, otherwise the packet will be considered to be corrupted...
edit: assuming you are working on IP packets, the above only applies for changes in the IP header, since only the header, not the payload, is 'protected' by the IP checksum.
libnetfilter_queue recv() function
recv() may return -1 and errno is set to ENOBUFS in case your application is not fast enough to retrieve the packets from the kernel. In that case, you can increase the socket buffer size by means of nfnl_rcvbufsiz(). Although this delays ENOBUFS errors, you may hit it again sooner or later.
Source: libnetfilter_queue Documentation
Rewriting network packets on the fly using libnetfilter_queue
I can't believe I missed this previously. As reticent as I am to post questions on SO, I thought I would never work this one out myself. :)
I didn't look at the function prototype properly. It turns out in the "verdict" function (outlined below),
int nfq_set_verdict(struct nfq_q_handle *qh,
u_int32_t id,
u_int32_t verdict,
u_int32_t data_len,
const unsigned char *buf
)
The last two parameters are for the data to be returned to the network stack. Obvious in hindsight, but I missed it completely as the print_pkt
function doesn't take the packet data as a parameter, but extracts it from the struct nfq_data
.
The key is to NF_ACCEPT
the packet and pass the suitably modified packet back to the kernel.
simple program using libnetfilter_queue isn't working
Yes, you have. If your firewall lets the packets trough the rules nothing will happen and the packets wont left the kernel space. But if you setting up some rules that send the packets to the user space, your programm will work.
iptables -A INPUT -i eth0 -j NFQUEUE --queue-num 0
This line will send all packets from the INPUT with the --in-interface eth0 into the userspace.
Sending queued packets with NFQUEUE?
Your idea makes sense. In fact I've seen a very similar scheme implemented in a commercial product I worked on. It had to process individual packets at high rates, so it would always copy the incoming packet and immediately set an NF_DROP
verdict. It would then perform the processing, and if it decided that the packet should be forwarded, it would send the copy to the outbound interface. So you're not alone.
As far as I know, nfq_set_verdict
can be called only once per packet. Once the verdict is set, NFQUEUE sends the packet to the destination (which is packet heaven in your case). It doesn't keep an extra copy of the packet just in case you change your mind. So to send the packet back to the network you'll have to store a copy of it and send it using your own socket. And yes, if you want to send the received packet as-is (including headers) the outbound socket would have to be raw
.
forwarding packets to service in same host without using loopback network
I propose the following solution:
- store packets in the application and return verdict NF_DROP
- re-inject packets into the network stack using RAW sockets
- tag concatenated UDP packets with a DSCP (see IP packet format)
- in iptables, add a rule to match on this DSCP (--dscp) and ACCEPT the packet directly, without it passing through your netfilter application
If your provider already tags some packets with DSCP, you can add some iptables rules to clear them, like:
iptables -t mangle -A INPUT -j DSCP --set-dscp 0
I hope this solves your use-case.
libnetfilter_queue: Why can't I see the TCP payload of packets from nfq_get_payload?
Thanks to Joel for pointing out that problem was not in the C code, but in the iptables rules. There was a -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
rule prior to the NFQUEUE rule, so I was only getting the connection setup packets... whoops.
Related Topics
Centos Cgconfig Fails to Start
Bash Separate Parameters with Specific Delimiter
How to Run a Linux Executable from Any Directory in Terminal
Printing Floating Point Numbers in Assembler
Nohup Create New Files Nohup.Out by Day
Ffmpeg Combining Images to Video and Streaming in One Command Line
Bus Error Opening and Mmap'Ing a File
Accessing Any Memory Locations Under Linux 2.6.X
How to Use Xdotool to Enter a Web Console Command
Replace a String in a File with Contents Copied from Another File
Restart Service from Cgi Script
How to Create a Folder with a Folder Name Containing Spaces in Linux
Why Do My Keystrokes Turn into Crazy Characters After I Dump a Bunch of Binary Data into My Terminal
Why This Shell Won't Work If It's Called from Rc.Local But Ssh
Make Install Error 'Nothing to Be Done'
Save The Result of Ls Command in The Remote Sftp Server on Local Machine