I'm coming from years of modest use of iptables and its precursors. I'm trying to configure a router with firewalld.
My router has two interfaces, one for the LAN and one for the WAN. The WAN interface is zone "external". The router has a static IP address assigned by the ISP. The ISP also routes a subnet to me (not containing the static IP address). The subnet is globally routable. The LAN machines have addresses in that subnet.
I have three constraints that I want to express but don't know how. Rich rules seem the best bet.
1. I want to masquerade a subset of nodes on the LAN, even though they have routable addresses. Currently I have all masqueraded. How can I be selective? Do I unselect "masquerade" and replace it with an ordered sequence of rich rules, the last of which applies masquerading?
2. I want traffic coming in from the LAN with destination addresses in the masqueraded set to be dropped. In other words, those nodes should only be reached through masquerading. This does not seem to happen by default (as I would have expected).
3. I want the set of services offered by my router itself to be different from the set of services offered by the non-masqueraded nodes.
Motivation for 2: my insecure boxes are a lot more secure if they are safely behind NAT. But they have routable IP addresses and my current firewalld configuration allows all the machines to be directly addressed. I tried to use a rich rule to block this, but it had no effect. I assumed that I should use "rule ipv4 destination address=... drop". That seemed to have no effect. Switching to "source" didn't help. I assume that the masquerade setting somehow overrides.
Motivation for 3: the services that I wish to expose on my LAN nodes are different from those I wish to offer on my router. I don't know how to express this. (Of course a separate firewall on each LAN node would work but that's a lot more work and a lot easier to get wrong.)
On Fri, Jul 31, 2020 at 08:09:07AM -0000, D. Hugh Redelmeier wrote:
I'm coming from years of modest use of iptables and its precursors. I'm trying to configure a router with firewalld.
My router has two interfaces, one for the LAN and one for the WAN. The WAN interface is zone "external". The router has a static IP address assigned by the ISP. The ISP also routes a subnet to me (not containing the static IP address). The subnet is globally routable. The LAN machines have addresses in that subnet.
I have three constraints that I want to express but don't know how. Rich rules seem the best bet.
- I want to masquerade a subset of nodes on the LAN, even though they have routable addresses. Currently I have all masqueraded. How can I be selective? Do I unselect "masquerade" and replace it with an ordered sequence of rich rules, the last of which applies masquerading?
You can masquerade with rich rules and they also support priority.
# firewall-cmd --zone <zone> --add-rich-rule='rich family=ipv4 priority=<priority> source address=<addrA>/<maskA> masquerade' # firewall-cmd --zone <zone> --add-rich-rule='rich family=ipv4 priority=<priority>+1 source address=<addrB>/<maskB> masquerade'
where <zone> is the _egress_ zone.. i.e. the uplink
- I want traffic coming in from the LAN with destination addresses in the masqueraded set to be dropped. In other words, those nodes should only be reached through masquerading. This does not seem to happen by default (as I would have expected).
For this you'll have to use a rich rule with _negative_ priority. See man firewalld.richlanguage man page for details. This is because the "masquerade" from above adds an accept in the "filter_IN_<zone>_allow" chain to allow the traffic being masqueraded. These rich rules will execute before the rules in "filter_IN_<zone>_allow". See "Information about logging and actions" in man firewalld.richlanguage to understand the chain ordering.
# firewall-cmd --zone <zone> --add-rich-rule='rich family=ipv4 priority=<negative_priority> source address=<addrA>/<maskA> destination address=<addrB>/<maskB> drop' # firewall-cmd --zone <zone> --add-rich-rule='rich family=ipv4 priority=<negative_priority> source address=<addrB>/<maskB> destination address=<addrA>/<maskA> drop'
- I want the set of services offered by my router itself to be different from the set of services offered by the non-masqueraded nodes.
Motivation for 2: my insecure boxes are a lot more secure if they are safely behind NAT. But they have routable IP addresses and my current firewalld configuration allows all the machines to be directly addressed. I tried to use a rich rule to block this, but it had no effect. I assumed that I should use "rule ipv4 destination address=... drop". That seemed to have no effect. Switching to "source" didn't help. I assume that the masquerade setting somehow overrides.
firewalld does not yet support FORWARD filtering. It's very, very close to being complete [1]. I would love early feedback if you'd like to experiment [2]. But if you're new to firewalld it may be a bit overwhelming.
[1]: https://github.com/orgs/firewalld/projects/1#card-25963208 [2]: https://github.com/firewalld/firewalld/pull/639
What are the zones involved? You may be hitting an issue [3] related to FORWARD chain policies.
[3]: https://github.com/firewalld/firewalld/issues/177
Motivation for 3: the services that I wish to expose on my LAN nodes are different from those I wish to offer on my router. I don't know how to express this. (Of course a separate firewall on each LAN node would work but that's a lot more work and a lot easier to get wrong.)
Thanks for your answers here and on IRC.
I had tried a couple of different rich rules with negative priority, hoping that they would apply before masquerading, but they didn't seem to. I might have made some mistakes in formulating the rule.
From output of sudo firewall-cmd --info-zone=external services: smtp smtps ssh services: ... ssh masquerade: yes rule priority="-10" family="ipv4" destination address="my.net.ip.addr/24" drop
Even with this rule, I could ssh directly into my LAN from outside. Should that not have been blocked by my rich rule?
The documentation I read never said whether rules were ingress or egress rules for the zone (i.e. the relevant interfaces). That left me uncertain, thinking they might well be either or both. As a result, I had a second rule: rule priority="-10" family="ipv4" source address="my.net.ip.addr/24" drop but it made no difference.
firewalld.richlanguage(5) section "Information about logging and actions" does not say on which chain or at which priority masquerading is applied. So my use of negative priority was an experiment, after trying no priority.
I had a nagging fear that my rules might apply on egress as well. If they did, my LAN would be isolated: all outgoing packets from the subnet would be dropped (because the source address would match). That didn't seem to be the case. But I would like to be able to do egress filtering.
Did I miss these points in the documentation?
Allowing rules to specify that they apply for ingress or egress might be useful. Allowing rules to specify that they apply in forwarding (as you mention) would be useful, but they too should be conditional on the direction. Maybe "source" and "destination", at least in the context of rules applied in both directions.
(I believe that the ignorance of newbies is a non-renewable resource that should not be wasted.)
On Fri, Jul 31, 2020 at 04:11:51PM -0000, D. Hugh Redelmeier wrote:
Thanks for your answers here and on IRC.
I had tried a couple of different rich rules with negative priority, hoping that they would apply before masquerading, but they didn't seem to. I might have made some mistakes in formulating the rule.
From output of sudo firewall-cmd --info-zone=external services: smtp smtps ssh services: ... ssh masquerade: yes rule priority="-10" family="ipv4" destination address="my.net.ip.addr/24" drop
Even with this rule, I could ssh directly into my LAN from outside. Should that not have been blocked by my rich rule?
No - the above will _not_ block SSH outside --> LAN. I suspect it's only being allowed due to the issue I linked in my last email [1]. What is your LAN zone? trusted? internal?
I think misunderstood what you wanted from your original email.
[1]: https://github.com/firewalld/firewalld/issues/177
The documentation I read never said whether rules were ingress or egress rules for the zone (i.e. the relevant interfaces). That left me uncertain, thinking they might well be either or both. As a result, I had a second rule: rule priority="-10" family="ipv4" source address="my.net.ip.addr/24" drop but it made no difference.
firewalld.richlanguage(5) section "Information about logging and actions" does not say on which chain or at which priority masquerading is applied. So my use of negative priority was an experiment, after trying no priority.
That chain suffix/sorting (_pre, _log, _deny, _allow, _post) applies to all rich rules. But the different chain (input, prerouting, postrouting) used by a rich rule varies depending on the rich rule. "service value=... accept" would go to input. forward-port would go to prerouting, masquerade goes to postrouting.
I had a nagging fear that my rules might apply on egress as well.
Masquerading _must_ be applied on postrouting (egress).
With the few exceptions (forward-port, masquerade) firewalld rules apply to the input chain (ingress).
If they did, my LAN would be isolated: all outgoing packets from the subnet would be dropped (because the source address would match). That didn't seem to be the case. But I would like to be able to do egress filtering.
As I said in my last email.. that's not possible yet. But is almost complete. forward/output filtering will be in the next feature release.
Did I miss these points in the documentation?
Allowing rules to specify that they apply for ingress or egress might be useful. Allowing rules to specify that they apply in forwarding (as you mention) would be useful, but they too should be conditional on the direction. Maybe "source" and "destination", at least in the context of rules applied in both directions.
Again. See my links from my last email.
firewalld-users@lists.fedorahosted.org