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.
- 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 [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
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 [sshd] 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: Starting Fail2Ban Service... Jun 16 07:57:40 localhost.localdomain systemd: Started Fail2Ban Service. Jun 16 07:57:41 localhost.localdomain fail2ban-server: 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 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 google.com | grep -i country Registrant Country: US Admin Country: US Tech Country: US $ whois rpmfusion.org | grep -i country Registrant Country: FR $ whois aliexpress.com | 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:
#!/bin/bash # Based on the below article # https://www.linode.com/community/questions/11143/top-tip-firewalld-and-ipset-country-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/countries/all-zones.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 && \ 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 && \ 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
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. countries=""
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. success
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 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:
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