人力検索に応えてみた。
question:1136813234の質問に答えてみた。
class Observation
def Observation.start(arg)
Observation.new.start(arg)
end
def initialize
@blacklist = Hash.new{|hash,key| hash[key] = 0}
@judgement = 10
end
def start(target)
pipe = IO.popen(”tail -f #{target}”,’r’)
loop do
if (input = pipe.gets)
result = analyze(input)
if result[’protocol’] =~ /ssh/ && result[’success?’] == false
add_black(result[’ip’])
end
add_deny(result[’ip’]) if @blacklist[result[’ip’]] > @judgement
end
end
end
def analyze(str)
flag = true
ary = str.split
date = ary.slice!(0..2).join(’ ’)
host = ary.shift
protocol = ary.shift
if pos = ary.index(’from’)
ip = ary.slice!(pos + 1)
end
flag = false if ary.include?(’not’||’invalid’)
return {’date’ => ”#{date}”, ’host’ => ”#{host}”, ’protocol’ => ”#{protocol}”,
’ip’ => ”#{ip}”, ’success?’ => ”#{flag}”}
end
def add_black(ip)
@blacklist[ip] += 1
end
def add_deny(ip)
file = File.open(”/etc/hosts.deny”,’a+’)
file.flock(File::LOCK_EX)
file.puts(ip)
file.flock(File::LOCK_UN)
file.close
end
end
if $0 == __FILE__
Observation.start(’/var/log/messages’)
end
こんな感じ。
analyzeメソッドで解析してハッシュを返すってやり方はけっこう気に入ってるけど今になって思えばstartメソッドで判定するんじゃなくてjudgeメソッドを作ればよかったかなぁと思ったり思わなかったり。動かしてないけどこれちゃんと動くのかなぁ?