Create an account


Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Fedora - Protect your system with fail2ban and firewalld blacklists

#1
Protect your system with fail2ban and firewalld blacklists

<div><p>If you run a server with a public-facing SSH access, you might have experienced malicious login attempts. This article shows how to use two utilities to keep the intruder out of our systems.</p>
<p>To protect against repeated ssh login attempts, we’ll look at <em>fail2ban</em>. And if you don’t travel much, and perhaps stay in one or two countries, you can configure <em>firewalld</em> to only <a href="https://www.linode.com/community/questions/11143/top-tip-firewalld-and-ipset-country-blacklist">allow access from the countries you choose</a>.</p>
<p>First let’s work through a little terminology for those not familiar with the various applications we’ll need to make this work:</p>
<p><strong>fail2ban:</strong> Daemon to ban hosts that cause multiple authentication errors.</p>
<p>fail2ban will monitor the SystemD journal to look for failed authentication attempts for whichever jails have been enabled. After the number of failed attempts specified it will add a firewall rule to block that specific IP address for an amount of time configured. </p>
<p><strong>firewalld:</strong> A firewall daemon with D-Bus interface providing a dynamic firewall.</p>
<p>Unless you’ve manually decided to use traditional iptables, you’re already using firewalld on all supported releases of Fedora and CentOS.</p>
<h2>Assumptions</h2>
<ul>
<li>The host system has an internet connection and is either fully exposed directly, through a DMZ (both REALLY bad ideas unless you know what you’re doing), or has a port being forwarded to it from a router.</li>
<li>While most of this might apply to other systems, this article assumes a current version of Fedora (31 and up) or RHEL/CentOS 8. On CentOS you must enable the Fedora EPEL repo with
<div class="codecolorer-container text default" style="overflow:auto;border:1px solid #9F9F9F;width:435px">
<div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace">sudo dnf install epel-release</div>
</div>
</li>
</ul>
<h2>Install &amp; Configuration</h2>
<h3>Fail2Ban</h3>
<p>More than likely whichever FirewallD zone is set already allows SSH access but the sshd service itself is not enabled by default. To start it manually and without permanently enabling on boot:</p>
<pre class="wp-block-preformatted">$ sudo systemctl start sshd</pre>
<p>Or to start and enable on boot:</p>
<pre class="wp-block-preformatted">$ sudo systemctl enable --now sshd</pre>
<p>The next step is to install, configure, and enable fail2ban. As usual the install can be done from the command line:</p>
<pre class="wp-block-preformatted">$ sudo dnf install fail2ban</pre>
<p>Once installed the next step is to configure a jail (a service you want to monitor and ban at whatever thresholds you’ve set). By default IPs are banned for 1 hour (which is not near long enough). The best practice is to override the system defaults using *.local files instead of directly modifying the *.config files. If we look at my jail.local we see:</p>
<pre class="wp-block-preformatted"># cat /etc/fail2ban/jail.local
[DEFAULT] # "bantime" is the number of seconds that a host is banned.
bantime = 1d # A host is banned if it has generated "maxretry" during the last "findtime"
findtime = 1h # "maxretry" is the number of failures before a host get banned.
maxretry = 5</pre>
<p>Turning this into plain language, after 5 attempts within the last hour the IP will be blocked for 1 day. There’s also options for increasing the ban time for IPs that get banned multiple times, but that’s the subject for another article.</p>
<p>The next step is to configure a jail. In this tutorial sshd is shown but the steps are more or less the same for other services. Create a configuration file inside <em>/etc/fail2ban/jail.d</em>. Here’s mine:</p>
<pre class="wp-block-preformatted"># cat /etc/fail2ban/jail.d/sshd.local
[sshd]
enabled = true</pre>
<p>It’s that simple! A lot of the configuration is already handled within the package built for Fedora (Hint: I’m the current maintainer). Next enable and start the fail2ban service.</p>
<pre class="wp-block-preformatted">$ sudo systemctl enable --now fail2ban</pre>
<p>Hopefully there were not any immediate errors, if not, check the status of fail2ban using the following command:</p>
<pre class="wp-block-preformatted">$ sudo systemctl status fail2ban</pre>
<p>If it started without errors it should look something like this:</p>
<pre class="wp-block-preformatted">$ systemctl status fail2ban
● fail2ban.service - Fail2Ban Service
Loaded: loaded (/usr/lib/systemd/system/fail2ban.service; disabled; vendor preset: disabled)
Active: active (running) since Tue 2020-06-16 07:57:40 CDT; 5s ago
Docs: man:fail2ban(1)
Process: 11230 ExecStartPre=/bin/mkdir -p /run/fail2ban (code=exited, status=0/SUCCESS)
Main PID: 11235 (f2b/server)
Tasks: 5 (limit: 4630)
Memory: 12.7M
CPU: 109ms
CGroup: /system.slice/fail2ban.service
└─11235 /usr/bin/python3 -s /usr/bin/fail2ban-server -xf start
Jun 16 07:57:40 localhost.localdomain systemd[1]: Starting Fail2Ban Service…
Jun 16 07:57:40 localhost.localdomain systemd[1]: Started Fail2Ban Service.
Jun 16 07:57:41 localhost.localdomain fail2ban-server[11235]: Server ready</pre>
<p>If recently started, fail2ban is unlikely to show anything interesting going on just yet but to check the status of fail2ban and make sure the jail is enabled enter:</p>
<pre class="wp-block-preformatted">$ sudo fail2ban-client status
Status
|- Number of jail: 1
`- Jail list: sshd</pre>
<p>And the high level status of the sshd jail is shown. If multiple jails were enabled they would show up here.</p>
<p>To check the detailed status a jail, just add the jail to the previous command. Here’s the output from my system which has been running for a while. I have removed the banned IPs from the output:</p>
<pre class="wp-block-preformatted">$ sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
| |- Currently failed: 8
| |- Total failed: 4399
| `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions |- Currently banned: 101 |- Total banned: 684 `- Banned IP list: ...</pre>
<p>Monitoring the fail2ban log file for intrusion attempts can be achieved by “tailing” the log:</p>
<pre class="wp-block-preformatted">$ sudo tail -f /var/log/fail2ban.log</pre>
<p>Tail is a nice little command line utility which by default shows the last 10 lines of a file. Adding the “-f” tells it to follow the file which is a great way to watch a file that’s still being written to.</p>
<p>Since the output has real IPs in it, a sample won’t be provided but it’s pretty human readable. The INFO lines will usually be attempts at a login. If enough attempts are made from a specific IP address you will see a NOTICE line showing an IP address was banned. After the ban time has been reached you will see an NOTICE unban line.</p>
<p>Lookout for several WARNING lines. Most often this happens when a ban is added but fail2ban finds the IP address already in its ban database, which means banning may not be working correctly. If recently installed the fail2ban package it should be setup for FirewallD rich rules. The package was only switched from “ipset” to “rich rules” as of <em>fail2ban-0.11.1-6</em> so if you have an older install of fail2ban it may still be trying to use the ipset method which utilizes legacy iptables and is not very reliable.</p>
<h3>FirewallD Configuration</h3>
<h4>Reactive or Proactive?</h4>
<p>There are two strategies that can be used either separately or together. Reactive or proactive permanent blacklisting of individual IP address or subnets based on country of origin.</p>
<p>For the reactive approach once fail2ban has been running for a while it’s a good idea to take a look at how “bad is bad” by running <em>sudo fail2ban-client status sshd</em> again. There most likely will be many banned IP addresses. Just pick one and try running <em>whois</em> on it. There can be quite a bit of interesting information in the output but for this method, only the country of origin is of importance. To keep things simple, let’s filter out everything but the country.</p>
<p>For this example a few well known domain names will be used:</p>
<pre class="wp-block-preformatted">$ whois google.com | grep -i country<br />Registrant Country: US<br />Admin Country: US<br />Tech Country: US</pre>
<pre class="wp-block-preformatted">$ whois rpmfusion.org | grep -i country<br />Registrant Country: FR</pre>
<pre class="wp-block-preformatted">$ whois aliexpress.com | grep -i country<br />Registrant Country: CN</pre>
<p>The reason for the <em>grep -i</em> is to make grep non-case sensitive while most entries use “Country”, some are in all lower case so this method matches regardless.</p>
<p>Now that the country of origin of an intrusion attempt is known the question is, “Does anyone from that country have a legitimate reason to connect to this computer?” If the answer is NO, then it should be acceptable to block the entire country.</p>
<p>Functionally the proactive approach it not very different from the reactive approach, however, there are countries from which intrusion attempts are very common. If the system neither resides in one of those countries, nor has any customers originating from them, then why not add them to the blacklist now rather than waiting?</p>
<h4>Blacklisting Script and Configuration</h4>
<p>So how do you do that? With FirewallD ipsets. I developed the following script to automate the process as much as possible:</p>
<pre class="wp-block-preformatted">#!/bin/bash
# Based on the below article
# https://www.linode.com/community/questio...-blacklist # Source the blacklisted countries from the configuration file
. /etc/blacklist-by-country # Create a temporary working directory
ipdeny_tmp_dir=$(mktemp -d -t blacklist-XXXXXXXXXX)
pushd $ipdeny_tmp_dir # Download the latest network addresses by country file
curl -LO http://www.ipdeny.com/ipblocks/data/coun...nes.tar.gz
tar xf all-zones.tar.gz # For updates, remove the ipset blacklist and recreate
if firewall-cmd -q --zone=drop --query-source=ipset:blacklist; then firewall-cmd -q --permanent --delete-ipset=blacklist
fi # Create the ipset blacklist which accepts both IP addresses and networks
firewall-cmd -q --permanent --new-ipset=blacklist --type=hash:net \ --option=family=inet --option=hashsize=4096 --option=maxelem=200000 \ --set-description="An ipset list of networks or ips to be dropped." # Add the address ranges by country per ipdeny.com to the blacklist
for country in $countries; do firewall-cmd -q --permanent --ipset=blacklist \ --add-entries-from-file=./$country.zone &amp;&amp; \ echo "Added $country to blacklist ipset."
done # Block individual IPs if the configuration file exists and is not empty
if [ -s "/etc/blacklist-by-ip" ]; then echo "Adding IPs blacklists." firewall-cmd -q --permanent --ipset=blacklist \ --add-entries-from-file=/etc/blacklist-by-ip &amp;&amp; \ echo "Added IPs to blacklist ipset."
fi # Add the blacklist ipset to the drop zone if not already setup
if firewall-cmd -q --zone=drop --query-source=ipset:blacklist; then echo "Blacklist already in firewalld drop zone."
else echo "Adding ipset blacklist to firewalld drop zone." firewall-cmd --permanent --zone=drop --add-source=ipset:blacklist
fi firewall-cmd -q --reload popd
rm -rf $ipdeny_tmp_dir</pre>
<p>This should be installed to <em>/usr/local/sbin</em> and don’t forget to make it executable!</p>
<pre class="wp-block-preformatted">$ sudo chmod +x /usr/local/sbin/firewalld-blacklist</pre>
<p>Then create a configure file: <em>/etc/blacklist-by-country</em>:</p>
<pre class="wp-block-preformatted"># Which countries should be blocked?
# Use the two letter designation separated by a space.
countries=""</pre>
<p>And another configuration file <em>/etc/blacklist-by-ip</em>, which is just one IP per line without any additional formatting.</p>
<p>For this example 10 random countries were selected from the ipdeny zones:</p>
<pre class="wp-block-preformatted"># ls | shuf -n 10 | sed "s/\.zone//g" | tr '\n' ' '
nl ee ie pk is sv na om gp bn</pre>
<p>Now as long as at least one country has been added to the config file it’s ready to run!</p>
<pre class="wp-block-preformatted">$ sudo firewalld-blacklist % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed
100 142 100 142 0 0 1014 0 --:--:-- --:--:-- --:--:-- 1014
100 662k 100 662k 0 0 989k 0 --:--:-- --:--:-- --:--:-- 989k
Added nl to blacklist ipset.
Added ee to blacklist ipset.
Added ie to blacklist ipset.
Added pk to blacklist ipset.
Added is to blacklist ipset.
Added sv to blacklist ipset.
Added na to blacklist ipset.
Added om to blacklist ipset.
Added gp to blacklist ipset.
Added bn to blacklist ipset.
Adding ipset blacklist to firewalld drop zone.
success</pre>
<p>To verify that the firewalld blacklist was successful, check the drop zone and blacklist ipset:</p>
<pre class="wp-block-preformatted">$ sudo firewall-cmd --info-zone=drop
drop (active) target: DROP icmp-block-inversion: no interfaces: sources: ipset:blacklist services: ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: $ sudo firewall-cmd --info-ipset=blacklist | less
blacklist type: hash:net options: family=inet hashsize=4096 maxelem=200000 entries: </pre>
<p>The second command will output all of the subnets that were added based on the countries blocked and can be quite lengthy.</p>
<h4>So now what do I do?</h4>
<p>While it will be a good idea to monitor things more frequently at the beginning, over time the number of intrusion attempts should decline as the blacklist grows. Then the goal should be maintenance rather than active monitoring. </p>
<p>To this end I created a SystemD service file and timer so that on a monthly basis the by country subnets maintained by ipdeny are refreshed. In fact everything discussed here can be downloaded from my pagure.io project:</p>
<p><a href="https://pagure.io/firewalld-blacklist">https://pagure.io/firewalld-blacklist</a></p>
<p>Aren’t you glad you read the whole article? Now just download the service file and timer to <em>/etc/systemd/system/ </em>and enable the timer:</p>
<pre class="wp-block-preformatted">$ sudo systemctl daemon-reload
$ sudo systemctl enable --now firewalld-blacklist.timer</pre></p>
</div>


https://www.sickgaming.net/blog/2020/06/...lacklists/
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

Forum software by © MyBB Theme © iAndrew 2016