My VM backend server cannot see external IP routed with Iptables to VPN internal IP

Ecofintech asked:

I am using Iptables to route https traffic from Internet to a internal network through HAproxy.
The Iptables NAt rules are:

iptables -i eth0 -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination 10.0.0.7
iptables -i eth0 -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.0.0.7

iptables -t nat -A POSTROUTING -j MASQUERADE

were 10.0.0.0/24 is a Wireguard VPN (server’s IP is 10.0.0.1, haproxy’s IP is 10.0.0.7)

Then I want to see the origin IP logged in HAproxy, but I can see only the VPN server’s IP:

# tail -f /var/log/haproxy

Jul 14 18:27:02 localhost haproxy[13304]: 10.0.0.1:57539 [14/Jul/2021:18:27:02.199] fe-frontend-https~ fe-frontend-https/<NOSRV> -1/-1/-1/-1/0 503 99 - - SC-- 1/1/0/0/0 0/0 "GET /.env HTTP/1.1

How can I proxy the traffic in a trasnparent way, so HAproxy can log origin external IP?

Thanks

edited:

All Iptables rules:

# iptables -L --line-numbers -v
Chain INPUT (policy ACCEPT 757M packets, 641G bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 ACCEPT     udp  --  virbr10 any     anywhere             anywhere             udp dpt:domain
2        0     0 ACCEPT     tcp  --  virbr10 any     anywhere             anywhere             tcp dpt:domain
3    83841   27M ACCEPT     udp  --  virbr10 any     anywhere             anywhere             udp dpt:bootps
4        0     0 ACCEPT     tcp  --  virbr10 any     anywhere             anywhere             tcp dpt:67
5       12  1008 ACCEPT     icmp --  any    any     10.0.0.0/8           anywhere             icmp echo-request
6        0     0 ACCEPT     icmp --  any    any     10.0.0.0/8           anywhere             icmp echo-reply

Chain FORWARD (policy ACCEPT 482M packets, 578G bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1     589M  441G ACCEPT     all  --  any    virbr10  anywhere             192.168.100.0/24     ctstate RELATED,ESTABLISHED
2     744M  637G ACCEPT     all  --  virbr10 any     192.168.100.0/24     anywhere            
3        0     0 ACCEPT     all  --  virbr10 virbr10  anywhere             anywhere            
4        0     0 REJECT     all  --  any    virbr10  anywhere             anywhere             reject-with icmp-port-unreachable
5      296 11864 REJECT     all  --  virbr10 any     anywhere             anywhere             reject-with icmp-port-unreachable

Chain OUTPUT (policy ACCEPT 753M packets, 664G bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1    83839   28M ACCEPT     udp  --  any    virbr10  anywhere             anywhere             udp dpt:bootpc

# iptables -L -n -t nat -v

Chain PREROUTING (policy ACCEPT 31M packets, 1964M bytes)
 pkts bytes target     prot opt in     out     source               destination         
23743 1296K DNAT       tcp  --  eth0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:443 to:10.0.0.7
 3935  182K DNAT       tcp  --  eth0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:10.0.0.7


Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 9549 packets, 531K bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 RETURN     all  --  *      *       192.168.100.0/24     255.255.255.255     
 4660  280K MASQUERADE  tcp  --  *      *       192.168.100.0/24    !192.168.100.0/24     masq ports: 1024-65535
 7729  704K MASQUERADE  udp  --  *      *       192.168.100.0/24    !192.168.100.0/24     masq ports: 1024-65535
    2   168 MASQUERADE  all  --  *      *       192.168.100.0/24    !192.168.100.0/24    
    0     0 RETURN     all  --  *      *       192.168.100.0/24     224.0.0.0/24        
    0     0 RETURN     all  --  *      *       192.168.100.0/24     255.255.255.255     
    0     0 MASQUERADE  tcp  --  *      *       192.168.100.0/24    !192.168.100.0/24     masq ports: 1024-65535
    0     0 MASQUERADE  udp  --  *      *       192.168.100.0/24    !192.168.100.0/24     masq ports: 1024-65535
    0     0 MASQUERADE  all  --  *      *       192.168.100.0/24    !192.168.100.0/24    
  19M 1143M MASQUERADE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 MASQUERADE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 MASQUERADE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain OUTPUT (policy ACCEPT 20209 packets, 2137K bytes)
 pkts bytes target     prot opt in     out     source               destination   

(mostly are default NAT rules for libvirt)

My answer:


The MASQUERADE rule you specified is too broad. You have specified to masquerade all traffic leaving this host via any interface, thus all traffic gets NATted and its source address rewritten, even though it is unnecessary and in this case undesirable.

(And for some reason the rule is there three times.)

Masquerading should be applied only to traffic leaving the edge toward the Internet, thus you should specify the egress interface (which has your global IP address) in your masquerade rule. For example:

iptables -t nat -o eth0 -A POSTROUTING -j MASQUERADE

The other erroneous masquerade rules should be deleted.


View the full question and any other answers on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.