Is there a way to rate limit connection attempts with firewalld?

On our CentOS 6 servers, I've used information from this article to reduce the brute force ssh attempts on our servers, specifically the rate limiting / logging section. Is there a way to do the same thing using firewalld in CentOS 7? I'd prefer to avoid switching back to iptables since it seems firewalld is the direction that the OS is going.

For reference, here's the basic configuration in iptables that we're using (some values are different)

/sbin/iptables -N LOGDROP
/sbin/iptables -A LOGDROP -j LOG
/sbin/iptables -A LOGDROP -j DROP
iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --set
iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent  --update --seconds 60 --hitcount 4 -j LOGDROP

Try with:

firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT_direct 0 -p tcp --dport 22 -m state --state NEW -m recent --set
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT_direct 1 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 30 --hitcount 4 -j REJECT --reject-with tcp-reset
firewall-cmd --reload

A full example: RHEL7: How to mitigate HTTP attacks.

About logging rejecting package FirewallD simply does not support the same level of logging that the old iptables-service did. See https://lists.fedorahosted.org/pipermail/firewalld-users/2014-February/000155.html

But there may be a posible work-around: https://bluehatrecord.wordpress.com/2014/04/17/logging-packet-drops-in-firewalld/


CentOS 7 has changed a few things that people have become comfortable with and they squirm - wiggle away - and run from - the reality of the changes usually.

