3

I run a few Linux containers, each running a webapp, on my Ubuntu host. To access the webapps, I use iptables to forward port:

sudo iptables -t nat -A PREROUTING -p tcp --dport <port> -j DNAT --to-destination #<container_ip>:<port>

This work well if the traffic comes from outside of my host. If the request is done by localhost it doesn't work:

 curl <host_ip>:<port>       #works (from outside the host)
 curl <container_ip>:<port>  #works (from inside the host)
 curl 127.0.0.1:<port>       #doesn't work (from inside the host)

I understand that packet coming from localhost do not go through the iptables DNAT rule and that is why it's not working. Is there anyway to get this working ?

Sridhar Ratnakumar
  • 177
  • 1
  • 2
  • 9
rmonjo
  • 231
  • 1
  • 4
  • 12

3 Answers3

1

@Brigo: That is incorrect. The nat table can contain an OUTPUT chain. The problem is that the nat table's PREROUTING chain is not applied to the loopback interface.

@rmonjo, use the OUTPUT chain in addition to the PREROUTING chain:

iptables -t nat -A OUTPUT -o lo -p tcp --dport <port> -j DNAT \
--to-destination #<container_ip>:<port>

Edit: this doesn't work. I was thinking of the REDIRECT target which won't solve this problem.

Mark Wagner
  • 17,764
  • 2
  • 30
  • 47
  • Thank you, I got really enthusiastic about this answer but it doesn't work. Now when I `curl 127.0.0.1:3100`, curl just does nothing (no more "couldn't connect to host", at least before it times out). What am I missing ? – rmonjo Jul 31 '13 at 08:21
  • Yep, I'm wrong. – Mark Wagner Jul 31 '13 at 19:46
  • For me this safed my day when from within the host connecting to `:` instead of `127.0.0.1:` what the OP tried. `:` was rejected before adding your IPTABLES rule, thanks! – Selaron Jan 27 '20 at 16:33
0

If you're open to solutions not involving iptables, you could just run a simple proxy server (like balance or haproxy or pen or something) to intercept traffic to localhost and pass it to your containers.

larsks
  • 41,276
  • 13
  • 117
  • 170
  • Ok, confirmed that this is not possible using iptables. The only way is to use some kinds of proxy as you mentioned. – rmonjo Jul 31 '13 at 19:55
0

i've spend a lot of time trying to get iptables to do this trick, but somehow if you add a dnat target to the output chain of the nat table further processing of the packet seems to stop.

Debugging of iptables can be done with this trick: http://backreference.org/2010/06/11/iptables-debugging/

A graphical overview of the packet flow in Linux also helps: http://inai.de/images/nf-packet-flow.png

i've resorted to xinetd to solve my problem, see Forwarding the endpoint (at localhost) of an SSH -L tunnel to another machine

  • It does this because DNAT is disposative. You have to arrange your rules in precedential order with nondisposative rules ordinally prior to disposative ones. – Falcon Momot Sep 30 '13 at 08:08