Dealing with a layer 4 network turned out harder than expected, because all the rules I learnt don't seem to apply. I want to run a service on a VM ("backend") that is protected against common attacks by not giving it a public IP. Only a single port shall be forwarded from the publicly visible head node ("head"). The service behind that port is safe against common attacks.
The idea is that if an attacker manages to compromise "head", e.g. through a vulnerability with whatever service, or a temporary outage of the GCE firewall, there is some time left to respond until he makes his way to "backend". So, if an intrusion is detected on "head", the "backend" could be shut down automatically in an instant.
In short:
VM "head" with a public IP forwards port XXXX to VM "backend".
I managed to set this up with iptables and DNAT, but observed that source IPs of forwarded packets are replaced with the local IP of "head". If there was a way to preserve original source IPs, this would be the preferred perfect solution. How?
Setting this up with a load balancer seems like overkill for a single instance and didn't work for me yet, because there's no way to specify "head" as public entry point. I'm afraid that with another dedicated public IP for the load balancer, "backend" would be exposed to attacks from outside. I may be wrong, though.
Any idea how to go about with this scenario?
Thanks in advance.
Faizan, please forget the previous suggestion. Here's a solution that was now tested and proven in a more complete production network.
The challenge with port forwarding in GCE is that instances only have a single network interface, so packets forwarded with DNAT get their source IP replaced by SNAT immediately when they run through the POSTROUTING chain. As this happens before they reach their destination instance, it looks like DNAT didn't work. The fix now is to protect forwarded packets after DNAT from immediate SNAT by skipping that rule in POSTROUTING. The second rule below does exactly that:
iptables -t nat -A PREROUTING -i eth0 -p tcp -d 192.168.1.4 --dport 80 -j DNAT --to-destination 192.168.1.6
iptables -t nat -A POSTROUTING -o eth0 -p tcp -d 192.168.1.6 --dport 80 -j RETURN
The above rules can be repeated for any number of ports to be forwarded. The final rule below ensures all instances in the local network have Internet access w/o them having a public IP (this rule replaces the MASQUERADE rule suggested in the GCE documentation):
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 192.168.1.4
Note that a GCE firewall rule must allow all forwarded ports from anywhere, on both the head node and the service node.
This solution enables port forwarding to instances w/o a public IP, while those instances also have full access to the Internet. The latter also requires IP Forwarding to be enabled for the head node, and a default route added to the subnetwork, as explained in the current documentation. Would be great if this example could be added to the documentation.
Forgot to mention the current documentation: https://cloud.google.com/compute/docs/networking Section "Configure a NAT gateway"