fail2ban with postfix
A system administrator should care about the security integrity of the server to avoid being compromised. There are a number of security practices that can be practiced to avoid a system being compromised without further installing security packages. Those include disabling the root access through SSH and disabling password-based authentication. A good system administrator would take it further by installing good security packages, for example the Fail2Ban.
Fail2Ban monitors log files and bans any rogue attempt by dynamically modifying the
iptables. Fail2Ban has the capability to send email notifications, like almost any other security packages out there. We will discuss how to install Fail2Ban and also the Postfix.
Postfix will take care of the mail delivery. Since most servers do not open SMTP port 25 for various reasons, the strategy here is to relay the email from Postfix to third-party email services, for example the Mailgun. That is what we are going to do.
Before that, a few security practices worth doing
- Ordered List ItemChange SSH port from the standard port 22 to something else.
- Disable SSH root login.
- Public-private key pair is recommended for SSH, then disable password authentication.
- Install ufw on Debian-based system, activate it and allow only certain ports to be accessed.
Now, let's install fail2ban.
$ sudo apt-get install fail2ban comment: add custom ssh entry based on jail.conf with custom ports $ sudo vim /etc/fail2ban/jail.local
fail2ban maintains configuration at
/etc/fail2ban/jail.conf. Best if we do not edit this file, instead create a new file in the same directory, the
jail.local. Settings in
jail.local override the ones
jail.conf. Here is an example with port 1234 as our custom SSH port.
[SSH] enabled = true port = ssh,sftp,1234 filter = sshd logpath = /var/log/auth.log maxretry = 5
To enable email notification with
postfix, let's further edit the
[DEFAULT] mta = mail destemail = [email protected] sendername = Fail2Ban is Speaking Here action = %(action_mwl)s
In the original
jail.conf, fail2ban sets the
sendmail as the default MTA. I had a bad experience with
sendmail, which I will discuss below. Here are a few things to take note of the configuration above:
- action = %(action_mwl)s specifies the
fail2banto include information about the offending attacker, including the specific log and IP address.
- destemail specifies destination email which the notification should be sent to. Now, let's get the
Banning is great, but not enough. We need to know when that would happen and who is the offender. It would be great if fail2ban can send an email notification about that. So, let's install postfix as our mail transfer agent (MTA). We need
mailutils so that we can use the
libsasl2 modules as the authenticating mechanism between
postfix and Mailgun. Then, edit the
postfix configuration file
main.cf to add/modify the lines specified below.
$ sudo apt-get install postfix mailutils libsasl2-modules $ sudo vim /etc/postfix/main.cf
inet_interfaces = loopback-only relayhost = [smtp.mailgun.org]:587 smtp_sasl_auth_enable = yes smtp_sasl_password_maps = static:[email protected]:password smtp_sasl_security_options = noanonymous
Couple things to take note here:
- inet_interfaces = loopback-only specifies that only local applications can use
- smtp_sasl_security_options = noanonymous specifies that no one else can use
postfixto deliver mail through Mailgun.
postfix afterward and let's try it by issuing this command:
echo "This is the body of the email" | mail -s "This is the subject line" [email protected]
Initially I tried using sendmail.
$ sudo apt-get install sendmail sendmail-bin
However, I could not get it to work. I removed it and that's where the nightmare started. Shortly after removing
sendmail thoroughly with
apt-get purge command, my
dhcp service went kaput. I was suddenly disconnected from the SSH session.
Upon further interrogating with
systemctl status networking.service and reading the log file
/var/log/daemon.log, I realized that the
dhclient was trying to reach for
sendmail, as if without
sendmail it would not establish connection to the switch/router. Effectively, the VPS was cut out off the internet. At the same time, disk read and write spiked. The
dhclient was writing a lot of errors mesages to the
daemon.log and also to the
syslog. If I did not notice this sooner, the whole VPS would be maxed out because within mere three hours, almost 1 GB of error log accumulated.
How to mitigate this problem? According to this thread on AskUbuntu, delete all
sendmail scripts in
/etc/dhcp, then restart the networking by issuing command
sudo systemctl restart networking.service. Watch the status for any weird things, should they occur.
This happened because even with
sendmail was not being thoroughly cleaned from the system.
Securing Port 53
I put this section up after configuring my
fail2ban on the Rene Azaria to protect Rene from being a vector/zombie in a DNS reflection/amplification attack. These are the changes I made.
I created new file
/etc/fail2ban/filter.d/iptables-dns.conf with the following contents:
[Definition] failregex = fw-dns.*SRC=<HOST> DST ^.* security: info: client #.*: query \(cache\) './(NS|A|AAAA|MX|CNAME)/IN' denied ignoreregex =
Added directives in
[iptables-dns] enabled = true ignoreip = 127.0.0.1 filter = iptables-dns action = iptables-multiport[name=iptables-dns, port="53", protocol=udp] bantime = 86400 findtime = 120 maxretry = 1
And I ran these
# First command $ sudo iptables \ -A INPUT `# append to the INPUT chain` \ -p udp -m udp `# for UDP protocol` \ --dport 53 `# if dest port is 53` \ -m limit --limit 25/sec \ -j LOG --log-prefix "fw-dns " \ --log-level 7 # Second command $ sudo iptables \ -A INPUT `# append to the INPUT chain` \ -p udp `# for UDP protocol` \ --dport 53 -m string `# if dest port is 53` \ --from 50 --algo bm --hex-string '|0000FF0001|' \ -m recent --set --name dnsanyquery # Third command $ sudo iptables \ -A INPUT \ -p udp --dport 53 -m string \ --from 50 --algo bm --hex-string '|0000FF0001|' \ -m recent --name dnsanyquery --rcheck --seconds 1 --hitcount 1 -j DROP
The original tutorial by Freek limits the connection to 5/sec. I thought it was too low, so I changed it to 25/sec. Also, the option
--mask from the original tutorial returned error. I have no idea why.
Crossed my fingers. I hope this is good enough to avoid being a vector. I'll be constantly monitoring my Pi-hole instance.