Use fail2ban and FirewallD blacklists to protect your system | Linux China

If you are running a server with public SSH access, you may have encountered malicious login attempts. This article describes how to use two utilities to prevent intruders from entering our system.

To prevent repeated ssh login attempts, let's take a look at fail2ban.

First, let's introduce some terms to those unfamiliar with these applications to do this:

fail2ban: a daemon used to disable hosts with multiple authentication errors. fail2ban will monitor the system D log for any enabled“   Failed verification attempt of "jail". After the specified number of failures is reached, it will add a firewall rule to block the specific IP address for the configured time.

Firewall D: a firewall daemon with D-Bus interface, which provides dynamic firewall. Unless you decide to use traditional iptables, you have installed FirewallD on all supported Fedora and CentOS.

Hypothetical premise

  • The host system has an Internet connection and is either directly exposed to the Internet, or through the DMZ (both are very bad ideas unless you know what you are doing), or there is a port forwarded from the router.
  • Although most of the content may be applicable to other systems, this article assumes that the current system is Fedora (31 and above) or RHEL/CentOS 8. On CentOS, you must use   sudo dnf install epel-release   Enable Fedora EPEL warehouse.

Installation and configuration


It is likely that SSH access has been allowed in a firewall area, but the sshd service itself is not enabled by default. To start it manually without permanently enabling it at startup:

$ sudo systemctl start sshd

Or enable it when the system starts and start it at the same time:

$ sudo systemctl enable --now sshd

The next step is to install, configure and enable fail2ban. As usual, the installation can be done from the command line:

$ sudo dnf install fail2ban

After installation, the next step is to configure the "prison" (the services you want to monitor and prohibit with any threshold you set). By default, IP will be disabled for 1 hour (this is not long enough). The best practice is to use  *. local   The file overwrites the system defaults instead of modifying them directly  *. config   File. If we check my   jail.local, we can see:

# cat /etc/fail2ban/jail.local

# "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

In popular language, after five attempts in the past hour, the IP will be banned for one day. For multiple blocked IPS, you can also choose to increase the blocking time, but this is the subject of another article.

The next step is to configure the prison. Shown in this tutorial is   sshd, but the steps for other services are roughly the same. stay  / etc/fail2ban/jail.d   Create a profile in. This is my file:

# cat /etc/fail2ban/jail.d/sshd.local
enabled = true

That's it! Many configurations are already handled in the packages built for Fedora (tip: I'm the current maintainer). Next, enable and start the fail2ban service:

$ sudo systemctl enable --now fail2ban

I hope there is no immediate error. If not, please use the following command to check the status of fail2ban:

$ sudo systemctl status fail2ban

If it does not start incorrectly, it should be like this:

$ 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

If it is just started, fail2ban is unlikely to display any interesting information, but to check the status of fail2ban and ensure that "prison" is enabled, enter:

