I want to replace iptables(8) with IPVS for a TCP reverse proxy which involved dual-way NAT.
My current setup using iptables is functionally equivalent to a userspace forwarder (like socat(1)). It has the following setup:
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8000 -j DNAT --to-destination 172.31.1.1:80
# iptables -P FORWARD ACCEPT
iptables -t nat -A POSTROUTING -o eth1 -d 172.31.1.1 -p tcp --dport 80 -j MASQUERADE
The machine has 10.0.0.2 on eth0
and 172.31.0.2 on eth1
. It also has the following routes:
default via 10.0.0.1 dev eth0
172.31.0.0/24 dev eth1
172.31.1.0/24 via 172.31.0.1 dev eth1
I say this is "functionally equivalent" to a userspace proxy because all traffic coming to TCP address 10.0.0.2:8000 is forwarded to the intranet host 172.31.1.1, while on the target host the traffic appears to come from 172.31.0.2 instead of the real host. Neither side sees the actual address of the opposite, only this reverse proxy server.
I'm trying to learn IPVS by replacing this iptables-based setup with Linux Virtual Server. I started with this:
ipvsadm -A -t 10.0.0.2:8000
ipvsadm -a -t 10.0.0.2:8000 -r 172.31.1.1:80 -m
The critical point is, it's frequent that neither the source host nor the target host is reachable on the same link as one of the interfaces. Traffic may need to be sent to a gateway on both sides.
I couldn't figure out why curl http://10.0.0.2:8000/
on this host gives the expected result, while the same command doesn't even establish a TCP connection when run on a host outside of the network (10.0.0.2 / eth0 is public-facing).
Using tcpdump
, I can see a SYN packet to the backend, a SYNACK packet returned, but no ACK afterwards (the 3rd step of TCP 3-way handshake).
I know that a VPN or just tunneling can solve this problem, but I want to do this without either of them.
In case it's relevant, this reverse proxy is running CentOS 7.7 with both SELinux and firewalld disabled.
0 Answers