/etc/init.d/iptables를 다음과 같이 만든다. (permission은 775)
#!/bin/sh -e
### BEGIN INIT INFO
# Provides: iptables
# Required-Start: networking ifupdown $local_fs
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
### END INIT INFO
IPTABLES=/sbin/iptables
EXT_ETH=eth0
${IPTABLES} -F
${IPTABLES} -t nat -F
${IPTABLES} -X BLACKLISTCHECK
${IPTABLES} -P INPUT ACCEPT
${IPTABLES} -P OUTPUT ACCEPT
${IPTABLES} -P FORWARD ACCEPT
${IPTABLES} -A INPUT -j ACCEPT -i lo
${IPTABLES} -A INPUT -j ACCEPT -p icmp --icmp-type any
${IPTABLES} -A INPUT -j ACCEPT -m state --state ESTABLISHED,RELATED
${IPTABLES} -N BLACKLISTCHECK
${IPTABLES} -A INPUT -j BLACKLISTCHECK -i ${EXT_ETH} -m state --state NEW -p tcp --dport 22
for x in `cat /tmp/ssh_evil`; do
${IPTABLES} -I BLACKLISTCHECK -s $x -j DROP
done
# 80, 22번 포트만 오픈
${IPTABLES} -A INPUT -j ACCEPT -i ${EXT_ETH} -m state --state NEW -p tcp --dport 22
${IPTABLES} -A INPUT -j ACCEPT -i ${EXT_ETH} -m state --state NEW -p tcp
--dport 80
${IPTABLES} -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --set
${IPTABLES} -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 6 -j LOG --log-prefix "SSH_brute_force "
${IPTABLES} -A INPUT -j REJECT --reject-with icmp-host-prohibited
/etc/init.d/swatch 파일이 없다면 다음의 내용으로 생성한다. (permission은 775)
#!/bin/sh -e
### BEGIN INIT INFO
# Provides: swatch
# Required-Start: networking ifupdown $local_fs
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
### END INIT INFO
PATH="/sbin:/bin:/usr/sbin:/usr/bin"
NAME="swatch"
DAEMON="/usr/bin/swatch"
DESC="simple watcher"
CONFFILE="/etc/swatch.conf"
#LOGFILE="/var/log/secure"
LOGFILE="/var/log/syslog"
PIDFILE="/var/run/swatch.pid"
OPTS="--config-file=$CONFFILE --tail-file=$LOGFILE --pid-file=$PIDFILE --awk-field-syntax --tail-args='-F' --daemon"
test -x $DAEMON || exit 0
start() {
if [ ! -f "$CONFFILE" ]; then
echo "Error: $CONFFILE does not exist."
exit 1
fi
if [ ! -f "$LOGFILE" ]; then
echo "Error: $LOGFILE does not exist."
exit 1
fi
if [ -f "$PIDFILE" ]
then
echo "Error: $NAME is already running."
else
$DAEMON $OPTS >/dev/null 2>&1
fi
}
stop() {
if [ -f "$PIDFILE" ]
then
PID=`cat $PIDFILE`
if ps h $PID > /dev/null
then
pkill -P $PID
kill $PID
else
echo "Error: $NAME is not running, but PID file exists. Deleting it."
fi
rm -f $PIDFILE
else
echo "Error: $NAME is not running."
fi
}
case "$1" in
start)
echo "Starting $DESC: $NAME"
start
;;
stop)
echo "Stopping $DESC: $NAME"
stop
;;
restart)
echo "Restarting $DESC: $NAME"
stop
sleep 1
start
;;
*)
echo "Usage: $0 start|stop|restart"
exit 1
;;
esac
exit 0
swatch.conf에는 다음을 추가한다.
perlcode my $sshscript = '/root/swatch-ssh';
watchfor /([a-zA-Z]{3})\s+([0-9]{1,2}) ([0-9]{2}:[0-9]{2}:[0-9]{2}) ([a-zA-Z0-9_-]+) kernel: \[.*\] SSH_brute_force .*SRC=(.*) DST=/
exec "$sshscript '$*' >> /var/log/swatch.log"
throttle 00:00:30
swatch에서 실행할 스크립트를 만든다.
/root/swatch-ssh 파일의 내용은 다음처럼 구성한다. (역시 permission은 775)
(다른 기능도 같이 하는 스크립트에서 일부만 발췌함)
#!/usr/bin/ruby1.8
if ARGV.length==0 && ARGV.length < 2
puts "Error!! Argument must more than 1 words!!"
puts "ex) swatch-ssh message"
exit 1
else
begin
message = ""
argv_msg = ARGV[0].split
host = argv_msg[3]
beginflag = false
for qs in argv_msg do
message = message + (message!=""?" ":"") + qs if beginflag == true
beginflag = true if qs == host
end
# for 3ware modules message
message.sub!(/kernel: \[[0-9\s]+\.[0-9]+\] /, '')
message.sub!(/\(.*\)/, '')
smsmessage = sprintf("[%s]%s\n", host, message)
# smsmessage.gsub!(' ', '_')
smsmessage.sub!(/\[mgm\]/, '')
smsmessage.sub!(/SSH_brute_force .* SRC=/, '')
smsmessage.sub!(/ DST=.*/, '')
File.open("/tmp/ssh_deny", 'a') {|f| f.write(smsmessage) }
command = sprintf("cat /tmp/ssh_evil /tmp/ssh_deny | sort -u > /tmp/ssh_uniq_evil ; rm /tmp/ssh_deny ; cp /tmp/ssh_uniq_evil /tmp/ssh_evil ; /etc/init.d/iptables")
# printf("%s\n", command)
system(command)
end
end
exit 0
이제 모든 준비는 완료되었습니다.
iptables 스크립트를 실행시키고 swatch를 restart하면 끝.
iptables -N BLACKLISTCHECK
touch /tmp/ssh_evil
update-rc.d iptables defaults 20
update-rc.d swatch defaults 20
/etc/init.d/iptables
/etc/init.d/swatch restart
위에서 설정한 내용은 다음과 같습니다.
1. iptables를 설정하여 ssh 연결이 1분에 6번 이상 연결되면 kernel에 log를 남기게 됩니다.
2. swatch에서는 iptables가 남긴 kernel log를 발견하게 되면 /root/swatch-ssh 스크립트를 실행시킵니다.
3. /root/swatch-ssh 스크립트에서는 해당 IP Address를 /tmp/ssh_evil 파일에 남기는 동시에 /etc/init.d/iptables 스크립트를 실행시켜서 발견된 IP Addreess를 통해서 들어오는 연결을 차단합니다.
위의 1,2,3 과정을 반복하면서 ssh brute force attack이 발견되면 해당 IP Address를 지속적으로 차단합니다.
작성자 : 저입니다. ^^