If I remember correctly, the 'flow' for a packet coming in would be:
I've tested this on some EC2 instances: one public and one private. Both running apache with a simple webpage, one saying 'gateway' and one saying 'node'.
Before adding IP tables rules I can curl a simple webpage and it correctly shows it's from my 'gateway' instance. I then do the following on the gateway:
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/10-forwarding.conf
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 10.0.100.154
sudo iptables -A FORWARD -i eth0 -p tcp --dport 80 -j ACCEPT
sudo iptables -t nat -A POSTROUTING -p tcp --dport 80 -j SNAT --to 10.0.0.160
This allows me to curl the public IP, where it's NAT'd to the target internal VM and correctly forwarded/NAT'd for the response. I've set up the private subnet without any external routing, so unless it's routing to the internal range, it's not going anywhere. It works as hoped!
If you've multiple interfaces then you should be able to lock down the FORWARD
rule a bit better with additions of -i eth0 -o wg0
to some rules, and the POSTROUTING
rule with a -o wg0
.
So I think your rules should be:
# dnat to target VPN VM
iptables -t nat -A PREROUTING -i eth0 -p tcp -m multiport --dports 80,443 -j DNAT --to-destination $WIREGUARD_CLIENT_ADDRESS
# forward between interfaces for new conns
iptables -A FORWARD -i eth0 -o wg0 -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT
# allow forwarding related traffic - no need for both sets of -i/-o as we can just allow related
iptables -A FORWARD -m state ESTABLISHED,RELATED -j ACCEPT
# postrouting for VPN
iptables -t nat -A POSTROUTING -o wg0 -p tcp -m multiport --dports 80,443 -j MASQUERADE