Securing VSFTP with TCP Wrappers and IPTables
I’ve been drinking beer and perhaps had one too many. Regardless of the reason, I felt the urge to further secure my favorite server. The target of my paranoia is once again the VSFTPd. I already have iptables and fail2ban running with various elaborate rules and filters. In addition I wanted to place some restrictions via TCP wrappers.The first step is to add something like this to /etc/hosts.deny
vsftpd: ALL \ : spawn (/bin/logger %h denied access to %d) : deny
The “spawn” action creates an entry in the /var/log/messages saying “<ip> denied access to vsftpd”
Then you add the allowed IPs to the /etc/hosts.allow.
1vsftpd:192.168.12.0/255.255.255.0 192.168.13.0/255.255.255.0 \ 192.168.120.0/255.255.255.0 192.168.121.0/255.255.255.0 \ : spawn (/bin/logger %h allowed access to %d) : allow
The cool thing here is the “spawn” directive. You can have more than one and one of them can be an aggressive nmap scan, a ping flood or something even less tolerant of unwelcome visitors.
Bounce vsftpd and you should be good to go. So I did go and grabbed another beer and by the time I got back there were a couple dozen “access denied” entries in the log for the same IP from Chicago. This got me thinking that blocking that IP with iptables would probably be beneficial for the overall health of my server.
So the idea is simple: scan all current and rotated /var/log/messages*; extract unique IPs; identify the “heavy-hitters”; block them with iptables. Here’s a quick script to do this.
2#!/bin/bash # # Identified IPs blocked by TCP Wrappers (/etc/hosts.deny) multiple times # and permanently block those IPs with IPTables firewall # m="denied access to " t=10 whitelist="192.168.122.|192.168.123." zgrep "${m}" /var/log/messages* | \ for ip in `grep -oE "([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})" | grep -Ev "${whitelist}" | \ sort -u -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n` do n=$(zgrep -c "\b${ip} ${m}\b" /var/log/messages* | awk -F':' '{sum=sum+$NF} END {print sum}') if [ ${n} -ge ${t} ] then if [ `/sbin/iptables -S | grep -c "${ip}.*DROP"` -eq 0 ] then c=$(geoiplookup ${ip} | grep Country | grep -woE [A-Z]{2}, | sed 's/,//g') echo -e "Banning ${ip} from ${c} after ${n} TCP Wrappers denials" | tee >(logger) /sbin/iptables -A INPUT -s ${ip} -j DROP fi fi done /sbin/service iptables save
Save the script as, say, /var/adm/bin/tcpwrapper_ip_block.sh; make it executable and add this root cron job:
25 */1 * * * /var/adm/bin/tcpwrapper_ip_block.sh >/dev/null 2>&1
When someone is blocked by the script, you should see an entry in the /var/log/messages along the lines of:
Nov 11 00:58:46 thereminvox root: Banning 208.100.26.229 from US after 27 TCP Wrappers denials
The idea here is that, if someone is persistently trying to break into your FTP server, they may also decide to explore other avenues of attack. Blocking them with iptables minimizes their options.