1 |
rabit |
1.1 |
#!/bin/sh |
2 |
|
|
#--------------------------------------------------------------------- |
3 |
|
|
#- Adjusting net filter updater daemon |
4 |
|
|
#- rabit@netfrag.org, 01.11.2004 |
5 |
|
|
I='$Id$' |
6 |
|
|
#--------------------------------------------------------------------- |
7 |
|
|
#- Functions: |
8 |
|
|
|
9 |
|
|
# Syntax: dropaddress <IP_address> |
10 |
|
|
# |
11 |
|
|
dropaddress() { |
12 |
|
|
local IP LogMsg RegEx RuleCount |
13 |
|
|
|
14 |
|
|
if [ -n "$EXCLUDE" ]; then |
15 |
|
|
for IP in $EXCLUDE; do |
16 |
|
|
case $1 in |
17 |
|
|
($IP) |
18 |
|
|
logmessage "Ignoring excluded address '$1'." |
19 |
|
|
return 1 |
20 |
|
|
;; |
21 |
|
|
esac |
22 |
|
|
done |
23 |
|
|
fi |
24 |
|
|
|
25 |
|
|
RegEx='DROP.*'$1 |
26 |
|
|
RuleCount=`iptables -L INPUT -n | egrep $RegEx | wc -l` |
27 |
|
|
|
28 |
|
|
if [ $RuleCount == 0 ]; then |
29 |
|
|
|
30 |
|
|
if [ "$PRETEND" == 1 ]; then |
31 |
|
|
logmessage "(PRETEND) Dropping rule for address '$1' now would be inserted." |
32 |
|
|
else |
33 |
|
|
iptables -I INPUT -s $1 -j DROP |
34 |
|
|
|
35 |
|
|
LogMsg="Dropping rule for address '$1' has been inserted." |
36 |
|
|
logmessage "$LogMsg" |
37 |
|
|
|
38 |
|
|
[ -n "$LOG_DROPPED" ] && syslogwarning "$LogMsg" |
39 |
|
|
fi |
40 |
|
|
|
41 |
|
|
else |
42 |
|
|
logmessage "Address '$1' already gets dropped by $RuleCount rule(s). Doing nothing." |
43 |
|
|
fi |
44 |
|
|
|
45 |
|
|
return |
46 |
|
|
} |
47 |
|
|
|
48 |
|
|
# Syntax: echo_log [<Message>] |
49 |
|
|
# |
50 |
|
|
echo_log() { |
51 |
|
|
[ -n "$LOGTARGET" ] && echo $1 >>$LOGTARGET |
52 |
|
|
|
53 |
|
|
return $? |
54 |
|
|
} |
55 |
|
|
|
56 |
|
|
# Syntax: end [<ExitVal>] |
57 |
|
|
# |
58 |
|
|
end() { |
59 |
|
|
ExitVal=${1:-0} |
60 |
|
|
|
61 |
|
|
logmessage "Closing session. Exit code is '$ExitVal'." |
62 |
|
|
|
63 |
|
|
exit $ExitVal |
64 |
|
|
|
65 |
|
|
return |
66 |
|
|
} |
67 |
|
|
|
68 |
|
|
# Syntax: includeconf |
69 |
|
|
# |
70 |
|
|
includeconf() { |
71 |
|
|
# If existant, include the 'anfud.conf' file: |
72 |
|
|
[ -e /etc/anfud.conf ] && source /etc/anfud.conf |
73 |
|
|
|
74 |
|
|
return $? |
75 |
|
|
} |
76 |
|
|
|
77 |
|
|
# Syntax: init |
78 |
|
|
# |
79 |
|
|
init() { |
80 |
|
|
# Include the configuration file: |
81 |
|
|
includeconf |
82 |
|
|
|
83 |
|
|
# Set the default output log target: |
84 |
|
|
[ -z "$LOGTARGET" ] && LOGTARGET=/var/log/anfud.log |
85 |
|
|
|
86 |
|
|
echo_log # Before starting, output a blank line. |
87 |
|
|
logmessage "Session started ($A)." |
88 |
|
|
|
89 |
|
|
return |
90 |
|
|
} |
91 |
|
|
|
92 |
|
|
# Syntax: logmessage "<Message>" |
93 |
|
|
# |
94 |
|
|
logmessage() { |
95 |
|
|
echo_log "`date +'%b %e %H:%M:%S'` $N[$$]: $1" |
96 |
|
|
|
97 |
|
|
return $? |
98 |
|
|
} |
99 |
|
|
|
100 |
|
|
# Syntax: syslogwarning "<Message>" |
101 |
|
|
# |
102 |
|
|
syslogwarning() { |
103 |
|
|
logger -p warning -t $N[$$] $1 |
104 |
|
|
|
105 |
|
|
return $? |
106 |
|
|
} |
107 |
|
|
|
108 |
|
|
#--------------------------------------------------------------------- |
109 |
|
|
#- Signal trapping: |
110 |
|
|
|
111 |
|
|
trap 'logmessage "Recieved signal 1 (SIGHUP)."; end' 1 |
112 |
|
|
trap 'logmessage "Recieved signal 2 (SIGINT)."; end' 2 |
113 |
|
|
trap 'logmessage "Recieved signal 3 (SIGQUIT)."; end' 3 |
114 |
|
|
#trap 'logmessage "Recieved signal 4 (SIGILL)."; end' 4 |
115 |
|
|
#trap 'logmessage "Recieved signal 6 (SIGABRT)."; end' 6 |
116 |
|
|
trap 'logmessage "Recieved signal 9 (SIGKILL)."; end' 9 |
117 |
|
|
trap 'logmessage "Recieved signal 15 (SIGTERM)."; end' 15 |
118 |
|
|
|
119 |
|
|
#--------------------------------------------------------------------- |
120 |
|
|
#- Constants: |
121 |
|
|
|
122 |
|
|
# Extract the basename: |
123 |
|
|
N=$(basename $0) |
124 |
|
|
|
125 |
|
|
# Format the CVS ID line: |
126 |
|
|
|
127 |
|
|
I=${I:5} |
128 |
|
|
|
129 |
|
|
if [ -n "$I" ]; then |
130 |
|
|
#while read Name Ver Date Time User Exp; do |
131 |
|
|
# A="${Name/,v} v$Ver by $User ($Date, $Time)" |
132 |
|
|
#done < <(echo $I) |
133 |
|
|
A=$I |
134 |
|
|
else |
135 |
|
|
A="No CVS ID yet" |
136 |
|
|
fi |
137 |
|
|
|
138 |
|
|
#- Match masks: |
139 |
|
|
|
140 |
|
|
# Example lines from '/var/log/auth.log' where SSH login failed: |
141 |
|
|
#"Jan 1 00:00:00 machine sshd[1000]: Illegal user admin from 127.0.0.1" |
142 |
|
|
#"Jan 1 00:00:00 machine sshd[1000]: Failed password for root from 127.0.0.1 port 30000 ssh2" |
143 |
|
|
#"Jan 1 00:00:00 machine sshd[1000]: error: PAM: Authentication failure for root from 127.0.0.1" |
144 |
|
|
|
145 |
|
|
# Match mask for illegal SSH user login attempt: |
146 |
|
|
MatchP1='* sshd*: Illegal user *' |
147 |
|
|
|
148 |
|
|
# Match masks for SSH logins w/ failed password: |
149 |
|
|
MatchN2='* sshd*: Failed * for illegal user * from *' |
150 |
|
|
MatchP2='* sshd*: Failed password for * from *' |
151 |
|
|
|
152 |
|
|
# Match mask for SSH logins w/ incorrect password: |
153 |
|
|
MatchN3='* sshd*: error: PAM: Authentication failure for illegal user * from *' |
154 |
|
|
MatchP3='* sshd*: error: PAM: Authentication failure for * from *' |
155 |
|
|
|
156 |
|
|
# Example lines from '/var/log/auth.log' where FTP login failed: |
157 |
|
|
#"Jan 1 00:00:00 machine ftpd[17986]: FTP LOGIN FAILED FROM host.domain, root" |
158 |
|
|
|
159 |
|
|
MatchFTP_P1='* ftpd*: FTP LOGIN FAILED FROM *, *' |
160 |
|
|
|
161 |
|
|
#--------------------------------------------------------------------- |
162 |
|
|
#- Initialise: |
163 |
|
|
|
164 |
|
|
init |
165 |
|
|
|
166 |
|
|
#--------------------------------------------------------------------- |
167 |
|
|
#- Default parameters: |
168 |
|
|
|
169 |
|
|
# The log file to be scanned for intrusion attempts: |
170 |
|
|
# (default: "SCANLOG=/var/log/syslog") |
171 |
|
|
[ -z "$SCANLOG" ] && [ -e /var/log/syslog ] && SCANLOG=/var/log/syslog |
172 |
|
|
|
173 |
|
|
# On start seek and parse log file from beginning: |
174 |
|
|
# (default: "SEEKSTART=1") |
175 |
|
|
[ -z "$SEEKSTART" ] && SEEKSTART=1 |
176 |
|
|
|
177 |
|
|
# Follow the scan log file: |
178 |
|
|
# (default: "LOGFOLLOW=1") |
179 |
|
|
[ -z "$LOGFOLLOW" ] && LOGFOLLOW=1 |
180 |
|
|
|
181 |
|
|
# Time between log file scans (in seconds): |
182 |
|
|
# (default: "INTERVAL=1") |
183 |
|
|
[ -z "$INTERVAL" ] && INTERVAL=1 |
184 |
|
|
|
185 |
|
|
# Drop when illegal SSH login username: |
186 |
|
|
# (default: "DROP_SSH_ILLEGALUSER=1") |
187 |
|
|
[ -z "$DROP_SSH_ILLEGALUSER" ] && DROP_SSH_ILLEGALUSER=1 |
188 |
|
|
|
189 |
|
|
# Drop when FTP login failed: |
190 |
|
|
# (default: "DROP_FTP_FAILEDLOGIN=1") |
191 |
|
|
[ -z "$DROP_FTP_FAILEDLOGIN" ] && DROP_FTP_FAILEDLOGIN=1 |
192 |
|
|
|
193 |
|
|
# Log address dropping to the system log: |
194 |
|
|
# (default: "LOG_DROPPED=1") |
195 |
|
|
[ -z "$LOG_DROPPED" ] && LOG_DROPPED=1 |
196 |
|
|
|
197 |
|
|
# Pretend operation(s) (parse only): |
198 |
|
|
# (default: "PRETEND=0") |
199 |
|
|
[ -z "$PRETEND" ] && PRETEND=0 |
200 |
|
|
|
201 |
|
|
#--------------------------------------------------------------------- |
202 |
|
|
#- Early exit conditions: |
203 |
|
|
|
204 |
|
|
if [ -z "$SCANLOG" ] || [ ! -f "$SCANLOG" ]; then |
205 |
|
|
logmessage "ERROR: No log file to scan. Nothing to do for me." |
206 |
|
|
end 1 |
207 |
|
|
fi |
208 |
|
|
|
209 |
|
|
if [ $SEEKSTART != 1 ] && [ $LOGFOLLOW == 0 ]; then |
210 |
|
|
logmessage "ERROR: No seek, no follow. Nothing to do for me." |
211 |
|
|
end 1 |
212 |
|
|
fi |
213 |
|
|
|
214 |
|
|
#--------------------------------------------------------------------- |
215 |
|
|
|
216 |
|
|
# Flag for marking the first run: |
217 |
|
|
FirstRun=1 |
218 |
|
|
|
219 |
|
|
while [ -e $SCANLOG ]; do |
220 |
|
|
|
221 |
|
|
#LogSize=`du -b $SCANLOG | cut -f1` |
222 |
|
|
LogSize=$(stat -c %s $SCANLOG) |
223 |
|
|
|
224 |
|
|
if [ "$FirstRun" == 1 ]; then |
225 |
|
|
if [ "$SEEKSTART" == 1 ]; then |
226 |
|
|
logmessage "Reading '$SCANLOG' from start. File size is '$LogSize' bytes." |
227 |
|
|
else |
228 |
|
|
OldLogSize=$LogSize |
229 |
|
|
fi |
230 |
|
|
fi |
231 |
|
|
|
232 |
|
|
if ((LogSize > OldLogSize)); then |
233 |
|
|
|
234 |
|
|
tail --bytes=$[LogSize - OldLogSize] $SCANLOG | \ |
235 |
|
|
while read LogFileLine; do |
236 |
|
|
|
237 |
|
|
case "$LogFileLine" in |
238 |
|
|
|
239 |
|
|
($MatchP1) |
240 |
|
|
IP=`echo "\$LogFileLine" | cut -d' ' -f11` |
241 |
|
|
DateTime=`echo "\$LogFileLine" | cut -d' ' -f1-4` |
242 |
|
|
Username=`echo "\$LogFileLine" | cut -d' ' -f9` |
243 |
|
|
logmessage "SSH: illegal login as '$Username' from '$IP' at '$DateTime'." |
244 |
|
|
[ "$DROP_SSH_ILLEGALUSER" == 1 ] && dropaddress $IP |
245 |
|
|
;; |
246 |
|
|
|
247 |
|
|
($MatchN2) |
248 |
|
|
;; |
249 |
|
|
|
250 |
|
|
($MatchP2) |
251 |
|
|
IP=`echo "\$LogFileLine" | cut -d' ' -f12` |
252 |
|
|
DateTime=`echo "\$LogFileLine" | cut -d' ' -f1-4` |
253 |
|
|
Username=`echo "\$LogFileLine" | cut -d' ' -f10` |
254 |
|
|
logmessage "SSH: failed password for '$Username' from '$IP' at '$DateTime'." |
255 |
|
|
dropaddress $IP |
256 |
|
|
;; |
257 |
|
|
|
258 |
|
|
($MatchN3) |
259 |
|
|
;; |
260 |
|
|
|
261 |
|
|
($MatchP3) |
262 |
|
|
IP=`echo "\$LogFileLine" | cut -d' ' -f14` |
263 |
|
|
DateTime=`echo "\$LogFileLine" | cut -d' ' -f1-4` |
264 |
|
|
Username=`echo "\$LogFileLine" | cut -d' ' -f12` |
265 |
|
|
logmessage "SSH: incorrect password for '$Username' from '$IP' at '$DateTime'." |
266 |
|
|
dropaddress $IP |
267 |
|
|
;; |
268 |
|
|
|
269 |
|
|
($MatchFTP_P1) |
270 |
|
|
Address=`echo "\$LogFileLine" | cut -d' ' -f11` |
271 |
|
|
DateTime=`echo "\$LogFileLine" | cut -d' ' -f1-4` |
272 |
|
|
Username=`echo "\$LogFileLine" | cut -d' ' -f12` |
273 |
|
|
Address=${Address/,} |
274 |
|
|
IP=$(resolveip -s $Address) |
275 |
|
|
logmessage "FTP: failed login as '$Username' from '$IP' at '$DateTime'." |
276 |
|
|
[ "$DROP_FTP_FAILEDLOGIN" == 1 ] && dropaddress $IP |
277 |
|
|
;; |
278 |
|
|
|
279 |
|
|
esac |
280 |
|
|
done |
281 |
|
|
|
282 |
|
|
elif ((OldLogSize > LogSize)); then |
283 |
|
|
logmessage "'$SCANLOG' has been truncated. New file size is '$LogSize' bytes." |
284 |
|
|
fi |
285 |
|
|
|
286 |
|
|
OldLogSize=$LogSize |
287 |
|
|
|
288 |
|
|
[ "$LOGFOLLOW" != 1 ] && end |
289 |
|
|
|
290 |
|
|
[ "$FirstRun" == 1 ] && [ "$LOGFOLLOW" == 1 ] && \ |
291 |
|
|
logmessage "Following. Scanning '$SCANLOG' every '$INTERVAL' second(s)." |
292 |
|
|
|
293 |
|
|
# First run just ended: |
294 |
|
|
FirstRun=0 |
295 |
|
|
|
296 |
|
|
# Make the defined pause: |
297 |
|
|
sleep $INTERVAL |
298 |
|
|
done |
299 |
|
|
|
300 |
|
|
#--------------------------------------------------------------------- |