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