Blocking FTP Hacking Attempts
Recent times have seen a large increase in automated attacks on various server ports with many, but not all, of the ip addresses tracing back to China. The targeted services include web servers (HTTP), name servers (bind) and FTP. So how do we go about identifying and blocking specifically the FTP attacks using ProFTPD and other server tools?
Sensible first steps
Disable FTP
Firstly, do you really need to be running an FTP server? If not, turn it off and block the relevant ports. For example, using iptables:
/sbin/iptables -A INPUT -p tcp --match multiport --dports ftp,ftp-data -j DROP
In any case you almost certainly want to disable anonymous FTP connections. For one thing Googlebot has a nasty habit of exploring anonymous ftp which could result in the wrong files being exposed.
Limit access to FTP
If you do need to allow FTP then can you restrict access to specific ip addresses within your local network or a clients network? If so you should set up a white-list.
This can be enabled using /etc/proftpd/proftpd.conf as shown below - including one or more Allow clauses to identify from where you want to allow FTP access:
<Limit LOGIN>
# single ip address example
Allow from 192.168.0.1
# multiple ip addresses example
Allow from 192.168.0.1 10.30.124.6
# subnet example
Allow from 192.168.0.0/16
# hostname example
Allow from example.net
DenyAll
</Limit>
The final DenyAll prevents the rest of the world from being able to connect. If you're running ftp via inetd then the changes take effect immediately. Otherwise you will need to restart your FTP server.
Make logins harder to guess
Most FTP hacking attempts are automated so rely on guessing both the username and the password. For example, if your domain name is www.example.net the hacking script will try "example", "examplenet", "admin@example.net", "webmaster@example.net" and so on. Generic usernames including "admin", "www", "data" and "test" are also being tried.
If the script is unable to guess a valid username then it will not be able to try any passwords. You should ensure your FTP usernames are not predictable in any way from the domain name - by appending some random letters or digits for example.
Hackers are also equipped with dictionaries and large databases of exposed username/password combinations from previously exploited servers. So make sure your passwords, not just for FTP, are long and complicated and don't match common patterns.
Dynamically blocking login attempts
The Fail2Ban program can be used to detect failed login attempts and automatically block the source ip address for a period of time. With Fail2Ban installed, we can enable this as follows.
Enable the jail in /etc/fail2ban/jail.conf:
[proftpd]
enabled = true
port = ftp,ftp-data,ftps,ftps-data
filter = proftpd
logpath = /var/log/proftpd/proftpd.log
maxretry = 5
bantime = 3600
Define the regular expression to look for in /etc/fail2ban/filter.d/proftpd.conf:
failregex = \(\S+\[<HOST>\]\)[: -]+ USER \S+: no such user found from \S+ \[\S+\] to \S+:\S+ *$
\(\S+\[<HOST>\]\)[: -]+ USER \S+ \(Login failed\): .*$
\(\S+\[<HOST>\]\)[: -]+ SECURITY VIOLATION: \S+ login attempted\. *$
\(\S+\[<HOST>\]\)[: -]+ Maximum login attempts \(\d+\) exceeded *$
With the above configuration any ip address responsible for 5 or more failed FTP login attempts - any logfile entries matching the above regular expressions - will be 'jailed' for a period of 1 hour. You can change these values to require less failed login attempts or to make the jailing last longer.
Identifying repeat offenders
While dynamic blocking goes a long way to making our FTP secure, it still allows a single ip address to make several attempts every few hours. And when the attacks are coming from a network with hundreds or thousands of available addresses that can quickly add up.
To put a permanent block in place we need to first identify the networks in questions. This can be done by analysing the Fail2Ban log files.
e.g. for a single log file:
awk '($5 ~ /proftpd/ && $6 ~ /Ban/){print $7}' /var/log/fail2ban.log | sort | uniq -c
e.g. for all log files:
zgrep -h Ban /var/log/fail2ban.log* | grep proftpd | awk '{print $(NF)}' | sort | uniq -c
The output in each case is an ordered list of ip addresses that have been jailed by Fail2Ban with a record of how many times each has been blocked in the period covered by the log or logs:
1 116.7.53.3
10 117.41.184.12
1 120.43.22.214
1 120.43.27.81
9 222.186.23.31
10 222.186.23.69
10 222.186.25.112
9 222.186.26.149
2 46.29.250.191
3 59.58.137.77
9 60.169.78.76
10 60.169.78.77
10 60.169.78.81
9 60.169.78.87
6 61.147.110.21
9 61.147.110.22
8 61.147.110.3
10 61.147.110.68
9 61.160.194.114
9 61.160.222.83
9 61.160.236.115
10 61.160.247.105
1 98.126.227.67
From this list we take the ip addresses and address blocks that have appeared the most in the log file. Remember that a tally of 10 indicates at least 50 failed login attempts from that ip address, and possibly hundreds of blocked attempts while they were jailed.
Using our Subnet Calculator we can convert these addresses into netmasks. For example, if you input 222.186.23.31 and 222.186.26.149 the resulting netmask is 222.186.16.0/20 which covers 4,096 addresses.
Checking with whois 222.186.16.0 we find that the block is owned by 'CHINANET JIANGSU' who actually control 222.184.0.0/13 (524,288 addresses). We can now choose whether to target just the /20 block that was explicitly matched or the larger /13 block of addresses belonging to the ISP.
Use the whois results to make sure you're not matching any known networks which do require FTP access to the server.
Permanent blocking
Having identifed a number of ip addresses and/or netmasks you have the choice of blocking them using iptables - so making a permanent entry in your firewall - or using ProFTP configuration to create a blacklist.
The blacklist option is usually much simpler to maintain and means not having to tinker with the firewall every time.
Using the results of our analysis we identified one ip address and four blocks of addresses that could safely be blocked. In proftpd.conf we created a blacklist and applied it to the LOGIN Limit clause as shown here:
<Class blacklist>
From 117.41.184.12
From 222.184.0.0/13
From 60.160.0.0/12
From 61.147.0.0/16
From 61.160.0.0/16
</Class>
<Limit LOGIN>
Order deny,allow
DenyClass blacklist
AllowAll
</Limit>
Using a class instead of including the list directly is more efficient and allows the same class to be applied to multiple virtual hosts. Running ProFTPD under inetd means that any changes take effect immediately without any services needing to be restarted.
For more details on ProFTPD configuration options there is an extremely useful HOWTO linked under References below.
Measure of success
After a few day we can re-scan the ProFTPD and Fail2Ban log files to see how successful we have been in blocking failed login attempts and whether there are any other addresses that need to be added to the blacklist.
In our case there has been a marked reduction in failed logins with the vast majority being blocked/denied:
Date | Failed logins | Fail2Ban blocks | Access denied |
---|---|---|---|
18 | 418 | 69 | - |
19 | 479 | 64 | - |
20 | 392 | 55 | - |
21 | 313 | 48 | 196 |
22 | 72 | 10 | 940 |
23 | 72 | 11 | 438 |
24 | 90 | 13 | 577 |
Just as importantly, none of these attempts matched a valid username so in the last few days there have been no passwords even being tested by the automated attacks.
Previously, with just Fail2Ban, each ip address would get to connect a few times before being blocked. This encourages them to keep trying. Now that the very first response is "denied" we can expect a drop-off, but have to stay attent for attacks from new addresses.
References
Related Articles - Fail2Ban
- System Monitoring the fail2ban log
- System Optimising your Fail2Ban filters
- System Fail2Ban 0.8.3 Howto
- System Implementing Port Knocking with knockd
- System Using a Fail2Ban Jail to Whitelist a User
- System Blocking FTP Hacking Attempts
- System fail2ban and sendmail
- System Using systemd to bind fail2ban to nftables
- System fail2ban and iptables