Post

ENG | A Guide to SSH Hardening Using Fail2Ban on Fedora

ENG | A Guide to SSH Hardening Using Fail2Ban on Fedora

Introduction

I wanted to limit the number of lines written into journal to reduce disc writes and perhaps a bit of CPU usage. iotop command showed that journalctl is responsible for the majority of disc activity. journalctl -f showed lots of failed ssh logins despite ssh is configured to use a non-standard port on my router. I found that fail2ban is likely the default solution on Fedora.

Fail2ban works by scanning log files and temporarily (e.g. for two hours) bans IP addresses with unsuccesfull ssh logins.

Installation and config

The installation is straightforward, but an user-specific config has to be created. After that, the fail2ban service must be started.

Note, that port is port on which SSH service is running on the server, not the one which is redirected on a router.

Basically all commands mentioned must be run with root privileges.

1
2
3
4
su
dnf in fail2ban
vim /etc/fail2ban/jail.local 
cat /etc/fail2ban/jail.local
1
2
3
4
5
6
[sshd]
enabled = true
port = 22
filter = sshd
maxretry = 3
bantime = 7200
1
2
3
systemctl enable fail2ban
systemctl start fail2ban
systemctl status fail2ban

Also feel free to change log level in /etc/fail2ban/fail2ban.conf if there are many messages about repeated attempts in log file, you won’t read them anyways.

Useful commands

Here are some useful commands to monitor and manage your Fail2Ban installation.”

Checking status

