I want a virtual machine in the cloud (VM1
) to act as TCP proxy for a server (VM2
), so that the IP address of VM2
is not exposed to the clients. Clients should connect to the public IP address of VM1
on port 9735
, and all the traffic should be forwarded to VM2
on the same port. Replies should go the other way around.
VM1
and VM2
are connected via wireguard. Both have two interfaces: the wireguard interface (wg0
), and an internet interface (ens5
, eth0
respectively). VM1
IP address on wg0
is 10.200.200.1
, while VM2
is 10.200.200.2
. The wireguard connection works fine. I can succesfully telnet 10.200.200.2:9735
from VM1
.
The problem arises when I try to telnet on the public IP of VM1
.
I configured iptables on VM1
in this way.
# Enable IP forwarding
# https://serverfault.com/questions/240532/iptables-dnat-not-working
echo 1 > /proc/sys/net/ipv4/ip_forward
# Reset and allow everything
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -t raw -F
iptables -t raw -X
iptables -t security -F
iptables -t security -X
export WAN=ens5
export LAN=wg0
# Filter rules, default accept, log some
iptables -P INPUT ACCEPT
iptables -A INPUT -p tcp --dport 9735 -j LOG --log-level info --log-prefix "fiter_in"
iptables -P OUTPUT ACCEPT
iptables -A OUTPUT -p tcp --dport 9735 -j LOG --log-level info --log-prefix "fiter_out"
iptables -P FORWARD ACCEPT
iptables -A FORWARD -p tcp --dport 9735 -j LOG --log-level info --log-prefix "filter_forward"
iptables -t nat -A PREROUTING -p tcp -i $LAN -j LOG --log-level info --log-prefix "prerouting_fr_wg0"
iptables -t nat -A PREROUTING -p tcp -i $WAN --dport 9735 -j LOG --log-level info --log-prefix "prerouting_9735"
iptables -t nat -A PREROUTING -p tcp -i $WAN --dport 9735 -j DNAT --to-destination 10.200.200.2:9735
iptables -t nat -A POSTROUTING -o $LAN -j LOG --log-level info --log-prefix "postrouting_to_wg0"
iptables -t nat -A POSTROUTING -o $WAN -j LOG --log-level info --log-prefix "postrouting_to_ens5"
iptables -t nat -A POSTROUTING -o $WAN -j MASQUERADE
On VM1
, the iptables forwarding works just fine, I can see the packets being forwarded using tcpdump
.
root@myserver:~# tcpdump -n -A tcp -i wg0
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on wg0, link-type RAW (Raw IP), snapshot length 262144 bytes
19:53:56.838847 IP [client public ip address].16190 > 10.200.200.2.9735: Flags [S], seq 2996679219, win 64240, options [mss 1420,sackOK,TS val 1658363264 ecr 0,nop,wscale 7], length 0
E..<[email protected].......
...?>&....3.........r.........
b...........
On VM2
, tcpdump
output is just nothing. It's like VM2
just does not receive anything.
Any suggestion about how I can further debug this issue?
vm2
is not receiving anything because theAllowedIps
setting on your wireguard interface is blocking the traffic. The easiest solution is to configurevm1
to masquerade traffic outwg0
:This will (a) ensure that only addresses on the wireguard network are seen on your wireguard interfaces, and (b) ensure that replies from
vm2
get routed throughvm1
(otherwise, replies would go outvm2
's default route).(You can find my containerized test setup here.)