Firewalld Annoyances
What's the best way to get an EL7-based system to operate in an implicit-deny stance?
Under EL6, you'd just set the INPUT chain policy to "DROP", add just the exceptions you needed for things like SSH (and ESTABLISHED/RELATED to ensure that yum worked) and you were good to go. It seems like firewalld doesn't really offer a posture that doesn't at least send and ICMP-host-prohibited response to people probling your systems. Switching the default zone to the "drop" zone is more functionally-limiting than even just the EL6 method.
Personally, I'd rip firewalld out and just run naked iptables, but our IA team informs us that we have to run firewalld because that's the approved host-based firewall solution for RHEL7.
Ideas for how best to get back my RHEL6 behavior under firewalld? Right now, I'm about ready to murder my IA guys for focing me to have to screw with firewalld when I've got nine million things I'd rather be working on.
Responses
How about using firewalld's direct rules? These are iptables-syntax rules which are processed first in the INPUT chain:
# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
INPUT_direct all -- 0.0.0.0/0 0.0.0.0/0
...
DROP all -- 0.0.0.0/0 0.0.0.0/0 ctstate INVALID
REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
(if you weren't already aware, firewalld is just a fancy state machine to iptables configuration)
You could then put all your ALLOW rules in the direct rules, add an explicit DROP at the end of the direct rules, and no traffic would never get processed beyond the INPUT_direct chain.
See "Direct Options" in man firewall-cmd for full syntax.
Yes, I understand.
Writing rules is easy:
# firewall-cmd --direct --add-rule ipv4 filter INPUT_direct 10 -p tcp -m tcp --dport 22 -j ACCEPT
success
# firewall-cmd --direct --add-rule ipv4 filter INPUT_direct 20 -j DROP
success
Nice options to see rules in a compact format:
# firewall-cmd --direct --get-all-rules
ipv4 filter INPUT_direct 10 -p tcp -m tcp --dport 22 -j ACCEPT
ipv4 filter INPUT_direct 20 -j DROP
or:
# firewall-cmd --direct --get-rules ipv4 filter INPUT_direct
10 -p tcp -m tcp --dport 22 -j ACCEPT
20 -j DROP
These are starting to make the old way look pretty ugly:
# iptables -S INPUT
-P INPUT ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -j INPUT_direct
-A INPUT -j INPUT_ZONES_SOURCE
-A INPUT -j INPUT_ZONES
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -j REJECT --reject-with icmp-host-prohibited
# iptables -S INPUT_direct
-N INPUT_direct
-A INPUT_direct -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT_direct -j DROP
If you want ICMP returns, then don't use the explicit -j DROP. As you can see, firewalld's INPUT chain already has an explicit -j REJECT --reject-with icmp-host-prohibited at the end.
The inverse of your loopback rule already exists matching on lo, and that scales to interface names beyond eth0 so I didn't add that one.
Does that all do what you want?
I think I understand, though I don't really see much difference between adding direct rules into INPUT or INPUT_direct. Sure the name is different but the end result ends up being the same. Why does it matter what the chain is called?
firewalld doesn't offer an implicit drop on a chain afaics, however it can put an explicit drop on a zone with --set-target=DROP, and you can add an explicit direct rule drop as above. Again the end result is the same, why does it matter where you do it?
I'm not actually modifying the core chains' behaviors (e.g., I'm not directly manipulating the INPUT chain, I'm manipulating the INPUT_direct chain).
Yeah, this isn't a feature of firewalld. The whole idea is to act as a frontend to iptables configuration so that the old method of modify-the-rules-file-and-restart-the-service (dropping the conntrack table in the process) becomes obsolete.
But again, why is this method a requirement for you to implement firewall rules? Just add direct rules to the firewall and let them land where firewalld puts them. Much like your requirements folks are saying "use firewalld" rather than "achieve this effective end-state", are you focusing too much on "use the INPUT chain in the old iptables method" rather than "achieve this effective end-state"? :)
Welcome! Check out the Getting Started with Red Hat page for quick tours and guides for common tasks.
