On a newly deployed FTP backup server, a routine check of the /var/log/secure log revealed numerous failed authentication attempts for both sshd and vsftpd. It was obvious someone was trying to brute-force passwords, so a security script needed to be written to prevent this.
The script requirements are as follows: This SHELL script is placed in a crontab scheduled task and runs every 6 hours (this interval can be defined based on actual circumstances) to read the /var/log/secure log. It extracts malicious IPs that are attempting to guess passwords. If the number of connections within a specific time unit (one week) exceeds a threshold, for example, 100 (this threshold can also be defined based on actual circumstances), the IP is added to the /etc/hosts.deny blacklist. If it falls below this threshold, the IP is ignored.
|
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
|
/var/log/secureThe failed authentication information inside is as follows:Nov 28 10:18:08 centos2 sshd[7556]: Connection closed by 222.216.30.109Nov 28 10:18:08 centos2 sshd[7557]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=222.216.30.109 user=rootNov 28 10:18:09 centos2 sshd[7559]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=222.216.30.109 user=rootNov 28 10:18:10 centos2 sshd[7551]: Failed password for root from 222.216.30.109 port 2391 ssh2Nov 28 10:18:10 centos2 sshd[7552]: Connection closed by 222.216.30.109Nov 28 10:18:10 centos2 sshd[7553]: Failed password for root from 222.216.30.109 port 2397 ssh2Nov 28 10:18:10 centos2 sshd[7554]: Connection closed by 222.216.30.109Nov 28 10:18:11 centos2 sshd[7557]: Failed password for root from 222.216.30.109 port 2401 ssh2Nov 28 10:18:11 centos2 sshd[7558]: Connection closed by 222.216.30.109Nov 28 10:18:11 centos2 sshd[7559]: Failed password for root from 222.216.30.109 port 2403 ssh2Nov 28 10:18:11 centos2 sshd[7560]: Connection closed by 222.216.30.109Nov 28 10:37:01 centos2 vsftpd: pam_unix(vsftpd:auth): check pass; user unknownNov 28 10:37:01 centos2 vsftpd: pam_unix(vsftpd:auth): authentication failure; logname= uid=0 euid=0 tty=ftp ruser=hello rhost=centos1.cn7788.comNov 28 10:37:01 centos2 vsftpd: pam_succeed_if(vsftpd:auth): error retrieving information about user helloNov 28 10:37:19 centos2 vsftpd: pam_unix(vsftpd:auth): check pass; user unknownNov 28 10:37:19 centos2 vsftpd: pam_unix(vsftpd:auth): authentication failure; logname= uid=0 euid=0 tty=ftp ruser=yhc rhost=centos1.cn7788.comNov 28 10:37:19 centos2 vsftpd: pam_succeed_if(vsftpd:auth): error retrieving information about user yhcNov 28 10:37:36 centos2 vsftpd: pam_unix(vsftpd:auth): check pass; user unknownNov 28 10:37:36 centos2 vsftpd: pam_unix(vsftpd:auth): authentication failure; logname= uid=0 euid=0 tty=ftp ruser=yuhongchun rhost=centos1.cn7788.comNov 28 10:37:36 centos2 vsftpd: pam_succeed_if(vsftpd:auth): error retrieving information about user yuhongchunNov 28 10:42:44 centos2 vsftpd: pam_unix(vsftpd:auth): check pass; user unknownNov 28 10:42:44 centos2 vsftpd: pam_unix(vsftpd:auth): authentication failure; logname= uid=0 euid=0 tty=ftp ruser=yuhongchun rhost=114.112.169.70Nov 28 10:42:44 centos2 vsftpd: pam_succeed_if(vsftpd:auth): error retrieving information about user yuhongchunNov 28 10:42:56 centos2 vsftpd: pam_unix(vsftpd:auth): check pass; user unknownNov 28 10:42:56 centos2 vsftpd: pam_unix(vsftpd:auth): authentication failure; logname= uid=0 euid=0 tty=ftp ruser=andrewyu rhost=114.112.169.70Nov 28 10:42:56 centos2 vsftpd: pam_succeed_if(vsftpd:auth): error retrieving information about user andrewyu |
Let’s observe the log rotation pattern of /var/log/secure, as shown below:
|
1
2
3
4
5
|
ls -lsart secure.*512 -rw------- 1 root root 516379 11-04 01:31 secure.4660 -rw------- 1 root root 668192 11-11 00:05 secure.3304 -rw------- 1 root root 306589 11-17 10:33 secure.2484 -rw------- 1 root root 488620 11-25 02:33 secure.1 |
Basically, the /var/log/secure file rotates on a weekly basis. For those with strict security requirements, you can also follow a “leave no one behind” principle to capture malicious IPs from older secure logs and then dump them into the /etc/hosts.deny file. Next, we need to figure out how to efficiently capture these malicious IPs. If we refer to the original version of the SHELL script, to capture the IP addresses probing the vsftpd and sshd services from the secure log,
we can use the following command:
|
1
|
cat /var/log/secure | awk '/Failed/{print $(NF-3)}'| sort| uniq -c| awk '{print $2"="$1;}' |
Obviously, this won’t capture the failed IP values for vsftpd. The failure information in the sshd log differs from that in the vsftpd log. I wrote several methods combining awk and sed, and after testing their efficiency, I felt that using an awk script is the fastest. You can also write a few variations and test them with the time command. Finally, I streamlined the code and completed the entire script. The script
content is as follows:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#!/bin/bashawk '{for(i=1;i<=NF;i++){if($i ~ /rhost/)print substr($i,7)}}' /var/log/secure | sort | uniq -c>/root/black.txtDEFINE="100"cat /root/black.txt | while read LINEdo NUM=`echo $LINE |awk '{print $1}'` host=`echo $LINE |awk '{print $2}'` if [ $NUM -gt $DEFINE ]; then grep $host /etc/hosts.deny > /dev/null if [ $? -gt 0 ]; then echo "sshd:$host" >> /etc/hosts.deny echo "vsftpd:$host" >> /etc/hosts.deny fi fidone |
After the script has been running for a while, we can inspect some of the files involved, such as /root/black.txt,the results will look like this:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
cat /root/black.txt 2 113.17.144.156 4 114.112.51.208 4 114.112.69.170 169 118-163-227-50.hinet-ip.hinet.net 8 119.188.7.200 8 122.70.130.11 61 124.248.32.246 12 183.203.14.121 3 189.26.255.11 56 199.204.237.60 3 199.30.53.220 5 201.236.80.4 6 220.172.191.31 30 222.216.30.109 60 222.253.159.111 58 223.4.180.23 166 58.221.42.178 1 61.132.4.85 152 61.142.106.34 22 61.167.33.222 7 85.126.166.83 166 www.b-nets.com |
The /etc/hosts.deny script content is as follows:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
sshd:124.248.32.246vsftpd:124.248.32.246sshd:199.204.237.60vsftpd:199.204.237.60sshd:222.253.159.111vsftpd:222.253.159.111sshd:223.4.180.23vsftpd:223.4.180.23sshd:58.221.42.178vsftpd:58.221.42.178sshd:61.142.106.34vsftpd:61.142.106.34sshd:118-163-227-50.hinet-ip.hinet.netvsftpd:118-163-227-50.hinet-ip.hinet.netsshd:www.b-nets.comvsftpd:www.b-nets.com |
Finally, we put this shell script into crontab to run every six hours, with the following command:
|
1
|
* */6 * * * root /bin/bash /root/hostsdeny.sh >> /dev/null 2>&1 |
Since the /var/log/secure log rotates on a weekly basis, the execution frequency of this script can be set as needed. If you feelthe server is being probed frequently, the execution interval can be set shorter; otherwise, it can be set longer.Note: If you only want to prevent SSH brute-force attacks, this script doesn’t need to be updated; you can adopt my originalSHELL script (i.e., the original version). This updated script is suitable for deployment on public-facing machines with FTP. It has been testedand is relatively stable, but I feel there is still room for improvement. You are welcome to email me for discussion, Yu Hongchun([email protected]).
This article is from the “抚琴煮酒” blog. Please be sure to retain this source: http://andrewyu.blog.51cto.com/1604432/1074650