i need to redirect all UDP packets with destination port 15000 to port 15001 if the packet contains for example the string test
. i have these two simple rules:
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 15000 -m string --string 'test' --algo bm -j LOG --log-prefix='[netfilter] '
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 15000 -m string --string 'test' --algo bm -j REDIRECT --to-ports 15001
The strange behaviors:
- if the first packet contains
test
string, redirection is done for
all packets of the connection; - if the first packet of the connection doesn't contains
test
, redirection is never done even if a subsequent packet containstest
However all packets matching rule are correctly logged.
i tried to add also the track information to the rule:
-m state --state NEW,ESTABLISHED
but the behaviour is the same. Some ideas?
This is the complete iptables
ruleset:
filter table:
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
nat table:
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
LOG udp -- anywhere anywhere udp dpt:15000 STRING match "test" ALGO name bm TO 65535 LOG level warning prefix "[netfilter] "
REDIRECT udp -- anywhere anywhere udp dpt:15000 STRING match "test" ALGO name bm TO 65535 redir ports 15001
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
mangle table:
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
raw table:
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Best Answer
nat table rules always work only for first packet in connection. Subsequent packets of same connection never traverse nat rule list and only supported by conntrack code
As UDP is connectionless in nature, "connection" here is defined simply by addresses, ports and timeout. So, if second UDP packet with same source port and address and same destination port and address arrives within the timeout, Linux believes it belongs to established "connection" and doensn't evaluate nat rule table for it at all, reusing verdict issued for previous packet.
See here: http://www.netfilter.org/documentation/HOWTO/netfilter-hacking-HOWTO-3.html