Imported Upstream version 2.7
[ossec-hids.git] / active-response / firewall-drop.sh
1 #!/bin/sh
2 # Adds an IP to the iptables drop list (if linux)
3 # Adds an IP to the ipfilter drop list (if solaris, freebsd or netbsd)
4 # Adds an IP to the ipsec drop list (if aix)
5 # Requirements: Linux with iptables, Solaris/FreeBSD/NetBSD with ipfilter or AIX with IPSec
6 # Expect: srcip
7 # Author: Ahmet Ozturk (ipfilter and IPSec)
8 # Author: Daniel B. Cid (iptables)
9 # Author: cgzones 
10 # Last modified: Oct 04, 2012
11
12 UNAME=`uname`
13 ECHO="/bin/echo"
14 GREP="/bin/grep"
15 IPTABLES=""
16 IP4TABLES="/sbin/iptables"
17 IP6TABLES="/sbin/ip6tables"
18 IPFILTER="/sbin/ipf"
19 if [ "X$UNAME" = "XSunOS" ]; then
20     IPFILTER="/usr/sbin/ipf"
21 fi    
22 GENFILT="/usr/sbin/genfilt"
23 LSFILT="/usr/sbin/lsfilt"
24 MKFILT="/usr/sbin/mkfilt"
25 RMFILT="/usr/sbin/rmfilt"
26 ARG1=""
27 ARG2=""
28 RULEID=""
29 ACTION=$1
30 USER=$2
31 IP=$3
32
33
34 LOCAL=`dirname $0`;
35 cd $LOCAL
36 cd ../
37 PWD=`pwd`
38 filename=$(basename "$0")
39
40 LOCK="${PWD}/fw-drop"
41 LOCK_PID="${LOCK}/pid"
42 LOG_FILE="${PWD}/../logs/active-responses.log"
43
44 echo "`date` $0 $1 $2 $3 $4 $5" >> ${LOG_FILE}
45
46
47 # Checking for an IP
48 if [ "x${IP}" = "x" ]; then
49    echo "$0: <action> <username> <ip>" 
50    exit 1;
51 fi
52
53 case "${IP}" in
54     *:* ) IPTABLES=$IP6TABLES;;
55     *.* ) IPTABLES=$IP4TABLES;;
56     * ) echo "`date` Unable to run active response (invalid IP: '${IP}')." >> ${LOG_FILE} && exit 1;;
57 esac
58
59 # This number should be more than enough (even if a hundred
60 # instances of this script is ran together). If you have
61 # a really loaded env, you can increase it to 75 or 100.
62 MAX_ITERATION="50"
63
64 # Lock function
65 lock()
66 {
67     i=0;
68     # Providing a lock.
69     while [ 1 ]; do
70         mkdir ${LOCK} > /dev/null 2>&1
71         MSL=$?
72         if [ "${MSL}" = "0" ]; then
73             # Lock aquired (setting the pid)
74             echo "$$" > ${LOCK_PID}
75             return;
76         fi
77
78         # Getting currently/saved PID locking the file
79         C_PID=`cat ${LOCK_PID} 2>/dev/null`
80         if [ "x" = "x${S_PID}" ]; then
81             S_PID=${C_PID}
82         fi
83
84         # Breaking out of the loop after X attempts
85         if [ "x${C_PID}" = "x${S_PID}" ]; then
86             i=`expr $i + 1`;
87         fi
88
89         # Sleep 1 after 10/25 interactions
90         if [ "$i" = "10" -o "$i" = "25" ]; then
91             sleep 1;
92         fi
93
94         i=`expr $i + 1`;
95
96         # So i increments 2 by 2 if the pid does not change.
97         # If the pid keeps changing, we will increments one
98         # by one and fail after MAX_ITERACTION
99
100         if [ "$i" = "${MAX_ITERATION}" ]; then
101             kill="false"
102             for pid in `pgrep -f "${filename}"`; do
103                 if [ "x${pid}" = "x${C_PID}" ]; then
104                     # Unlocking and exiting
105                     kill -9 ${C_PID}
106                     echo "`date` Killed process ${C_PID} holding lock." >> ${LOG_FILE}
107                     kill="true"
108                     unlock;
109                     i=0;
110                     S_PID="";
111                     break;
112                 fi
113             done
114
115             if [ "x${kill}" = "xfalse" ]; then
116                 echo "`date` Unable kill process ${C_PID} holding lock." >> ${LOG_FILE}
117                 # Unlocking and exiting
118                 unlock;
119                 exit 1;
120             fi
121         fi
122     done
123 }
124
125 # Unlock function
126 unlock()
127 {
128    rm -rf ${LOCK} 
129 }
130
131
132
133 # Blocking IP
134 if [ "x${ACTION}" != "xadd" -a "x${ACTION}" != "xdelete" ]; then
135    echo "$0: invalid action: ${ACTION}"
136    exit 1;
137 fi
138
139
140
141 # We should run on linux
142 if [ "X${UNAME}" = "XLinux" ]; then
143    if [ "x${ACTION}" = "xadd" ]; then
144       ARG1="-I INPUT -s ${IP} -j DROP"
145       ARG2="-I FORWARD -s ${IP} -j DROP"
146    else
147       ARG1="-D INPUT -s ${IP} -j DROP"
148       ARG2="-D FORWARD -s ${IP} -j DROP"
149    fi
150    
151    # Checking if iptables is present
152    if [ ! -x ${IPTABLES} ]; then
153       IPTABLES="/usr"${IPTABLES}
154       if [ ! -x ${IPTABLES} ]; then
155         echo "$0: can not find iptables"
156         exit 0;
157       fi
158    fi
159
160    # Executing and exiting
161    COUNT=0;
162    lock;
163    while [ 1 ]; do
164        echo ".."
165         ${IPTABLES} ${ARG1}
166         RES=$?
167         if [ $RES = 0 ]; then
168             break;
169         else
170             COUNT=`expr $COUNT + 1`;
171             echo "`date` Unable to run (iptables returning != $RES): $COUNT - $0 $1 $2 $3 $4 $5" >> ${LOG_FILE}
172             sleep $COUNT;
173
174             if [ $COUNT -gt 4 ]; then
175                 break;
176             fi    
177         fi
178    done
179    
180    while [ 1 ]; do
181         ${IPTABLES} ${ARG2}
182         RES=$?
183         if [ $RES = 0 ]; then
184             break;
185         else
186             COUNT=`expr $COUNT + 1`;
187             echo "`date` Unable to run (iptables returning != $RES): $COUNT - $0 $1 $2 $3 $4 $5" >> ${LOG_FILE}
188             sleep $COUNT;
189
190             if [ $COUNT -gt 4 ]; then
191                 break;
192             fi       
193         fi
194    done
195    unlock;
196             
197    exit 0;
198    
199 # FreeBSD, SunOS or NetBSD with ipfilter
200 elif [ "X${UNAME}" = "XFreeBSD" -o "X${UNAME}" = "XSunOS" -o "X${UNAME}" = "XNetBSD" ]; then
201    
202    # Checking if ipfilter is present
203    ls ${IPFILTER} >> /dev/null 2>&1
204    if [ $? != 0 ]; then
205       exit 0;
206    fi    
207
208    # Checking if echo is present
209    ls ${ECHO} >> /dev/null 2>&1
210    if [ $? != 0 ]; then
211        exit 0;
212    fi    
213    
214    if [ "x${ACTION}" = "xadd" ]; then
215       ARG1="\"@1 block out quick from any to ${IP}\""
216       ARG2="\"@1 block in quick from ${IP} to any\""
217       IPFARG="${IPFILTER} -f -"
218    else
219       ARG1="\"@1 block out quick from any to ${IP}\""
220       ARG2="\"@1 block in quick from ${IP} to any\""
221       IPFARG="${IPFILTER} -rf -"
222    fi
223   
224    # Executing it 
225    eval ${ECHO} ${ARG1}| ${IPFARG}       
226    eval ${ECHO} ${ARG2}| ${IPFARG}
227    
228    exit 0;
229
230 # AIX with ipsec
231 elif [ "X${UNAME}" = "XAIX" ]; then
232
233   # Checking if genfilt is present
234   ls ${GENFILT} >> /dev/null 2>&1
235   if [ $? != 0 ]; then
236      exit 0;
237   fi
238          
239   # Checking if lsfilt is present
240   ls ${LSFILT} >> /dev/null 2>&1
241   if [ $? != 0 ]; then
242      exit 0;
243   fi
244   # Checking if mkfilt is present
245   ls ${MKFILT} >> /dev/null 2>&1
246   if [ $? != 0 ]; then
247      exit 0;
248   fi
249          
250   # Checking if rmfilt is present
251   ls ${RMFILT} >> /dev/null 2>&1
252   if [ $? != 0 ]; then
253      exit 0;
254   fi
255
256   if [ "x${ACTION}" = "xadd" ]; then
257     ARG1=" -v 4 -a D -s ${IP} -m 255.255.255.255 -d 0.0.0.0 -M 0.0.0.0 -w B -D \"Access Denied by OSSEC-HIDS\"" 
258     #Add filter to rule table
259     eval ${GENFILT} ${ARG1}
260     
261     #Deactivate  and activate the filter rules.
262     eval ${MKFILT} -v 4 -d
263     eval ${MKFILT} -v 4 -u
264   else
265     # removing a specific rule is not so easy :(
266      eval ${LSFILT} -v 4 -O  | ${GREP} ${IP} | 
267      while read -r LINE
268      do
269          RULEID=`${ECHO} ${LINE} | cut -f 1 -d "|"`
270          let RULEID=${RULEID}+1
271          ARG1=" -v 4 -n ${RULEID}"
272          eval ${RMFILT} ${ARG1}
273      done
274     #Deactivate  and activate the filter rules.
275     eval ${MKFILT} -v 4 -d
276     eval ${MKFILT} -v 4 -u
277   fi
278
279 else
280     exit 0;
281 fi