$ sudo fail2ban-client status
|- Number of jail:      1
`- Jail list:   sshd

The superior status of sshd "prison" will also be displayed. If multiple "prisons" are enabled, they will be displayed here.

To view the detailed status of a "prison", simply add the "prison" name to the previous command. Here is the output of my system, which has been running for some time. I have deleted the prohibited IP from the output:

$ 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:   ...

Monitoring the fail2ban log file for intrusion attempts can be realized through the "trailing" log:

$ sudo tail -f /var/log/fail2ban.log

tail   Is a good command line tool. By default, it can display the last 10 lines of a file. add to  - f   Tell it to follow the file, which is a good way to observe a file that is still being written.

Because there is real IP in the output content, samples will not be provided here, but it is highly readable. INFO   Line is usually an attempt to log in. If you make enough attempts from a specific IP address, you will see one   NOTICE   The line shows that an IP address is disabled. After the forbidden time is reached, you will see a   NOTICE   Lift the ban.

Note several warning lines. The most common case is that when a prohibition is added, fail2ban finds that the IP address is already in its prohibition database, which means that the prohibition may not work properly. If it is a recently installed fail2ban package, it should be set to firewall D's rich rules. This package switched from ipset mode to rich rule mode in fail2ban-0.11.1-6, so if your fail2ban was installed earlier, it may still try to use ipset mode. This method uses traditional iptables, which is not very reliable.

Firewall D configuration

Passive or active?

There are two strategies that can be used separately or together: passively blacklisting a single IP address or actively blacklisting a subnet permanently according to the country of origin.

For the passive mode, once fail2ban runs for a period of time, it is best to run it again   sudo fail2ban-client status sshd   Let's see what bad guys there are. There are likely to be many prohibited IP addresses. Select one Game trading , and then try to run it   whois. There may be a lot of interesting information in the output results, but for this method, only the country of origin is important. To keep it simple, let's filter out all information except countries.

In this example, we will use some famous domain names:

$ whois | grep -i country
Registrant Country: US
Admin Country: US
Tech Country: US
$ whois | grep -i country
Registrant Country: FR
$ whois | grep -i country
Registrant Country: CN

use   grep -i   The reason is to make   grep   It is case insensitive, and most entries use "country", while some entries are all lowercase "country", so this method can match anyway.

Now that we know the country of origin of the attempted invasion, the question is, "does anyone from this country have a legitimate reason to connect to this computer?" if the answer is no, it should be acceptable to block the whole country.

In terms of function, the active method is not much different from the passive method. However, intrusion attempts from some countries are very common. If your system is neither in these countries nor has any customers from these countries, why not add them to the blacklist now and wait? (LCTT translation note: my experience is that it is too arbitrary to be blacklisted in the category of country. It is suggested that the WHOIS network segment of the IP can be blacklisted, because these network segments often have the same use nature. For example, they are used for user access or IDC hosting, and their security status is roughly the same. Therefore, if there is a malicious attack from an IP of the network segment It can be expected that other IPS in the network segment may also be used to make such an attempt.)

Blacklist scripts and configuration

So how do you do this? Use FirewallD ipset. I developed the following script to automate the process as much as possible:

# Based on the below article

# 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
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

# 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 to the blacklist
for country in $countries; do
    firewall-cmd -q --permanent --ipset=blacklist \
        --add-entries-from-file=./$ && \
        echo "Added $country to blacklist ipset."

# 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 && \
        echo "Added IPs to blacklist ipset."

# 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."
    echo "Adding ipset blacklist to firewalld drop zone."
    firewall-cmd --permanent --zone=drop --add-source=ipset:blacklist

firewall-cmd -q --reload

rm -rf $ipdeny_tmp_dir

This should be installed in  / usr/local/sbin, don't forget to make it executable!

$ sudo chmod +x /usr/local/sbin/firewalld-blacklist

Then create a configuration file  / etc/blacklist-by-country:

# Which countries should be blocked?
# Use the two letter designation separated by a space.

And another profile  / Etc / blacklist by IP, only one IP per line, without any additional formatting.

In this example, 10 countries are randomly selected from ipdeny's regional files:

# ls | shuf -n 10 | sed "s/\.zone//g" | tr '\n' ' '
nl ee ie pk is sv na om gp bn

Now you can run as long as you add at least one country to the configuration file!

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

To verify whether the firewall D blacklist is successful, check   drop   District and   blacklist   ipset.

$ sudo firewall-cmd --info-zone=drop
drop (active)
  target: DROP
  icmp-block-inversion: no
  sources: ipset:blacklist
  masquerade: no
  rich rules:

$ sudo firewall-cmd --info-ipset=blacklist | less
  type: hash:net
  options: family=inet hashsize=4096 maxelem=200000

The second command will output all subnets. These subnets are added based on the blocked countries and may be quite long.

So what should I do now?

Although the monitoring frequency will be high at the beginning, the number of intrusion attempts should decrease with the increase of blacklist over time. Then the goal should be maintenance, not active monitoring.

To this end, I created a SystemD service file and timer so that the subnets of each country maintained by ipdeny are refreshed every month. In fact, everything discussed here can be downloaded from my project.

Are you glad you finished reading the whole article? Now just download the service file and timer to  / / etc/systemd/system /, and enable the timer:

$ sudo systemctl daemon-reload
$ sudo systemctl enable --now firewalld-blacklist.timer

Tags: Linux CentOS server

Posted on Tue, 26 Oct 2021 03:36:28 -0400 by Ron Woolley