Modifying packets

Hi All,

I am trying to figure out how to modify packets as they pass from LAN to WAN (and back again).

Specifically I need to modify a UDP packet on a specific port such that the changes made require calculating a custom checksum and writing this back to the packet.

I've managed to build and install a custom app on the OpenWRT firmware - this is where I would like to pass the packet and have it modified ready to send out.

The bit I'm struggling with is how to know when the packets I'm interested in have arrived, and how to call my app to modify them.

I thought iptables might have been the answer, but I can't see how to call an app to make the changes.

Anyone have any thoughts on how to implement this?


Typically there is only one checksum that is correct for a given packet[1]. Perhaps you could enlighten us as to what you are trying to achieve so that a reasonable approach could be suggested.


Checksum is the 16-bit one's complement of the one's complement sum of a
pseudo header of information from the IP header, the UDP header, and the
data,  padded  with zero octets  at the end (if  necessary)  to  make  a
multiple of two octets.

The pseudo  header  conceptually prefixed to the UDP header contains the
source  address,  the destination  address,  the protocol,  and the  UDP
length.   This information gives protection against misrouted datagrams.
This checksum procedure is the same as is used in TCP.

                  0      7 8     15 16    23 24    31 
                 |          source address           |
                 |        destination address        |
                 |  zero  |protocol|   UDP length    |

If the computed  checksum  is zero,  it is transmitted  as all ones (the
equivalent  in one's complement  arithmetic).   An all zero  transmitted
checksum  value means that the transmitter  generated  no checksum  (for
debugging or for higher level protocols that don't care).
1 Like

Thanks for the quick reply. The checksum per se is irrelevant. I only mentioned it to indicate the changes that I need to make to the packet are non-trivial and can't be done by a script. The checksum I'm referring to is different to the IP packet one.

Thus I need to write an app to handle all the calculations and changes.

Have your application listen on a specific port use iptables to forward the relevant packets to this specific port and then process them

That makes sense. So once I've finished modifying the packet, should my app also then send the modified packet to a specific port and again iptables would forward it to the WAN?

you could do that or send directly to their intended destination

1 Like

Great, thanks.

What is the correct way to obtain the interface/ip address to bind to from my app?

Nobody has mentioned NFQUEUE, which allows you to modify packets in user-space.

iptables-mod-nfqueue - 1.6.2-1 - iptables extension for user-space queuing via NFNETLINK.  Includes: - libxt_NFQUEUE
kmod-ipt-nfqueue - 4.14.63-1 - Netfilter module for user-space packet queuing Includes: - NFQUEUE

Thanks Mikma, this looks very interesting. Cheers.

So I managed to write a filter and got it to compile and capture packets on my Debian 9 dev system.
After much fighting with the OpenWrt SDK I also managed to build a package and install it on the target OpenWrt device.

Now came the big moment to test it...

root@OpenWRT:~# iptables -I INPUT -d -j NFQUEUE --queue-num 0 --q
iptables v1.8.2 (legacy): unknown option "--queue-num"
Try `iptables -h' or 'iptables --help' for more information.

After all that it appears the version of iptables doesn't know about NFQUEUE.
Is there something else I need to do to enable my filter hook?

Did you already install the nfqueue kmod and the user's page iptables extension packages that mikma listed?

I tried.

Installing iptables-mod-nfqueue (1.8.2-3) to root...

Collected errors:
 * satisfy_dependencies_for: Cannot satisfy the following dependencies for iptables-mod-nfqueue:
 * 	kernel (= 4.14.114-1-9bcd561448ae0d9d6f516e5662947645) * 	kernel (= 4.14.114-1-9bcd561448ae0d9d6f516e5662947645) * 	kernel (= 4.14.114-1-9bcd561448ae0d9d6f516e5662947645) * 
 * opkg_install_cmd: Cannot install package iptables-mod-nfqueue.

Seems my device is running kernel 4.14.87.

If you are using snapshots you need to install any packages soon after the snapshot becomes available.

If you miss the window, you will need to upgrade openwrt to the current snapshot and retry installing the package

Or as you compiling with the SDK, just compile also those packages...

But make sure that you are using the exactly correct SDK, which matches you firmware and kernel 4.14.87. that is especially important for compiling kernel packages.

Possibly you need to download a new firmware and the SDK at the same time. Then flash the new firmware and use that SDK to compile your packages.

So I figured building the latest kernel would be the best way forward. I have just finished building and wrote the image to an SD card. When I boot I see:

root@OpenWrt:/# uname -r

Great. So now I try to install the iptables module:

root@OpenWrt:/# opkg install iptables-mod-nfqueue
Installing iptables-mod-nfqueue (1.8.2-3) to root...
Collected errors:
 * satisfy_dependencies_for: Cannot satisfy the following dependencies for iptables-mod-nfqueue:
 *      kernel (= 4.14.115-1-9bcd561448ae0d9d6f516e5662947645)
 * opkg_install_cmd: Cannot install package iptables-mod-nfqueue.

Any ideas what I'm missing here?

You need to flash your own packages, not those from the OpenWrt repo.

The easiest is to add them to your build directly.

Enabling ccache under developer options will speed your builds.

Other options include building them as modules yourself and either uploading them to the OpenWrt instance and installing them, or running your own HTTP server with the packages available there and modifying the opkg config to use your repo. Since you've got to select and build them yourself anyway, might as well add them to the image.

1 Like

That makes sense.
A few questions:

  1. Where can I find the 'ccache' option under menuconfig?
  2. Where do I enable 'iptables-mod-nfqueue' under menuconfig?

I found 'kmod-ipt-nfqueue'.

I never remember myself for a lot of things and use search with the / key to find them.

Advanced configuration options (for developers) > Use ccache

Hmmm, Advanced Configuration Options is blank. There is nothing to choose.

You need to select it to show its options.