3

We currently have some rules setup in IPtables that look like the below:

-A PREROUTING -d dstip/32 -p udp -m udp --dport 27035 -m u32 --u32 "0x0>>0x16&0x3c@0x8=0xffffffff&&0x0>>0x16&0x3c@0xc=0x54536f75&&0x0>>0x16&0x3c@0x10=0x72636520&&0x0>>0x16&0x3c@0x14=0x456e6769&&0x0>>0x16&0x3c@0x18=0x6e652051&&0x0>>0x16&0x3c@0x1c=0x75657279" -j REDIRECT --to-ports 21010

This redirects packets containing that payload to our caching programs, this works great. However, only "new" packets are hitting this NAT rule. After some looking around, I managed to solve this issue by setting the following:

sudo sysctl -w net.netfilter.nf_conntrack_udp_timeout=0
sudo sysctl -w net.netfilter.nf_conntrack_udp_timeout_stream=0

This introduced another problem where ALL UDP packets were being set to this. During a small UDP flood, this would cause all udp traffic on the server to halt.

I'm needing to redirect ALL UDP packets containing a certain payload to another port on the same machine. We have another program listening on this port that replies to this payload. This is due to a query flood that usually freezes up one of our applications, so we offload this query to another program.

Any solutions to this? Been looking around for months without any sort of answer.

  • I don't see how you can translate a network address without using NAT. What are your objections to using network address translation in some form? – roaima Nov 18 '16 at 18:18
  • NAT is fine, except it needs to redirect all matching packets and not just NEW ones. Established connections etc do not go through NAT – user1372896 Nov 18 '16 at 18:32
  • I basically just need a way to redirect UDP packets containing x payload to another port – user1372896 Nov 18 '16 at 18:36
  • I would suggest then that you edit your question to remove the "without NAT" stipulation. – roaima Nov 18 '16 at 22:49
  • 1
    Can you edit the question and add you all rules in the NAT table ? – Wissam Roujoulah Nov 19 '16 at 4:58
0

I have two completely different methods to solve this problem:

iptables with conntrack zones

Contrack zones allow multiple conntrack instances (per network namespace).

By adding an orig-zone tag to the packet and thus flow, it's possible to have two conntrack instances splitting the (half created) flow in two parts: the normal packets and the matching packets, each in its own flow. Thus usual NAT rules will continue to work and can happen twice instead of once: once for the normal packets and once for the matching packets.

Instead of duplicating the test, a mark will be put in place after the one test done on the packet.

iptables -t raw -A PREROUTING -d dstip/32 -p udp -m udp --dport 27035 -m u32 --u32 "0x0>>0x16&0x3c@0x8=0xffffffff&&0x0>>0x16&0x3c@0xc=0x54536f75&&0x0>>0x16&0x3c@0x10=0x72636520&&0x0>>0x16&0x3c@0x14=0x456e6769&&0x0>>0x16&0x3c@0x18=0x6e652051&&0x0>>0x16&0x3c@0x1c=0x75657279" -j MARK --set-mark 1
iptables -t raw -A PREROUTING -m mark --mark 1 -j CT --zone-orig 1
iptables -t nat -A PREROUTING -p udp -m mark --mark 1 -j REDIRECT --to-ports 21010

Example of conntrack results:

# conntrack -E -p udp --orig-port-dst 27035
    [NEW] udp      17 30 src=10.0.3.1 dst=10.0.3.66 sport=52670 dport=27035 [UNREPLIED] src=10.0.3.66 dst=10.0.3.1 sport=27035 dport=52670
    [NEW] udp      17 30 src=10.0.3.1 dst=10.0.3.66 sport=52670 dport=27035 zone-orig=1 [UNREPLIED] src=10.0.3.66 dst=10.0.3.1 sport=21010 dport=52670
 [UPDATE] udp      17 30 src=10.0.3.1 dst=10.0.3.66 sport=52670 dport=27035 src=10.0.3.66 dst=10.0.3.1 sport=27035 dport=52670
 [UPDATE] udp      17 30 src=10.0.3.1 dst=10.0.3.66 sport=52670 dport=27035 zone-orig=1 src=10.0.3.66 dst=10.0.3.1 sport=21010 dport=52670

nftables with notrack and packet header field mangling

requires kernel >= 4.10

(Of course the zones method could be implemented with nftables).

Here NAT is done statelessly, with conntrack disabled, for matching incoming packets and all outgoing reply packets from the redirected port.

nft add table ip raw
nft add chain ip raw prerouting '{type filter hook prerouting priority -300;}'
nft add chain ip raw output '{type filter hook output priority -300;}'
nft add rule ip raw prerouting ip daddr dstip/32 udp dport 27035 @th,64,32 == 0xffffffff @th,96,32 == 0x54536f75 @th,128,32 == 0x72636520 @th,160,32 == 0x456e6769 @th,192,32 == 0x6e652051 @th,224,32 == 0x75657279 notrack udp dport set 21010
nft add rule ip raw output udp sport 21010 notrack udp sport set 27035

(note that the u32 equivalent raw payload filters can be simplified and are actually simplified automatically by nftables: it appears nftables handles u128 internally as can be seen with nft --debug=netlink list ruleset -a).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.