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.
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?
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
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).
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'
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.
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.)