consider the following situation: router with interfaces as follows: lan: 10.25.3.1/24 isp1: some public address isp2: 10.25.254.1/30 (with the entire 10.0.0.0/8 behind it - this is just a peer-to-peer link) now, i want the traffic to isp1 to be masqueraded but not the traffic to isp2 because i'm a part of the 10./8 "internet" (there are routes on the other side that lead to me, too). with current systemd (219) i have to set ipmaquerade for the lan interface which adds the "-s 10.25.3.1/25" rule. this is imho wrong (reversed) since masquerading should be decided depending on the destination, not the source. so the "correct" way should be to set ipmasquerade for isp1 which should create the "-o isp1" rule. also, even if i'm wrong, wouldn't it make more sense to create at least a "-i lan" rule? what is it based on addresses and not the interface? thanks.
IPMasquerade= is a setting you set on the *internal* interface, not the external one. It however results in IP tables rules that are processed on the *external* interfaces, not the internal one. When the packets are processed by the kernel on the external interface, then the incoming interface information is unavailable (which is a kernel limitation), hence we match on the source address instead. Just think of a setup with two internal interfaces (which is common for example for container setups where each container has its own veth link): for one of the internal interfaces IPMAsquerade is set, for the other it isn't. Now you need to write rules that clearly only apply to the packets from the interface where it is set. Hence the source iP address range check. Yupp, it would be good if we could match against the source interface instead for the MASQUERADE rules. But we cannot, the kernel simply does not allow such matches. Sorry.
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.