1
fail2ban-client status sshd
1
2
3
4
5
6
7
8
9
Status for the jail: sshd
|- Filter
|  |- Currently failed: 10
|  |- Total failed:     84
|  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned: 19
   |- Total banned:     30
   `- Banned IP list:   82.157.22.34 43.153.112.182 179.41.2.183 43.134.175.129 143.244.172.59 219.117.234.181 97.74.86.61 212.33.206.249 138.197.77.205 2.228.25.92 142.171.123.71 43.159.194.228 188.219.54.66 103.140.194.120 43.159.62.162 106.51.1.72 165.154.131.4 180.213.3.2 180.76.105.165

Unbanning IP

1
fail2ban-client unban 192.168.1.1

Checking fail2ban log

1
tail -f /var/log/fail2ban.log
1
2
3
4
5
6
7
8
9
10
2023-10-19 09:28:03,189 fail2ban.filter         [502590]: INFO    [sshd] Found 165.154.131.4 - 2023-10-19 09:28:02
2023-10-19 09:28:03,444 fail2ban.actions        [502590]: NOTICE  [sshd] Ban 165.154.131.4
2023-10-19 09:28:05,440 fail2ban.filter         [502590]: INFO    [sshd] Found 165.154.131.4 - 2023-10-19 09:28:05
2023-10-19 09:28:35,439 fail2ban.filter         [502590]: INFO    [sshd] Found 180.76.105.165 - 2023-10-19 09:28:34
2023-10-19 09:29:09,689 fail2ban.filter         [502590]: INFO    [sshd] Found 180.213.3.2 - 2023-10-19 09:29:09
2023-10-19 09:29:09,739 fail2ban.actions        [502590]: NOTICE  [sshd] Ban 180.213.3.2
2023-10-19 09:29:11,940 fail2ban.filter         [502590]: INFO    [sshd] Found 180.213.3.2 - 2023-10-19 09:29:11
2023-10-19 09:30:17,689 fail2ban.filter         [502590]: INFO    [sshd] Found 180.76.105.165 - 2023-10-19 09:30:17
2023-10-19 09:30:19,439 fail2ban.filter         [502590]: INFO    [sshd] Found 180.76.105.165 - 2023-10-19 09:30:19
2023-10-19 09:30:20,045 fail2ban.actions        [502590]: NOTICE  [sshd] Ban 180.76.105.165

Checking firewall rules

1
firewall-cmd --list-all
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
FedoraWorkstation (active)
  target: default
  icmp-block-inversion: no
  interfaces: enp0s31f6
  sources: 
  services: dhcpv6-client mdns samba-client ssh
  ports: 1025-65535/udp 1025-65535/tcp
  protocols: 
  forward: yes
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
        rule family="ipv4" source address="43.159.194.228" port port="22" protocol="tcp" reject type="icmp-port-unreachable"
        rule family="ipv4" source address="103.140.194.120" port port="22" protocol="tcp" reject type="icmp-port-unreachable"
        rule family="ipv4" source address="43.159.62.162" port port="22" protocol="tcp" reject type="icmp-port-unreachable"

Or nft list ruleset, output is too long as it includes all firewall rules in details.

Checking system logs

To dig deeper into system logs, the following commands can be helpful.

CommandMeaning
journalctl -rReverse, most recent messages first
journalctl -r -n 10Recent 10 messages
journalctl -fFollow, like tail -f display messages as they are logged
journalctl -xeu sshd.serviceList entries for unit sshd.service, most recent entries, with extra info

SELinux issue (2024-05-14)

Solved by Fedora 39 Update (sudo dnf -y up) on 2024-05-16, left here for future troubleshooting.

Today I found it does not work. Running journalctl -r while attempting to start the service revealed this.

1
2
3
4
5
6
7
8
9
10
11
12
May 14 01:43:07 marten setroubleshoot[720475]: SELinux is preventing fail2ban-server from create access on the sock_file fail2ban.sock. For complete SELinux messages run: sealert -l e65b9b42-9d32-4a8f-9758-5b1ff7d436aa
May 14 01:43:07 marten setroubleshoot[720475]: SELinux is preventing fail2ban-server from create access on the sock_file fail2ban.sock.

                                               *****  Plugin catchall (100. confidence) suggests   **************************

                                               If you believe that fail2ban-server should be allowed create access on the fail2ban.sock sock_file by default.
                                               Then you should report this as a bug.
                                               You can generate a local policy module to allow this access.
                                               Do
                                               allow this access for now by executing:
                                               # ausearch -c 'fail2ban-server' --raw | audit2allow -M my-fail2banserver
                                               # semodule -X 300 -i my-fail2banserver.pp
1
sealert -l e65b9b42-9d32-4a8f-9758-5b1ff7d436aa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
SELinux is preventing fail2ban-server from create access on the sock_file fail2ban.sock.

*****  Plugin catchall (100. confidence) suggests   **************************

If you believe that fail2ban-server should be allowed create access on the fail2ban.sock sock_file by default.
Then you should report this as a bug.
You can generate a local policy module to allow this access.
Do
allow this access for now by executing:
# ausearch -c 'fail2ban-server' --raw | audit2allow -M my-fail2banserver
# semodule -X 300 -i my-fail2banserver.pp


Additional Information:
Source Context                system_u:system_r:fail2ban_t:s0
Target Context                system_u:object_r:var_run_t:s0
Target Objects                fail2ban.sock [ sock_file ]
Source                        fail2ban-server
Source Path                   fail2ban-server
Port                          <Unknown>
Host                          marten
Source RPM Packages
Target RPM Packages
SELinux Policy RPM            selinux-policy-targeted-39.5-1.fc39.noarch
Local Policy RPM              fail2ban-selinux-1.0.2-13.fc39.noarch
Selinux Enabled               True
Policy Type                   targeted
Enforcing Mode                Enforcing
Host Name                     marten
Platform                      Linux marten 6.8.8-200.fc39.x86_64 #1 SMP
                              PREEMPT_DYNAMIC Sat Apr 27 17:42:13 UTC 2024
                              x86_64
Alert Count                   7
First Seen                    2024-05-08 20:30:10 CEST
Last Seen                     2024-05-14 01:43:04 CEST
Local ID                      e65b9b42-9d32-4a8f-9758-5b1ff7d436aa

Raw Audit Messages
type=AVC msg=audit(1715643784.130:19346): avc:  denied  { create } for  pid=720454 comm="fail2ban-server" name="fail2ban.sock" scontext=system_u:system_r:fail2ban_t:s0 tcontext=system_u:object_r:var_run_t:s0 tclass=sock_file permissive=0


Hash: fail2ban-server,fail2ban_t,var_run_t,sock_file,create

It seems to be discussed here

References

This post is licensed under CC BY 4.0 by the author.