I have a machine with two interfaces that have different routeable IPv4 addresses. To return traffic on the right interface, I used this answer and comment, and it works: I can ssh into the machine using either IP address. (I don't know if this has any impact, but it might have.)
Now I added the following iptables rules for reverse proxying / DNAT using this answer. My boot script now looks like:
# eth0 is automatically brought up and gets 192.168.1.2 as IP sudo ip link set eth1 up sudo ip addr add 192.168.2.2/24 dev eth1 sudo ip rule add from 192.168.2.2 table frometh1 sudo ip route add default via 192.168.2.1 dev eth1 table frometh1 sudo iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j DNAT --to-destination 10.0.0.1:443 sudo iptables -t nat -A PREROUTING -i eth1 -p tcp -m tcp --dport 443 -j DNAT --to-destination 10.0.0.1:443 sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE sudo iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE echo 1 > /proc/sys/net/ipv4/ip_forward
-i eth* was omitted and the DNAT rule was just one command. The MASQUERADE rules were also one command by exchanging
-o eth* for
-d 10.0.0.1. I split them in an attempt to make the interfaces explicit, in case iptables implicitly takes one of the interfaces.
When I try to reach
192.168.1.2:443, the traffic is forwarded and masqueraded as expected. The hit counter for the correct DNAT rule in the PREROUTING table is incremented and the right MASQUERADE rule is incremented. I can successfully build a TCP connection.
When trying to reach
192.168.2.2:443, I can see the traffic incoming on the interface, and the hit counter for correct DNAT rule in the PREROUTING table is incremented. But there is no outgoing packet and neither of the two MASQUERADE rules in POSTROUTING is incremented. The TCP SYN never reaches the remote system (
Note that it does not matter if the forwarding happens through eth0 or eth1, it's fine to forward the traffic to the target (
10.0.0.1) over either eth0 or eth1.
Why do the iptables rules work only for eth0 and not for eth1?
Edit: It might be relevant to know that proxying in userspace works fine:
mkfifo /tmp/fifo sudo nc -kvlp 443 </tmp/fifo | nc 10.0.0.1 443 >/tmp/fifo
Allows traffic to flow both ways, as described in this blog. The problem with this solution is that the remote end sees only one, persistent TCP connection. It should see one connection per client and handle multiple clients simultaneously.