0

I have a pretty default lxc-setup with one host and several containers. One container webfrontend is getting all host-traffic on ports 80 and 443 via DNATing the ports. An nginx on webfrontend decides via vhosts, which container webappX should get the request and proxies the request through to the webappX' private ip:

host:443 <--prerouting--> webfrontend:443 <--nginx--> webappX-private:80

-A PREROUTING -d 80.x.x.x/32 -i eth0 -p tcp -m tcp --dport 443 -j DNAT --to-destination 10.0.3.100:443
  • Host (public): 80.x.x.x
  • webfrontend (lxcbr0): 10.0.3.100
  • webappX (lxcbr0): 10.0.3.200
  • webappY (lxcbr0): 10.0.3.201
  • ...

This works fine and allows a central point for letsencrypt-certificates, etc.

However, when webappX needs to access webappY, the connection is refused and the webfrontend never sees the request. I can access webappY on the private ip (from webappX), but I cannot access webappY-public (aka the webfrontend):

root@webappX:~# curl -I http://10.0.3.201
HTTP/1.1 200 OK
[...]

root@webappX:~# curl -I http://webappY.example.com
curl: (7) Failed to connect to webappY.example.com port 80: Connection refused

root@webappX:~# nslookup webappY.example.com
[...]
Name: webappY.example.com
Address: 80.x.x.x

Forwarding between the containers are given:

*filter
-A FORWARD -o lxcbr0 -j ACCEPT
-A FORWARD -i lxcbr0 -j ACCEPT

So far, I've tried setting POSTROUTING-rules and OUTPUT-rules on eth0 and lo without success.

Any ideas?

2
  • 1
    What you want is NAT hairpinning. You are not hitting your DNAT rules, mainly because the traffic comes from another interface than eth0. However, I’m not sure that’s all.
    – Daniel B
    Commented Sep 28, 2016 at 9:20
  • @DanielB devil in the details... that did it. Could you post that as an answer? I'll add the iptables-rule to the answer and award the reputation. Thx!
    – Lars
    Commented Sep 28, 2016 at 10:39

1 Answer 1

1
+50

What you need is so called NAT hairpinning (aka NAT loopback, NAT reflection):

NAT loopback, [...] is a feature in many consumer routers which permits the access of a service via the public IP address from inside the local network.

Why is it not working? The IPTables DNAT rule you provided in your question specifies an incoming interface this rule should apply to: -i eth0. Your traffic isn’t coming from eth0 however, but some virtual network interface or whatever. Just removing this restriction to eth0 may be sufficient to make it work.

Alternatively, a separate rule could be added to lxcbr0:

iptables -t nat -A PREROUTING -i lxcbr0 -p tcp --dport 443 \
    --destination 80.x.x.x -j DNAT --to 10.0.3.100:443

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .