While playing around with keeplived, I came across this weird (or is it?) behaviour.
The scenario is as follows:
An internal network that has a gateway ( call it gw ) and a bunch of hosts (one of them called ih1) . Another host (call it ha) that has 2 interfaces : one in the public network a second in the internal one. An external host (eh1)
[ha] is a keepalived instance to route traffic to internal hosts that offer a service says smtp. [ih1] is an smpt server, it's default gateway is [gw]
from [eh1] nc [ha] 25 doesn't work, and if fails in a manner I didn't expect at all.
When the initial packet hits [ih1] it replies through its default gateway, [eh1] receives the reply but the strange thing is instead of the public ip of [gw] ( as one would expect because [gw] is supposed to be masquerading) it gets a reply with the actual ip address of [ih1]. i.e : [gw] is forwarding the packets, not masquerading them. Of course [eh] has no idea how to reach directly [ih1] so it fails to establish a connection.
Digging yields that all packets originating from [ih1] in reply to [eh] request are not going through the POSTROUTING chain of iptable's nat table.
But if [ih1] initiates the connection (say ping [eh1] or ssh [eh1] ) it works as it is supposed to.
Comparing both situations the only thing that jumps to mind is in the first [gw] never say the initial SYN packet, all it saw was SYN/ACK reply.
EDIT: where I_LAN is internal lan : 172.16.0.0/24 and E_LAN is external lan : 192.168.0.0/24
[eh1]-- E_LAN -- --------- ---E_LAN--[ha]--I_LAN--| switch |--I_LAN--[gw]--ELAN-- --------- | [ih1]