forked from colinmollenhour/ddos-deflate
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ddos.sh
executable file
·182 lines (174 loc) · 5.2 KB
/
ddos.sh
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#!/bin/bash
##############################################################################
# DDoS-Deflate version 0.6 Author: Zaf <zaf@vsnl.com> #
# #
# 7/21/2012 - Colin Mollenhour (colin@mollenhour.com) #
# - Use Bash explicitly
# - Added WARN_LIMIT feature
# - Don't print IP's under the limit
# - Add reverse DNS lookup for banned/warned IP addresses
# - Added logging to file
# - Add --no-kill option for easy testing
# - Add --list option for info
##############################################################################
# This program is distributed under the "Artistic License" Agreement #
# #
# The LICENSE file is located in the same directory as this program. Please #
# read the LICENSE file before you make copies or distribute this program #
##############################################################################
load_conf()
{
CONF="/usr/local/ddos/ddos.conf"
if [ -f "$CONF" ] && [ ! "$CONF" == "" ]; then
source $CONF
else
head
echo "$CONF not found."
exit 1
fi
}
head()
{
echo "DDoS-Deflate version 0.6"
echo "Copyright (C) 2005, Zaf <zaf@vsnl.com>"
echo
}
showhelp()
{
head
echo 'Usage: ddos.sh [OPTIONS] [N]'
echo "N : Ban limit for number of tcp/udp connections per IP (default $BAN_LIMIT)"
echo 'OPTIONS:'
echo '-h | --help: Show this help screen'
echo "-c | --cron: Create cron job to run this script regularly ($FREQ minutes)"
echo '-k | --kill: Block the offending ip making more than N connections (overrides config)'
echo '-n | --no-kill: Report only, do not block IPs (overrides config)'
echo '-l | --list: List all IPs and connection counts over the warning limit.'
}
unbanip()
{
UNBAN_SCRIPT=`mktemp /tmp/unban.XXXXXXXX`
TMP_FILE=`mktemp /tmp/unban.XXXXXXXX`
UNBAN_IP_LIST=`mktemp /tmp/unban.XXXXXXXX`
echo '#!/bin/sh' > $UNBAN_SCRIPT
echo "sleep $BAN_PERIOD" >> $UNBAN_SCRIPT
if [ $APF_BAN -eq 1 ]; then
while read line; do
echo "$APF -u $line" >> $UNBAN_SCRIPT
echo $line >> $UNBAN_IP_LIST
done < $BANNED_IP_LIST
else
while read line; do
echo "$IPT -D INPUT -s $line -j DROP" >> $UNBAN_SCRIPT
echo $line >> $UNBAN_IP_LIST
done < $BANNED_IP_LIST
fi
echo "grep -v --file=$UNBAN_IP_LIST $IGNORE_IP_LIST > $TMP_FILE" >> $UNBAN_SCRIPT
echo "mv $TMP_FILE $IGNORE_IP_LIST" >> $UNBAN_SCRIPT
echo "rm -f $UNBAN_SCRIPT" >> $UNBAN_SCRIPT
echo "rm -f $UNBAN_IP_LIST" >> $UNBAN_SCRIPT
echo "rm -f $TMP_FILE" >> $UNBAN_SCRIPT
. $UNBAN_SCRIPT &
}
add_to_cron()
{
rm -f $CRON
sleep 1
service crond restart
sleep 1
echo "SHELL=/bin/sh" > $CRON
if [ $FREQ -le 2 ]; then
echo "0-59/$FREQ * * * * root $PROG >/dev/null 2>&1" >> $CRON
else
let "START_MINUTE = $RANDOM % ($FREQ - 1)"
let "START_MINUTE = $START_MINUTE + 1"
let "END_MINUTE = 60 - $FREQ + $START_MINUTE"
echo "$START_MINUTE-$END_MINUTE/$FREQ * * * * root $PROG >/dev/null 2>&1" >> $CRON
fi
service crond restart
}
TMP_PREFIX='/tmp/ddos'
load_conf
LIST=0
while [ $1 ]; do
case $1 in
'-h' | '--help' | '?' )
showhelp
exit
;;
'--cron' | '-c' )
add_to_cron
exit
;;
'--kill' | '-k' )
KILL=1
;;
'--no-kill' | '-n' )
KILL=0
;;
'--list' | '-l' )
LIST=1
;;
*[0-9]* )
BAN_LIMIT=$1
;;
* )
showhelp
exit
;;
esac
shift
done
[ -z $WARN_LIMIT ] && WARN_LIMIT=$BAN_LIMIT
[ $LIST -eq 1 -a $BAN_LIMIT -lt $WARN_LIMIT ] && WARN_LIMIT=$BAN_LIMIT
[ $BAN_LIMIT -ge $WARN_LIMIT ] || WARN_LIMIT=$BAN_LIMIT
# Modified netstat command taken from: http://blog.everymanhosting.com/webhosting/dos-deflate-blocks-numbers-not-ip-addresses/
# Only check for ESTABLISHED status connections
BAD_IP_LIST=$(mktemp $TMP_PREFIX.XXXXXXXX)
netstat -ntu | grep ESTAB | grep ':' | awk '{print $5}' | sed 's/::ffff://' | cut -f1 -d ':' \
| sort | grep -v -f <(grep -vF '#' $IGNORE_IP_LIST | sort) | uniq -c \
| awk "{ if (\$1 >= $WARN_LIMIT) print; }" | sort -nr \
> $BAD_IP_LIST
cat $BAD_IP_LIST
if [ $LIST -eq 1 ]; then
FOUND_COUNT=$(cat $BAD_IP_LIST | wc -l)
echo "Found ${FOUND_COUNT} IPs with ${WARN_LIMIT} or more connections."
rm -f $TMP_PREFIX.*
exit
fi
BANNED_IP_MAIL=$(mktemp $TMP_PREFIX.XXXXXXXX)
BANNED_IP_LIST=$(mktemp $TMP_PREFIX.XXXXXXXX)
echo "Banned the following ip addresses on `date`" > $BANNED_IP_MAIL
echo >> $BANNED_IP_MAIL
IP_BANNED=0
IP_LOGGED=0
while read CONN IP; do
FQDN=$(dig +short -x $IP)
if [ $CONN -ge $BAN_LIMIT -a $KILL -eq 1 ]; then
echo "BANNED: $IP with $CONN connections ($FQDN)" >> $BANNED_IP_MAIL
echo $IP >> $BANNED_IP_LIST
echo $IP >> $IGNORE_IP_LIST
if [ $APF_BAN -eq 1 ]; then
$APF -d $CURR_LINE_IP
else
$IPT -I INPUT -s $CURR_LINE_IP -j DROP
fi
IP_BANNED=1
else
echo "WARNING: $IP with $CONN connections ($FQDN)" >> $BANNED_IP_MAIL
fi
IP_LOGGED=1
done < $BAD_IP_LIST
if [ $IP_BANNED -eq 1 ]; then
[ -n $AFTER_BAN ] && eval $AFTER_BAN
unbanip
fi
if [ $IP_LOGGED -eq 1 ]; then
if [ $LOG_FILE != "" ]; then
cat $BANNED_IP_MAIL >> $LOG_FILE
fi
if [ $EMAIL_TO != "" ]; then
cat $BANNED_IP_MAIL | mail -s "IP addresses banned on `date`" $EMAIL_TO
fi
fi
rm -f $TMP_PREFIX.*