Parse Fail2ban output
#!/usr/bin/env ruby | |
# ruby fail2ban.rb logfile | sort -rn | head -25 | |
# ruby fail2ban.rb logfile | awk '{print $2}' | sort | uniq -c | sort -rn | head -15 | |
require 'time' | |
networks = {} | |
module MBox | |
class Mail | |
def self.begin?(line) | |
if line.unpack('C*').pack("U*") =~ /\AFrom\s([^\s]+)\s(.+)\n/ | |
yield $1, DateTime.parse($2) | |
return true | |
end | |
end | |
attr_reader :header, :body | |
def initialize(from, time) | |
@meta, @header, @body = true, {}, String.new | |
end | |
def <<(line) | |
@meta = false if @meta and line.unpack('C*').pack("U*") =~ /\A\n/ | |
if @meta | |
case line.unpack('C*').pack("U*") | |
when /\A([^\s:]+):(.*)\n/ then @queue = @header[$1] = $2.strip | |
when /\A\s+(.+)\n/ then @queue << ' ' + $1.strip | |
else raise ArgumentError, 'Header contains inappropriate line' | |
end | |
else @body << line.unpack('C*').pack("U*") | |
end | |
end | |
end | |
extend self | |
def parse(file, mails = []) | |
File.open file do |fd| | |
raise ArgumentError, 'Not a valid mbox format' unless Mail.begin? fd.readline do |from, time| | |
mails << Mail.new(from, time) | |
end | |
fd.each do |line| | |
case | |
when Mail.begin?(line) { |from, time| mails << Mail.new(from, time) } | |
else mails.last << line | |
end | |
end | |
end; mails | |
end | |
end | |
unless !ARGV[0].nil? and File.readable? ARGV[0] | |
puts 'Usage: fail2ban.rb file' | |
exit | |
end | |
MBox.parse(ARGV[0]).each do |mail| | |
name = String.new | |
mail.body.upcase.match /^NETNAME:\s+(.+)\n/ do | |
if networks[$1].nil? then networks[name = $1] = { count: 0 } | |
else networks[$1][:count] += 1 | |
end | |
end | |
unless name.empty? | |
mail.body.upcase.scan /^(.+):\s+(.+)\n/ do |key, value| | |
networks[name][:country] = value if key == 'COUNTRY' | |
end | |
end | |
end | |
networks.each do |key, value| | |
puts value[:count].to_s + "\t" + | |
value[:country] + "\t" + | |
key | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment