1

I try to detect transit http traffic and forward it to one host by iptables string module.

iptables -A PREROUTING -t mangle -j CONNMARK --restore-mark
iptables -A PREROUTING -t mangle -p tcp    \
  -m string --string "GET" --algo kmp \
  -m mark --mark 0x0 -j CONNMARK --set-mark 0x55
iptables -A PREROUTING -t mangle -j CONNMARK --save-mark

iptables -A PREROUTING -t nat -p tcp -m connmark --mark 0x55 -j DNAT --to-destination 10.10.10.10:80

iptables -L -v -t mangle –line-numbers

Chain PREROUTING (policy ACCEPT 2469 packets, 2078K bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1     2469 2078K CONNMARK   all  --  any    any     anywhere             anywhere             CONNMARK restore
2        1   186 CONNMARK   tcp  --  any    any     anywhere             anywhere             STRING match  "GET" ALGO name kmp TO 65535 mark match 0x0 CONNMARK set 0x55
3     2469 2078K CONNMARK   all  --  any    any     anywhere             anywhere             CONNMARK save

There is count packets increase in mangle table. But in DNAT count is zero.

iptables -L -v -t nat --line-numbers

iptables -L -v -t nat --line-numbers
Chain PREROUTING (policy ACCEPT 306 packets, 61227 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 DNAT       tcp  --  any    any     anywhere             anywhere             connmark match  0x55 to:10.10.10.10:80

What is wrong with this rules?

All chains are on accept

-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
1

This will not work because you are trying to match contents inside a TCP connection, which thus has already been established. However DNAT needs to occur before the connection has been established, and thus it is too late to do DNAT.

Due to this, only packets that set up new connections actually are processed by the "nat" table. All successive packets will automatically get processed using the same SNAT/DNAT/etc strategy that was set up during the first packet.

So when the first packet of the connection (which does not contain any text data) your string match has not yet set the mark, and so the DNAT never matches.

Alternatives that you can consider include setting up a transparent proxy or reverse proxy..

  • For transparent proxy or reverse proxy i need to known destination port. But i need to found it by string module. How i can do this and forward target port to proxy? – Anton Riab Jul 30 '19 at 7:44
  • It seems to me the final destination is 10.10.10.10:80 so the final target port is 80. The original target port does not matter if you create a REDIRECT rule to forward it to a known local port running the proxy. – Jonas Berlin Jul 31 '19 at 9:56
  • The original target port does not matter Source port does not mater - you right @Jonas Berlin. But i need to detect http in any destination port. Only http trafic !!! – Anton Riab Aug 2 '19 at 6:26
  • You need to decide where the packet is going before you know if it contains http traffic. So either you send all traffic to your proxy or you explicitly configure specific ports to NOT go to proxy, like ssh: iptables -t nat -I PREROUTING -p tcp --dport 22 -j ACCEPT - this will make it NOT apply REDIRECT for this port. – Jonas Berlin Aug 2 '19 at 9:28

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.