Current location

narf Source control manager Git

summaryrefslogtreecommitdiff
blob: 06831f09bd5f3bec354d4f0802563cdef01743b3 (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
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
#!/bin/sh
# Script to trawl logs for nastiness and log bad IP addresses
# From http://netnix.blogspot.com/2005/06/openbsd-ssh-protection.html
# Warning and whitelist features by Olivier Mehani <shtrom-openbsd@ssji.net>
#
# Minimal pf.conf file:
#  table <whitelist> persist file "/etc/whitelist"
#  table <kiddies> persist file "/etc/blockers.list"
#  pass in quick on egress proto tcp from <whitelist> to (egress) port ssh
#  block in quick on $ext_if from <kiddies>
# Crontab entry:
#  */5     *       *       *       *       /usr/local/sbin/denyhost.sh
#
# Remember to manually populate your <whitelist> table:
#  # pfctl -vt whitelist -T add ADDRESS
# or by creating file /etc/whitelist (adding it to /etc/changelist may
# also be a good idea)
#

LOCAL_ADDR=root@`hostname`
HTTP_LOG=/srv/www/logs/access_log
HTTP_PATTERN="etc.passwd"
SSH_LOG=/var/log/authlog
SSH_PATTERN=".*\(ailed password\).*from \([0-9a-fA-F.:]\+\).*"
AUTHTRIES=3 # single digit
EXPIRY=604800 # s; 1w
BLOCKERS_FILE=/etc/blockers.list
TMP_DIR=/tmp

PATH=/usr/local/bin:$PATH

PIDFILE=/var/run/denyhost.sh.pid

MAIL=mail

# Exit if another instance is already running.
if test -e $PIDFILE && kill -0 `cat $PIDFILE` 2>/dev/null; then
  echo "$0 process already running (`cat $PIDFILE`), exiting" >&2
  exit 0
else
  echo $$ > $PIDFILE
fi

function process_ip
{
	HOST_FILE=`mktemp ${TMP_DIR}/denyhost.host.XXXXXX`
	host $IP > $HOST_FILE
	HOSTS=`gsed -n "s/.*\(:\|domain name pointer\) \(.\+\)/\2/p" $HOST_FILE | \
		gsed ':a N;s/\n/, /g; ta'`

	WHOIS_FILE=`mktemp ${TMP_DIR}/denyhost.whois.XXXXXX`
	whois $IP > $WHOIS_FILE
	ABUSE=`extract_email $WHOIS_FILE`

	HTTP_HOST_LOG=`mktemp ${TMP_DIR}/denyhost.host_http.log.XXXXXX`
	grep $IP $HTTP_FILTERED_LOG > $HTTP_HOST_LOG

	SSH_HOST_LOG=`mktemp ${TMP_DIR}/denyhost.host_ssh.log.XXXXXX`
	grep $IP $SSH_FILTERED_LOG > $SSH_HOST_LOG
	LOGINS=`gsed -n "s/.*sshd\[[0-9]\+\]: \(Invalid user\|Failed password for\( invalid user\)\?\) \([^[:space:]]\+\) from.*/\3/p" $SSH_HOST_LOG | \
		sort | uniq | gsed ':a N;s/\n/, /g; ta'`

	if [ -z "$ABUSE" ]; then
		NETS=`gsed -n "s/.*\(NET-[-0-9]\+\).*/\1/p" $WHOIS_FILE`
		for NET in $NETS; do
			whois $NET >> $WHOIS_FILE
		done
		ABUSE=`extract_email $WHOIS_FILE`
	fi

	if [ -z "$ABUSE" ]; then
		DEST_ADDR="${LOCAL_ADDR}"
		SUBJECT="Host $IP (admin unknown) is compromised"
	else
		DEST_ADDR="$ABUSE"
		CC="-c $LOCAL_ADDR"
		SUBJECT="Host $IP is compromised"
	fi
		(
	if [ -n "$ABUSE" ]; then
		cat << EOF
Greetings,

[ This is an automated email, please report any problem to
<shtrom-admin@ssji.net> ]

Unauthorised login attempts have recently been observed from an IP address
in one of your administrative ranges ($IP), as identified by WHOIS
information.

Please find below reports from the blocking system, including logs of
connection attempts at the bottom.

Could you please take this machine down for cleanup, or forward this
message to its administrator in charge.

EOF
	fi
	echo "Offending IP: $IP"
	echo "Hostnames: $HOSTS"
	echo "Abuse addresses: $ABUSE"
	echo "Usernames tried: $LOGINS"
	echo
	echo "Host and WHOIS information:"
	cat $HOST_FILE
	cat $WHOIS_FILE
	echo
	echo "Incriminating logs (HTTP):"
	cat $HTTP_HOST_LOG
	echo
	echo "Incriminating logs (SSH):"
	cat $SSH_HOST_LOG
	) | $MAIL ${CC} -s "${SUBJECT}" $DEST_ADDR

	rm -f $HOST_FILE $WHOIS_FILE $SSH_HOST_LOG $HTTP_HOST_LOG
}

function extract_email
{
	gsed -ne "/abuse.*@/{ \
		/whois-contact@lacnic.net/d; \
		/mail-abuse@cert.br/d; \
		/cert@cert.br/d; \
		/search-apnic-not-arin@apnic.net/d; \
		/hostmaster@nic.ad.jp/d; \
		/hostmaster@ripe.net/d; \
		/.*@apnic.net/d; \
		/abusepoc@afrinic.net/d; \
		/ncc@ripe.net/d; \
		/search-ripe-ncc-not-arin@ripe.net/d; \
		s/.*[^-+\._A-Za-z0-9]\([-+\._A-Za-z0-9]\+@\([-A-Za-z0-9]\+\.\)\+[A-Za-z]\+\).*/\1/p \
		}" \
		$1 |
		sort | uniq | gsed ':a N;s/\n/, /g; ta'
}

NEW_BLOCKERS_FILE=`mktemp ${TMP_DIR}/denyhost.blockers.list.XXXXXX`

# HTTP exploiters
HTTP_FILTERED_LOG=`mktemp ${TMP_DIR}/denyhost.http.log.XXXXXX`
grep -v -f ${BLOCKERS_FILE} ${HTTP_LOG} \
	> ${HTTP_FILTERED_LOG}
grep ${HTTP_PATTERN} ${HTTP_FILTERED_LOG} | cut -d" " -f 2 | \
	uniq >> ${NEW_BLOCKERS_FILE}

# SSH exploiters
SSH_FILTERED_LOG=`mktemp ${TMP_DIR}/denyhost.ssh.log.XXXXXX`
grep -v "Received disconnect" ${SSH_LOG} | \
	grep -v -f ${BLOCKERS_FILE} \
	> ${SSH_FILTERED_LOG}
gsed -n "s/${SSH_PATTERN}/\2/p" ${SSH_FILTERED_LOG} | \
	sort | uniq -c | \
	gsed "/^ *[1-$AUTHTRIES] */d;s/.* //" \
	>> ${NEW_BLOCKERS_FILE}

for IP in `cat $NEW_BLOCKERS_FILE`; do
	process_ip $IP
done

# Flush entries older than a week
pfctl -t kiddies -T expire $EXPIRY 1>/dev/null 2>&1

# Add new entries
pfctl -t kiddies -Tadd -f ${NEW_BLOCKERS_FILE} 1>/dev/null 2>&1
pfctl -t kiddies -Tshow | sed 's/^ *//' > ${BLOCKERS_FILE}

rm ${HTTP_FILTERED_LOG} ${SSH_FILTERED_LOG} ${NEW_BLOCKERS_FILE}
rm ${PIDFILE}