With StrictForwardPorts=yes firewalld adds rule(s) checking for the original destination port. It sounds like if some entity adds another DNAT rule for the same port matching e.g. on a different address, this rule will also be accepted. I.e.
<zone> <interface name"eth0"> <forward-port port="1234" to-port="1234" to-addr="1.2.3.4" </zone>
will configure port forwarding on eth0 to the address 1.2.3.4, but the rule
tcp dport 1234 ip saddr 5.6.7.8 dnat to 4.3.2.1
will create exception for one single source address redirecting it somewhere else which will be accepted due to the rule
ct original proto-dst 1234 accept
added by firewalld. As this rule only checks for the original destination port.
That is what the original fwmark implementation avoided.
On Wed, Jan 08, 2025 at 10:41:58AM +0300, Andrei Borzenkov via firewalld-users wrote:
With StrictForwardPorts=yes firewalld adds rule(s) checking for the original destination port. It sounds like if some entity adds another DNAT rule for the same port matching e.g. on a different address, this rule will also be accepted. I.e.
Agree.
<zone> <interface name"eth0"> <forward-port port="1234" to-port="1234" to-addr="1.2.3.4" </zone>
will configure port forwarding on eth0 to the address 1.2.3.4, but the rule
tcp dport 1234 ip saddr 5.6.7.8 dnat to 4.3.2.1
will create exception for one single source address redirecting it somewhere else which will be accepted due to the rule
ct original proto-dst 1234 accept
added by firewalld. As this rule only checks for the original destination port.
There are a couple scenarios to consider. Firewalld will accept the DNAT'd packet in both cases.
1) the firewalld DNAT rules executes first (firewalld DNAT wins) - all is well, the other DNAT does not apply
2) the other entity DNAT executes first (firewalld DNAT loses) - firewalld wanted to DNAT the packet - firewalld accepts the packets even though it was technically DNAT'd by another entity - still requires the firewalld user to configure a forward port
Off the top of my head, I don't know how to address this. I really don't want to reintroduce packet marks.
Practically, I'm not sure it's a concern. The user must still explicitly say "DNAT this port" in firewalld for it to occur. It _still_ requires configuration in firewalld. There is still some element of surprise since the packet is DNAT'd to a different target, but much less than the previous situation of "DNAT happened and I didn't configure it".
It's not perfect, but it sucks less.
I'm all for improvement if anyone has better ideas for implementation.
That is what the original fwmark implementation avoided.
Unfortunately that means packet marks cannot be used by the user/other entity, e.g. wireguard. AFAIK, there is no way to prevent firewalld's packet mark from being overwritten by an external entity.
firewalld-users@lists.fedorahosted.org