Skip to content

Instantly share code, notes, and snippets.

@jblanche
Created August 30, 2008 13:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jblanche/8109 to your computer and use it in GitHub Desktop.
Save jblanche/8109 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
# Petit script permettant de regarder quel login s'est récemment connecté au
# serveur FTP et combien d'IP différentes ont été utilisé afin de détecter
# les personnes ayant fait un peu trop tourner leurs logins.
# Le format d'une ligne de log est le suivant :
# Sun Aug 24 10:08:52 2008 [pid 2949] [jblanche] OK LOGIN: Client "88.99.11.22"
require 'date'
require 'net/smtp'
class LogParser
attr_accessor :login_lines, :download_lines
def initialize(file)
@login_lines, @download_lines = [], []
lines = IO.read(file) + IO.read(file+'.1')
lines.each do |line|
@login_lines << LoginItem.new(line) if line.include? 'OK LOGIN'
@download_lines << DownloadItem.new(line) if line.include? 'DOWNLOAD'
end
end
def last_week_logins
@login_lines.select {|item| item.date > Date.today-7}
end
def last_day_downloads
@download_lines.select {|item| item.date > Date.today-1}
end
end
class LogItem
@@items = []
attr_accessor :date, :owner, :ip, :line_items
def initialize(line)
@line_items = line.split
@owner = @line_items[7].gsub(/[\[\]]/,'')
@date = Date.parse(@line_items[0..2].join(' '))
end
end
class LoginItem < LogItem
def initialize(line)
super
@ip = @line_items.last.gsub('"','')
@@items << self
end
end
class DownloadItem < LogItem
attr_accessor :size
def initialize(line)
super
@ip = @line_items[11].gsub(/[",]/,'')
@size = line_items[13]
@@items << self
end
end
class User
include Enumerable
IPS_LIMIT = 2
@@users = []
attr_accessor :login, :ips, :download_size
def initialize(login)
@login, @ips, @download_size = login, [], 0
@@users << self
end
def add(ip)
@ips << ip unless @ips.include? ip
end
def self.find_or_create_by_login(login)
self.find(login) || new(login)
end
def cheater?
@ips.size > IPS_LIMIT
end
def <=>(user)
download_size <=> user.download_size
end
def self.cheaters
@@users.select {|p| p.cheater? }
end
def self.all
@@users.sort.reverse
end
private
def self.find(login)
@@users.find{|p| p.login == login}
end
end
class SizeFormater
def self.number_to_human_size(size, precision=1)
size = Kernel.Float(size)
case
when size.to_i == 1; "1 Byte"
when size < 1024; "%d Bytes" % size
when size < 1024**2; "%.#{precision}f KB" % (size / 1024)
when size < 1024**3; "%.#{precision}f MB" % (size / 1024**2)
when size < 1024**4; "%.#{precision}f GB" % (size / 1024**3)
else "%.#{precision}f TB" % (size / 1024**4)
end.sub(/([0-9]\.\d*?)0+ /, '\1 ' ).sub(/\. /,' ')
end
end
class Mailer
def self.send(from, to, subject, message)
msg = <<END_OF_MESSAGE
From: #{from}
To: #{to}
Subject: #{subject}
#{message}
END_OF_MESSAGE
Net::SMTP.start('localhost') do |smtp|
smtp.send_message msg, from, to
end
end
end
LOG_FILE = '/var/log/vsftpd.log'
mail = ""
parser = LogParser.new(LOG_FILE)
parser.last_week_logins.each do |item|
user = User.find_or_create_by_login(item.owner)
user.add(item.ip)
end
User.cheaters.each do |user|
mail << "#{user.login} a utilise #{user.ips.size} adresses ip differentes pour se connecter \n"
end
mail << "===========================================================================================\n"
parser.last_day_downloads.each do |item|
user = User.find_or_create_by_login(item.owner)
user.download_size = user.download_size+item.size.to_i
end
User.all.each do |user|
mail << "#{user.login} a downloade #{SizeFormater.number_to_human_size(user.download_size.to_s)} bytes today \n"
end
Mailer.send('from@host.com', 'to@admin.com','reporting vsftp', mail)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment