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