summaryrefslogtreecommitdiff
path: root/theDrain
blob: 22646fe056d35d515fcee9f28514290a30989653 (plain)
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#!/bin/bash
#
# Watch for floods and blacklist

# Lets  get some Variables defined
readonly max_ho=12						# Max # of Half Open Connectionsi from any /24
readonly host_ip=""				  		# IP addy of host machine
readonly log_file="/home/user/Drain.txt"		 	# Directory to log to.
readonly alert_to="user@example.com"				# Who to mail Alerts to
readonly alert_level=50						# How man Half Open before we send an e-mail
readonly server_name="$(hostname)"				# Name of your server. For E-mail alerts, defaults to hostmane
readonly whitelist_file="/home/user/whitelist"			# location of a list of IPs not to block 1 per live

# This Function scans for half open TCP connections (Sign of a SYN flood)
# and outputs a list of:
# <# of half open>   <IP Address>
function floodCheck () {
        netstat -tn | awk '$6 == "SYN_RECV" {print $5}' | rev | cut -d\: -f 2- | rev | cut -d\. -f 1-3 | sort | uniq -c -d
}


# This function takes an IP address as input
# Checks if it is already in iptables
# If not add it
function blackList () {
        if [[ $1 = "" ]]; then
                echo "no value"
                return 1
        fi
	# Is the IP whitelisted
	grep -q "$1" "$whitelist_file"
	if [[ $? -eq 0 ]]; then
		echo "$1 is Whitelisted. Not Blocking."
		return 1
	fi
        echo "Checking: $1"
        iptables -L INPUT -n | grep -q $1
        if [ $? == 0 ]; then
                echo "$1 already in blacklist"
                return 1
        fi
        echo "Blacklisting: $1"
        iptables -I INPUT -s "$1" -d $host_ip -p all -j DROP	# Don't wanna hear from ya
        iptables -I OUTPUT -d "$1" -s $host_ip -p all -j DROP 	# Don't wanna talk to ya
	echo -e "\n$(date) , Blocking $1\n" >> "$log_file"
	echo
}

# Some diagnostic output as I usually run this via "watch -n5 ..."
number_of_ho=$(netstat -tn | grep SYN_RECV | wc -l)             # Helps us to spot distributed attacks that floodCheck may miss

# E-mail Alerts
if [[ "$number_of_ho" -gt "$alert_level" ]] && [[ ! -e /tmp/ALERTED_FLAG ]]; then
       echo -e "$number_of_ho half open connections on $server_name.\nPotential SYN Flood situation.\nPlease checkwhat is going on.\nPlease clear ALERTED_FLAG when the situation is Resolved.\n\n \
		$server_name" | mail -s "SYN Flood Warning" -t "$alert_to"
       touch /tmp/ALERTED_FLAG
fi

# Display and Logging. (Probably should seperate the two)
if [[ "$number_of_ho" -gt "1" ]]; then
        echo "Number of half open connections: $number_of_ho"
        echo "-------------------------------------"
        floodCheck ; echo                           # Show the list so we can see distributed.
	echo -e "$(date), $number_of_ho half open. From: $(netstat -tn | awk '$6 == "SYN_RECV" {print $5}' | rev | cut -d\: -f 2- | rev | sort -u | wc -l) IP Addies." >> "$log_file"
        if [[ "$number_of_ho" -gt "$max_ho" ]]; then
                echo -e "$(netstat -tn | grep SYN_RECV)\n" >> "$log_file"
        fi

fi

# Check and block Flooders 
for ip_addy in $( floodCheck | awk -v allowed_ho=$max_ho '$1 > allowed_ho {print $2}' ) ;
do
	if [[ "$(whoami)" == "root" ]]; then
           	blackList "$ip_addy.0/24"
	fi
done