It was time to change out server security from using Fail2Ban to a more robust security package – ConfigServer Firewall (CSF). Fail2Ban has done a great job over the years with doing temporary bans on attackers going after services such as POP, SMTP, IMAP, and others.
But if you are looking for a more dynamic firewall solution for Ubuntu, ConfigServer Firewall (CSF) may be a good solution for a good security suite that allows for a higher degree of system protection.
ConfgServer Firewall can even check your core operating system files on a regular basis and uses hashes to determine if any files were changed. CSF also will watch processes and alert you whenever your load is over a certain amount. Plus the features that Fail2Ban offers with banning – plus the ability to do a more permanent ban after the same IP address (or IP adddress range) continues to attack for a certain number of times.
I’ve only had the software installed for a few days – but it is amazing to see all of the things that go on that you may not have known about.
One big event that I was starting to see with our servers was attacks against our customer websites. Because I believe in providing the best security for website hosting to our customers, I enacted CSF along with some other changes (see the other two posts about protecting the admin folders for Joomla and WordPress sites). When it comes down to it, website hosting customers just want their site secure and not to be hacked – so requiring an extra layer of security is a small annoyance but it pays off by having a much more secure website.
Enough background information as to why I installed it and some of the features of CSF. Let’s get into installing CSF on Ubuntu 12.04
First, download it:
wget http://www.configserver.com/free/csf.tgz
That will download the file to your computer. Next, unzip it:
tar -xzf csf.tgz
Now, go into the folder where the files were unzipped and run the install script:
cd csf
sudo bash install.sh
The ConfigServer Firewall should now be unzipped and installed. You will find the configuration files in the /etc/csf directory.
Now, you need to configure the software. Open up the csf.conf file in the /etc/csf directory. There are a lot of notes in that file on how to configure and how to set the settings. Set these up to your liking. Definitely ensure that you change the TESTING = “1” line to TESTING = “0”. Also ensure that you set your TCP_IN, TCP_OUT, UDP_IN, and UDP_OUT variables correctly. Don’t forget to add in all ports – especially SSH (or however you get into your server) otherwise you will lock yourself out.
There are other files that you should be aware of. If you want to specifically always make sure that some IP addresses are never blocked, open up the /etc/csf/csf.allow file. Put one IP address per line (or you can do a range – such as 1.2.3.4/24 where 24 is the subnet bits).
In addition, if you run a mail server and want to prevent some connections from known spammers at the firewall level, open the /etc/csf/csf.blocklists file. There are many different providers that keep a list of IP address ranges that are known to be a nuisance so you can “uncomment” those lines by just removing the “#” sign in front of the list. Those that I’ve decided to use include SPAMDROP, SPAMEDROP, DSHIELD, HONEYPOT, BFB, and OPENBL.
Once you have your configuration set how you want it, you now need to start the two services that make ConfigServer Firewall work:
sudo service csf start
sudo service lfd start
If everything is configured properly, then the firewall should be up and active!
CSF.Conf Setting Ideas
Here are a few csf.conf setting ideas that you may want to consider. Of course, it fully depends upon what your server does.
LF_DAEMON = “1”
- The LF Daemon is the service that will watch certain logs on your server for attempted brute force attacks. The LF Daemon is basically the same as Fail2Ban. By setting LF_DAEMON to 1, it enables the feature. Then you will need to go to the section in the CSF.conf that sets the ban limits (also shown in this post just below)
SMTP_BLOCK = “1”
- If you run a mail server on your system, I would HIGHLY recommend that you sent the SMTP_BLOCK to 1. This ensures that only the actual mail service (postfix, exim, etc) has the authority to send out messages to the Internet. One of our customer’s websites was attacked about a year ago and they were able to upload a script that was able to bypass all of the mail system and send out spam directly to the Internet. By setting SMTP_BLOCK to 1, it will prevent this from occurring. Also note to set “SMTP_ALLOWUSER” and “SMTP_ALLOWGROUP” with the user accounts and groups that the mail server actually runs from.
SMTP_ALLOWLOCAL = “1”
- Definitely ensure that this is set to “1” to allow your local server to send messages using the loopback connection, especially if you have SMTP_BLOCK set to 1.
SMTP_ALLOWUSER = “<users>”
SMTP_ALLOWGROUP = “<groups>”
- In our case, we use Exim as our mail system. On Ubuntu, Exim runs as the “Debian-exim” user /group. Therefore, the SMTP_ALLOWUSER and SMTP_ALLOWGROUP is set to “Debian-exim” in our case. If you leave any of the proper users/groups out when you have SMTP_BLOCK set to 1, your mail service itself won’t be able to send outgoing e-mail.
SYNFLOOD = “1”
SYNFLOOD_RATE = “100/s”
SYNFLOOD_BURST = “150”
- Turning on Synflood protection. If you have a fairly decent server, it won’t take much of any processing usage for this although the csf.conf file says it will slow down IP connections. I’ve not seen any performance issues when turning this on. In essence, SYN packets are sent to open a connection to the server – but SYNFLOODs are used to send half-open connections to a server and possibly cause a denial of service (DoS) attack. Therefore, you can turn on the protection by setting SYNFLOOD to 1. Then you can set the rate of how many SYN packets you are OK with receiving per second and then a burst rate. The rate and burst were set to the defaults.
CONNLIMIT = “21;2,25;5,80;20,443;20,587;5”
- This allows you to set how many connections you want to allow per IP address. This also helps to prevent attackers that want to try and flood a service on your server. As an example, I limit only two connections to port 21 (hence the 21;2) from the same IP. I limit port 25 connections to 5 (25;5) from the same IP and so on. You will put in the port – a semicolon – then the limit. Separate each by a comma as noted above.
UDPFLOOD = “1”
UDPFLOOD_LIMIT = “100/s”
UDPFLOOD_BURST = “500”
- Basically the same as SYNFLOOD as noted above – except this is for UDP floods.
LF_PERMBLOCK = “1”
LF_PERMBLOCK_INTERVAL = “86400”
LF_PERMBLOCK_COUNT = “2”
LF_PERMBLOCK_ALERT = “1”
- I love this. This is one thing that CSF has over Fail2Ban. In essence, you can set when you want to “permanantly” ban an IP address after they have attempted several times. Down further for the settings is the LF blocks setup per service. Those are temporary bans and you can specify a temporary ban in those spots. But after someone has been blocked temporarily so many times, it is time to do a more permanent block since they are nothing but trouble. LF_PERMBLOCK set to 1 enables this feature. The LF_PERMBLOCK_INTERVAL sets the “permanent” time period. 86400 is 24 hours.
- LF_PERMBLOCK_COUNT needs a little bit of clarification. In my case, I have it set to 2. This means that after someone has been temporarily banned (using the settings for the specific services), the IP address will be banned for the LF_PERMBLOCK_INTERVAL. However, even though I have it set to 2, it actually is 3. That is because they will be blocked temporarily two times. Then on the third time, they will be “permanently” blocked.
- LF_PERMBLOCK_ALERT is set to 1 – which means I am alerted by e-mail whenever a permanent block goes into effect.
LF_NETBLOCK = “1”
LF_NETBLOCK_INTERVAL = “86400”
LF_NETBLOCK_COUNT = “2”
LF_NETBLOCK_CLASS = “C”
LF_NETBLOCK_ALERT = “1”
- This is must like the PERMBLOCK noted above, but this actually will block a network range. In the event that more than one IP address from the LF_NETBLOCK_CLASS is attempting to infiltrate your system, CSF will actually do a “permanent” block (set to the LF_NETBLOCK_INTERVAL) for the entire range of IP addresses. I would definitely keep the LF_NETBLOCK_CLASS set to C – which means it will block and monitor only a class C network (254 addresses). If you set this any higher, you are blocking thousands of IPs.
LF_TRIGGER = “0”
- I would recommend keeping the LF_TRIGGER to 0 unless you are OK with setting the same trigger amount for each of your services. In essence, this trigger can be set to “5” if desired – which means that after five failed attempts against any of the services you want to monitor – that IP address will be blocked temporarily. By setting this to 0, it gives you more granular control over how many failed attempts you want to set on a per-service basis. In my case, I wanted to block FTP after three attempts – and everything else after 5.
LF_TRIGGER_PERM = “0”
- Again, I set this to 0 so I can specifically set the triggers for each service. If you want to have the same trigger amount for each service, then this value can be set to the time period you want to temporary ban the IP address that is attempting access to your server. As an example, set it to 300 seconds if you want to temporarily ban for 5 minutes.
LF_SELECT = “0”
- I am debating about changing this. If this is set to 0, that means the IP address that has undergone a temporary ban is only banned from that service (such as POP, IMAP, web, SMTP, etc). If set to 1, then that means the IP address will be blocked temporarily from accessing anything on the server.
LF_SSHD = “5”
LF_SSHD_PERM = “300”
- Here is where I specifically say that upon five failed attempts (LF_SSHD), the IP address will be temporarily banned for 300 seconds (LF_SSHD_PERM). The “PERM” in the variable name is misleading – because it is not a permanent block – only temporary. Of course, that temporary time period is set based on what you want. With my systems, I set it to 300 seconds (five minutes) and then because I have the LF_PERMBLOCK set to 1 (noted above), they will be fully blocked for a full 24 hours (LF_PERMBLOCK_INTERVAL) after three temporary bans.
LF_SMTPAUTH = “5”
LF_SMTPAUTH_PERM = “300”
LF_FTPD = “3”
LF_FTPD_PERM = “300”
LF_EXIMSYNTAX = “10”
LF_EXIMSYNTAX_PERM = “300”
LF_POP3D = “5”
LF_POP3D_PERM = “300”
LF_IMAPD = “5”
LF_IMAPD_PERM = “300”
LF_HTACCESS = “5”
LF_HTACCESS_PERM = “300”
LF_MODSEC = “5”
LF_MODSEC_PERM = “300”
- The settings above are just like the LF_SSHD. The first one will tell CSF / LFD how many invalid attempts to allow before temporarily blocking the IP address. Make note of LF_HTACCESS and LF_MODSEC. I have some custom Regex rules listed below that will help you watch for bots attempting to access password-protected directories. This is a HUGE benefit to us.
HTACCESS_LOG = “Log_Locations”
MODSEC_LOG = “Log_Locations”
- One neat thing you can do with CSF is use wildcards (*) in the log file names. Why? Well, because if you do web hosting and keep separate log files for each of your customers, you will want to be sure that CSF / LFD scans those logs for any kind of unauthorized access attempts (401 errors). So, let’s say that you have a setup like this:
- Customer base path is /var/www/<user-login>
- Logs are kept in /var/www/<user-login/logs
- Access log is named access.log
- Error log is named error.log
- Well, you can set HTACCESS_LOG = “/var/www/*/logs/error.log” and MODSEC_LOG = “/var/www/*/logs/access.log” to scan every log file in all user directories. Note the asterisk (*) where the <user-login> is. Very beneficial.
Speaking of MODSEC logs, that leads me into the next topic of Custom Regex.
Custom Regex Files
This is where things really can help out if you have non-standard services that you also want to monitor connections for. As an example, I have ensured that some of our other web programs that allow for logins are logged into a file that is already monitored – and then regex items were made to check those for invalid logins. That way if attempts are made against those systems, they can also be blocked there.
A Regex helper can be found here: http://regex101.com/r/uO1vS2
That allows you to put in the log line that you want to try and match – and then a box above that to fill in the regex. You will see that it was filled out with a log line I used along with the regex noted below in the first example.
Blocking 401 Unauthorized Attempts Against A Web Server
The big thing that I think will help out many people is to sense whenever someone is attempting to access a password-protected directory on your web server (think wp-admin for WordPress or administrator for Joomla). When an invalid attempt is made, it throws a “401” error in the access log. So, ensure that you have MODSEC_LOG set to monitor the log. Then you will want to add this to your /etc/csf/regex.custom.pm file:
if (($config{LF_MODSEC}) and ($globlogs{MODSEC_LOG}{$lgfile}) and ($line =~ /(\S+)(.*) 401 (.*)/)) {
$ip = $1; $acc = “”; $ip =~ s/^::ffff://;
if (&checkip($ip)) {return (“mod_security triggered by”,”$ip|$acc”,”mod_security”)} else {return}
}
In essence, you can see the “401” in the first line. That Regex will find any lines in the MODSEC_LOG file(s) that have a 401 in them (spaces on both sides to ensure it isn’t in an actual URL) and will temporary block the IP based on your LF_MODSEC setting (or LF_TRIGGER if you didn’t want to set the services independently with different trigger values).
Additional Regexes For ProFTPD
The Regexes included with CSF don’t fully match all of the items for ProFTPD logins. Therefore, I made a couple of extra Regexes to ensure they worked right. The first one will find any line that has “Login failed” in it. Of course, if the login failed, you want it to be noted. The Regex built in with CSF is more restrictive than this one:
if (($config{LF_FTPD}) and ($globlogs{FTPD_LOG}{$lgfile}) and ($line =~ /(\S+\S+\s+\d+\s+\S+) (\S+) proftpd\[\d+\] (\S+) \([^\[]+\[(\S+)\]\): USER (\S+) \(Login failed\)(.*)/)) {
$ip = $4; $acc = $5; $ip =~ s/^::ffff://; $acc =~ s/:$//g;
if (&checkip($ip)) {return (“Failed FTP login from”,”$ip|$acc”,”ftpd”)} else {return}
}
Here is another Regex that will find and block any that have SECURITY VIOLATION in it. This is done if someone tries to login to FTP using a root account:
if (($config{LF_FTPD}) and ($globlogs{FTPD_LOG}{$lgfile}) and ($line =~ /(\S+\S+\s+\d+\s+\S+) (\S+) proftpd\[\d+\] (\S+) \([^\[]+\[(\S+)\]\): SECURITY VIOLATION: (.*)/)) {
$ip = $4; $acc = $5; $ip =~ s/^::ffff://; $acc =~ s/:$//g;
if (&checkip($ip)) {return (“Failed FTP login from”,”$ip|$acc”,”ftpd”)} else {return}
}
Additional Regex for Dovecot IMAP
The built-in IMAP Regex into CSF didn’t work for me – maybe it is because of how I have logging setup, I’m not sure. So I had to modify the regex to simply look for any line that has “failed” in it:
if (($config{LF_POP3D}) and ($globlogs{POP3D_LOG}{$lgfile}) and ($line =~ /(.*)imap-login(.*)failed(.*)rip=(\S+)\,(.*)/)) {
$ip = $4; $acc = “”; $ip =~ s/^::ffff://;
if (&checkip($ip)) {return (“Failed IMAP login from”,”$ip|$acc”,”imapd”)} else {return}
}
Well, I hope that this tutorial about setting up ConfigServer Firewall (CSF) on Ubuntu has come in helpful for some of you out there. Especially the bits including the csf.conf recommended settings and the custom regex help for CSF.