Can't access domain internally via public IP address [duplicate]
I have a dedicated server running Proxmox and a VM inside Proxmox running Debian 7 (Wheezy).
As I only have one IP address, I'm using iptables to forward ports to the VM.
My /etc/network/interfaces
:
# The loopback network interface
auto lo
iface lo inet loopback
# For routing
auto vmbr1
iface vmbr1 inet manual
post-up /etc/pve/kvm-networking.sh
bridge_ports dummy0
bridge_stp off
bridge_fd 0
# vmbr0: Bridging. Make sure to use only MAC adresses that were assigned to you.
auto vmbr0
iface vmbr0 inet static
address 91.121.<redacted>
netmask 255.255.255.0
network 91.121.<redacted>.0
broadcast 91.121.<redacted>.255
gateway 91.121.<redacted>.254
bridge_ports eth0
bridge_stp off
bridge_fd 0
iface vmbr0 inet6 static
address 2001:41D0:1:A790::1
netmask 64
post-up /sbin/ip -f inet6 route add 2001:41D0:1:A7ff:ff:ff:ff:ff dev vmbr0
post-up /sbin/ip -f inet6 route add default via 2001:41D0:1:A7ff:ff:ff:ff:ff
pre-down /sbin/ip -f inet6 route del default via 2001:41D0:1:A7ff:ff:ff:ff:ff
pre-down /sbin/ip -f inet6 route del 2001:41D0:1:A7ff:ff:ff:ff:ff dev vmbr0
auto vmbr2
iface vmbr2 inet static
address 10.21.21.254
netmask 255.255.255.0
bridge_ports none
bridge_stp off
bridge_fd 0
pre-up echo 1 > /proc/sys/net/ipv4/ip_forward
pre-up iptables-restore < /etc/iptables.rules
The iptable rule looks like so (along with more ports, but they all look the same more or less):
-A PREROUTING -i vmbr0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.21.21.4:80
-A POSTROUTING -s 10.21.21.0/24 -o vmbr0 -j MASQUERADE
There is a site running using Node.js, proxied by Nginx all running inside the VM.
My Nginx configuration is:
upstream node {
server 127.0.0.1:4567;
}
server {
listen 80;
server_name myDomain.co.uk;
location / {
proxy_pass http://node;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
When pinging my domain, it works fine:
PING myDomain.co.uk (my.ip.address) 56(84) bytes of data.
64 bytes from myHostName.eu (my.ip.address): icmp_req=1 ttl=64 time=0.282 ms
64 bytes from myHostName.eu (my.ip.address): icmp_req=2 ttl=64 time=0.275 ms
64 bytes from myHostName.eu (my.ip.address): icmp_req=3 ttl=64 time=0.284 ms
64 bytes from myHostName.eu (my.ip.address): icmp_req=4 ttl=64 time=0.339 ms
However when trying cURL, it refuses to connect.
curl --verbose myDomain.co.uk
* About to connect() to myDomain.co.uk port 80 (#0)
* Trying my.ip.address...
* Connection refused
* couldn't connect to host
* Closing connection #0
curl: (7) couldn't connect to host
Edit:
I've changed the rules to (as per @FrederikNielsen's advice):
-A PREROUTING -d my.ip.address/32 -p tcp -m multiport --dports 80 -j DNAT --to-destination 10.21.21.4
-A POSTROUTING -s 10.21.21.0/24 -o vmbr0 -j MASQUERADE
-A POSTROUTING -s 10.21.21.0/24 -d 10.21.21.4/32 -p tcp -m multiport --dports 80 -j SNAT --to-source my.ip.address
But still no luck. The error has changed to:
* About to connect() to myDomain.co.uk port 80 (#0)
* Trying my.ip.address...
* Connection timed out
* couldn't connect to host
* Closing connection #0
curl: (7) couldn't connect to host
You are going to do some hairpin NAT'ing.
This question has a pretty good accepted answer that explains how to do it.
Another solution could be to use split-horizon DNS setup, but this involves a bit more setup than hairpin NAT'ing.
Update:
-A PREROUTING -d externalIP/32 -p tcp -m multiport --dports 80 -j DNAT --to-destination 10.21.21.4
-A POSTROUTING -s 10.21.21.0/24 -o vmbr0 -j MASQUERADE
-A POSTROUTING -s 10.21.21.0/24 -d 10.21.21.4/32 -p tcp -m multiport --dports 80 -j MASQUERADE
Update #2:
-A PREROUTING -d externalIP -p tcp --dport 80 -j DNAT --to-destination 10.21.21.4
-A POSTROUTING -s 10.21.21.0/24 -d 10.21.21.4 -p tcp --dport 80 -j SNAT --to-source routerInternalIP