Many people do not know or realize that firewalld is not a "new" firewall - it is a "front-end" to iptables that Red Hat is incorporating as a GUI capable enabled product add-on. For those familiar with "shorewall" - think in those terms (http://shorewall.org) and shorewall is available for Centos 7 also through the repos - and see also https://www.cyberciti.biz/faq/centos-rhel-shorewall-firewall-configuration-setup-howto-tutorial/ shorewall is not a simple - and/or highly gui but is effectively very powerful that can bond both worlds to together.

I would also add that if you use Webmin - Shorewall it has a graphical interface module that will activate if you install shorewall and reconfigure Webmin to see it. AND no I am not pushing shorewall - nor have any affiliation to the author of either program.

To that end Fail2ban is not Graphical - but is also a "front end" to Iptables as it can scan log files and bans IPs that show the malicious signs -- too many password failures, seeking for exploits, etc. - temporarily or permanently.

Generally Fail2Ban is then used to update firewall rules to reject the IP addresses for a specified amount of time, although any arbitrary other action (e.g. sending an email) could also be configured. Out of the box Fail2Ban comes with filters for various services (apache, courier, ssh, etc).

Fail2ban can be used to create rich text rules as well with firewalld - and the nice thing is firewalld uses xml files that can be edited with any editor quickly without rewriting a firewall-cmd command. Used with WinSCP and EditPadLite administration is simple and fast.

firewalld has equivalent action commands that produce iptables entries like if you want to create a more complex that restricts a port to a specific IP or network, you need to use a rich rule as an example shown below:

 firewall-cmd --zone=OPS --add-rich-rule='rule family="ipv4" source address="xxx.xxx.xxx.0/24" port protocol="tcp" port="9200" accept'

Which will create a netfilter rule as reported by iptables -nL like the following:

 ACCEPT     tcp  --  xxx.xxx.xxx.0/24     0.0.0.0/0            tcp dpt:9200 ctstate NEW

One must remember that while many people do not use a GUI to configure linux which are usually traditionally used as internet servers - there is a "control center" and for "NetworkManager" as "nm-connection-editor", and "firewall-config" which will all launch as graphical tools that make the job easier also.

So many people want to disable firewalld and go "back" to iptables - when the truth is you never left iptables

So the answer is the easiest thing to do is use fail2ban to permanently log ips to a blacklist file and then use a rich text rule to permanently reject that IP. i comes with files already set up that you just point fail2ban to the file and it will do the rest.

There are lots of tutorials and how to setup to use fail2ban to echo the offending ip to a blacklist file and ban it. See e.g. http://www.itadminstrator.com/2017/05/how-to-protect-ssh-with-fail2ban-on.html and https://arno0x0x.wordpress.com/2015/12/30/fail2ban-permanent-persistent-bans/ shows how to echo the ip to blacklist file. I would use the /etc/fail2ban/action.d/firewallcmd-rich-rules.conf file instead of multiport.conf to modify and add the echo commands to as it will permanently drop that IP offending forever until and unless you edit the xml file and take it out.

Here is a command that you put in the actionban= section UNDER the actual actionban command that will check for a duplicate ip in a file called ip.blacklist and then write it there

 if ! grep -Fq <ip> /etc/fail2ban/ip.blacklist; then echo "<ip> # fail2ban/$( date '+%%Y-%%m-%%d %%T' ): auto-add for repeat offender" >> /etc/fail2ban/ip.blacklist; fi

It will make an entry similar to:

197.32.10.180 # fail2ban/2017-11-22 16:18:33: auto-add for repeat offender

It should create the file ip.blacklist if it does not exist in etc/fail2ban

Remember these are instructions for CentOS - and assume you installed fail2ban from a yum repo for your version of Centos 7

Many of these attacks come from countries like China, Russia, the Ukraine, Korea etc - where many of the hackers attackers are hoping to cripple your server (usually removing ONE file you do not what) and then "ransom-ware" the server owner to ask for bitcoin, so I often go into the logs and get IP's - and go to http://whois.com/whois - and dump it in there to get the full CIDR net then edit the xml file and drop the entire subnet it is on.

Initally you use

 firewall-cmd --zone=public --add-rich-rule 'rule family="ipv4" source address=176.15.57.196 reject' --permanent

then do a

 firewall-cmd --reload

After that you can edit the file at etc/firewalld/zones/public.xml <= usually everyone uses "public" as the zone - but use which ever it is. It will make the public.xml file if this is your first time making an entry after the firewall-cmd --reload command as an entry like this (multiple ones depending)

  <rule family="ipv4">
    <source address="xxx.xxx.xx.x/xx"/>
    <reject/>
  </rule>

If the whois page does not list the CIDR of the network use online tools like https://www.ipaddressguide.com/cidr or https://www.derman.com/blogs/IP-Range-to-CIDR-Calculator or others to use the ip range you get from the whois to create a CIDR notation - and put it in the "source address" at the xxx.xxx.xx.x/xx save the file then do the firewall-cmd --reload command. You can change as many as you want and then do the reload command - providing you do not make any mistakes. NO ONE on that net will come into your server again - and they will get a message "network unreachable" - it will also ease the load on your server having to deal with the attacks, fending them off and logging them if they are getting dynamic IP's and coming again. Many countries do not have "anti-hacking" laws like the US and other major countries do, so you have make a decision if really need them visiting your site at all.

One thing not so obvious is that firewalld by default is set NOT TO LOG. It will log to the system journal file but you need to go into etc/firewalld/firewalld.conf and set => LogDenied=all

This is also needed set to that - for other programs like psad and mod-evasive which need the log info.

One can also use modprobe to watch for simple ddos attacks and implement a rule to drop the attacker also. See https://www.certdepot.net/rhel7-mitigate-http-attacks/

Of course you can also change the ssh port number


You can use a lightweight IPS likefail2ban.

It works with firewalld using an action plugin (/etc/fail2ban/action.d/firewallcmd-ipset.conf) that adds banned IPs to an ipset using direct rules.

The default banaction (/etc/fail2ban/jail.conf) is ipables-multiport, but you can create a local.conf for a custom [sshd-ddos] jail using a different banaction.

Check the examples in the fail2ban wiki and the Fedora wiki.


FirewallD rich fule to rate limit SSH-connections to one per minute:

firewall-cmd --add-rich-rule 'rule service name="ssh" accept limit value="1/m"'

Using a rich rule suggested in https://github.com/firewalld/firewalld/issues/70

I'd recommend targeting --zone public with above rate limiting and defining your known points-of-entry into trusted/home/work zone with command like --zone=trusted --add-source=-your-own-IP-here- to bypass rate limiting. Test this first. When your setup works, remember to persist the rules.

Example:

firewall-cmd --zone public --add-rich-rule 'rule service name="ssh" accept limit value="1/m"'
firewall-cmd --zone=trusted--add-source=-your-own-IP-here-
firewall-cmd --runtime-to-permanent