gltail 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,50 @@
1
+ # gl_tail.rb - OpenGL visualization of your server traffic
2
+ # Copyright 2007 Erlend Simonsen <mr@fudgie.org>
3
+ #
4
+ # Licensed under the GNU General Public License v2 (see LICENSE)
5
+ #
6
+
7
+ # Parser which handles logs from Cisco PIX or FWSM firewalls
8
+ # should also handle ASA logs, with minimal change...
9
+ # Leif Sawyer (leif@denali.net)
10
+ #
11
+
12
+ class PixParser < Parser
13
+ def parse( line )
14
+ if line.include?(': Built')
15
+ _, firewall, type, direction, srcif, src, srcport, dstif, dst, dstport =
16
+ /^.* \d+ \d+:\d+:\d+ \[?([a-zA-Z0-9\-]+)\/?\]?.* %(FWSM|PIX)-\d+-\d+: Built (\w+)bound \w+ connection \d+ for (\w+):([a-zA-Z0-9.]+)\/([a-zA-Z0-9.]+) \(.*\) to (\w+):([a-zA-Z0-9.]+)\/([a-zA-Z0-9.]+)/.match(line).to_a
17
+
18
+ if firewall
19
+ add_activity(:block => 'firewall', :name => firewall)
20
+ if direction == 'out'
21
+ add_activity(:block => 'hosts', :name => src)
22
+ add_activity(:block => 'sites', :name => dst)
23
+ else
24
+ add_activity(:block => 'hosts', :name => dst)
25
+ add_activity(:block => 'sites', :name => src)
26
+ end
27
+ printf("%sbound from %s firewall '%s', srcif=%s, src=%s, srcport=%s, dstif=%s, dst=%s, dstport=%s...\n", direction, type, firewall, srcif, src, srcport, dstif, dst, dstport ) if $VRB > 0
28
+ end
29
+
30
+ elsif line.include?('Accessed URL')
31
+ _, firewall, type, client, server, url = /^.* \d+ \d+:\d+:\d+ \[?([a-zA-Z0-9\-]+)\/?\]?.* %(FWSM|PIX)-\d+-\d+: ([a-zA-Z0-9.]+) Accessed URL ([a-zA-Z0-9.]+):(.*)[\?]?/.match(line).to_a
32
+ if firewall
33
+ add_activity(:block => 'firewall', :name => firewall)
34
+ add_activity(:block => 'hosts', :name => client)
35
+ add_activity(:block => 'sites', :name => server)
36
+ add_activity(:block => 'urls', :name => url)
37
+ printf("%s firewall '%s': client %s accessed url %s on host %s\n", type, firewall, client, url, server) if $VRB > 0
38
+ end
39
+
40
+ # elsif line.include?(': Deny')
41
+ # Deny udp src outside:_SRC_IP_/_SRC_PORT_ dst inside:_DST_IP_/_DST_PORT_ by access-group "_ACL_NAME"
42
+ # printf("ACL denied access ...\n") if $VRB > 0
43
+
44
+ # elsif line.include?('static translation')
45
+ # Teardown static translation from inside:_SRC_IP_ to dmz-anc-csa:_DST_IP_ duration 0:01:00
46
+ # printf("static translation ...\n") if $VRB > 0
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,119 @@
1
+ # gl_tail.rb - OpenGL visualization of your server traffic
2
+ # Copyright 2007 Erlend Simonsen <mr@fudgie.org>
3
+ #
4
+ # Licensed under the GNU General Public License v2 (see LICENSE)
5
+
6
+ # Parser which handles Postfix logs
7
+ class PostfixParser < Parser
8
+ def parse( line )
9
+ if line.include?(': connect from')
10
+ _, host, ip = /: connect from ([^\[]+)\[(\d+.\d+.\d+.\d+)\]/.match(line).to_a
11
+ if host
12
+ host = ip if host == 'unknown'
13
+ add_activity(:block => 'smtp', :name => host, :size => 0.03)
14
+ end
15
+ elsif line.include?(' sasl_username=')
16
+ _, username = /, sasl_username=(.*)/.match(line).to_a
17
+ add_activity(:block => 'logins', :name => "#{username}/sasl", :size => 0.1)
18
+ elsif line.include?('NOQUEUE: reject:')
19
+ #
20
+ # Parse rejection messages, including RBL rejections.
21
+ # The rejection status could be displayed with the actual error codes if desired.
22
+ # Change :name => 'rejected'
23
+ # To :name => status
24
+ # Or :name => extstatus
25
+ #
26
+ _, host, ip, status, extstatus, rejectreason, from, to, proto, helo = /: reject: RCPT from ([^\[]+)\[(\d+.\d+.\d+.\d+)\]: (\d+) (\d.\d.\d) (.*) from=<([^>]+)> to=<([^>]+)> proto=(.*) helo=<([^>]+)>/.match(line).to_a
27
+ add_activity(:block => 'status', :name => 'rejected', :size => 0.03)
28
+ host = ip if host == 'unknown'
29
+ if not rejectreason.nil?
30
+ if rejectreason.include?(' blocked using ')
31
+ rbltype = 'rbl'
32
+ if rejectreason.include?('Sender address')
33
+ # RHSBL-stle rejection message
34
+ _, ip, rbl, rbltext = /Sender address \[([^>]+)\] blocked using (.*)\; (.*)\;/.match(rejectreason).to_a
35
+ rbltype = 'rhsbl'
36
+ else
37
+ # Plain RBL rejection message
38
+ _, ip, rbl, rbltext = /Client host \[(\d+.\d+.\d+.\d+)\] blocked using (.*)\; (.*)\;/.match(rejectreason).to_a
39
+ end
40
+ if not rbl.nil?
41
+ # add_activity(:block => 'rejections', :name => host, :size => 0.03)
42
+ add_activity(:block => 'rejections', :name => rbltype + ' ' + rbl, :size => 0.03)
43
+ end
44
+ else
45
+ # Generic rejection message, print the whole thing.
46
+ _, address, reason = /<([^>]+)>\: (.*);/.match(rejectreason).to_a
47
+ # add_activity(:block => 'rejections', :name => host, :size => 0.03)
48
+ add_activity(:block => 'rejections', :name => reason, :size => 0.03)
49
+ end
50
+ end
51
+ elsif line.include?(' from=<')
52
+ _, from, size = /: from=<([^>]+)>, size=(\d+)/.match(line).to_a
53
+ if from
54
+ add_activity(:block => 'mail from', :name => from, :size => size.to_f/100000.0)
55
+ end
56
+ elsif line.include?(' to=<')
57
+ if line.include?('relay=local')
58
+ # Incoming
59
+ _, to, delay, status = /: to=<([^>]+)>, .*delay=([\d.]+).*status=([^ ]+)/.match(line).to_a
60
+ add_activity(:block => 'mail to', :name => to, :size => delay.to_f/10.0, :type => 5, :color => [1.0, 0.0, 1.0, 1.0])
61
+ add_activity(:block => 'status', :name => 'received', :size => delay.to_f/10.0, :type => 3)
62
+ else
63
+ # Outgoing
64
+ _, to, relay_host, delay, status = /: to=<([^>]+)>.*relay=([^\[,]+).*delay=([\d.]+).*status=([^ ]+)/.match(line).to_a
65
+ add_activity(:block => 'mail from', :name => to, :size => delay.to_f/10.0)
66
+ add_activity(:block => 'smtp', :name => relay_host, :size => delay.to_f/10.0)
67
+ add_activity(:block => 'status', :name => status, :size => delay.to_f/10.0, :type => 3)
68
+ end
69
+ elsif line.include?('spamd:') and (line.include?('clean message') or line.include?('identified spam'))
70
+ #
71
+ # Parse spamd log entries for the result summary, and add the clean/spam status to the status block.
72
+ #
73
+ # NOTE/TODO: Much more could be done with this block, including averaging scores and processing times
74
+ #
75
+ _, status, score, mailaddr, proctime, size = /: spamd: (\w+ \w+) \((\d+\.\d+)\/.*\) for (.*):.* in (\d+\.\d+) seconds, (\d+) bytes/.match(line).to_a
76
+ if not status.nil?
77
+ status = status.include?('clean') ? 'clean' : 'spam'
78
+ add_activity(:block => 'status', :name => status, :size => proctime.to_f/10.0)
79
+ end
80
+ elsif line.include?('clamd[')
81
+ #
82
+ # Parse clamd log entries. Print the name of the detected virus.
83
+ #
84
+ _, virusname = /clamd\[\d+\]: .*: (.*) FOUND/.match(line).to_a
85
+ add_activity(:block => 'status', :name => 'virus', :size => 0.03)
86
+ add_activity(:block => 'viruses', :name => virusname, :size => 0.03)
87
+ elsif line.include?(': warning:')
88
+ #
89
+ # Parse warning messages. If it is a known warning, shorten the message, otherwise print the full text
90
+ #
91
+ _, warningtext = /: warning: (.*)/.match(line).to_a
92
+ if warningtext.include?('malformed domain name')
93
+ warningtext = 'Malformed Domain Name'
94
+ elsif warningtext.include?('non-SMTP command')
95
+ warningtext = 'Non-SMTP Command'
96
+ elsif warningtext.include?('Non-recoverable failure in name resolution')
97
+ warningtext = 'DNS Failure'
98
+ elsif warningtext.include?('hostname nor servname provided')
99
+ warningtext = 'Host Verification Failure'
100
+ elsif warningtext.include?('address not listed for hostname')
101
+ warningtext = 'Hostname Without Address'
102
+ elsif warningtext.include?('Connection rate limit exceeded')
103
+ warningtext = 'Per-Host Connection Rate Exceeded'
104
+ elsif warningtext.include?('Connection concurrency limit exceeded')
105
+ warningtext = 'Per-Host Connection concurrency Exceeded'
106
+ elsif warningtext.include?('numeric domain name in resource data')
107
+ warningtext = 'Numeric Domain Name'
108
+ elsif warningtext.include?('numeric hostname')
109
+ warningtext = 'Numeric Host Name'
110
+ elsif warningtext.include?('valid_hostname: empty hostname')
111
+ warningtext = 'Empty Hostname'
112
+ elsif warningtext.include?('Illegal address syntax')
113
+ warningtext = 'Illegal Address Syntax'
114
+ end
115
+ add_activity(:block => 'status', :name => 'warning', :size => 0.03)
116
+ add_activity(:block => 'warnings', :name => warningtext, :size => 0.03)
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,42 @@
1
+ # gl_tail.rb - OpenGL visualization of your server traffic
2
+ # Copyright 2007 Erlend Simonsen <mr@fudgie.org>
3
+ #
4
+ # Licensed under the GNU General Public License v2 (see LICENSE)
5
+ #
6
+
7
+ # Parser which handles PostgreSQL logs
8
+ class PostgreSQLParser < Parser
9
+ def parse( line )
10
+ # here's an example parser for postgres log files; adjust accordingly for different logfile setups.
11
+ #
12
+ # postgresql.conf:
13
+ # log_line_prefix = '[%d, %t] '
14
+ # log_connections = on
15
+ # log_disconnections = on
16
+ # log_duration = on
17
+ # log_statement = 'all'
18
+
19
+ _, database, datetime, activity, description = /^\[(.*), (.* .* .*)\] LOG: ([a-zA-Z0-9\s]*): (.*)/.match(line).to_a
20
+
21
+ if database
22
+ add_activity(:block => 'database', :name => database, :size => 0.2)
23
+ else
24
+ _, datetime, activity, description = /^(.* .* .*) LOG: ([a-zA-Z0-9\s]*): (.*)/.match(line).to_a
25
+ end
26
+
27
+ if activity
28
+ activity = 'vacuum' if(description.include?('vacuum') || activity == 'autovacuum')
29
+ case activity
30
+ when 'duration'
31
+ add_activity(:block => 'database', :name => 'duration', :size => description.to_f / 100.0)
32
+ when 'statement'
33
+ add_activity(:block => 'database', :name => 'activity', :size => 0.2)
34
+ when 'connection authorized', 'disconnection'
35
+ add_activity(:block => 'database', :name => 'login/logout', :size => 0.2)
36
+ when 'vacuum'
37
+ add_event(:block => 'database', :name => 'vacuum', :message => description, :update_stats => true, :color => [1.0, 1.0, 0.0, 1.0])
38
+ end
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,30 @@
1
+ # gl_tail.rb - OpenGL visualization of your server traffic
2
+ # Copyright 2007 Erlend Simonsen <mr@fudgie.org>
3
+ #
4
+ # Licensed under the GNU General Public License v2 (see LICENSE)
5
+ #
6
+
7
+ # Parser which handles logs from PureFTPD
8
+ class PureftpdParser < Parser
9
+ def parse( line )
10
+ _, host, domain, user, date, url, status, size = /^([\d\S.]+) (\S+) (\S+) \[([^\]]+)\] \"(.+?)\" (\d+) ([\S]+)/.match(line).to_a
11
+
12
+ if host
13
+ user = host if user == 'ftp'
14
+
15
+ method, url = url.split(" ")
16
+ url = method if url.nil?
17
+
18
+ if method == "PUT"
19
+ add_activity(:block => 'urls', :name => url, :size => size.to_i, :type => 5)
20
+ else
21
+ add_activity(:block => 'urls', :name => url, :size => size.to_i)
22
+ end
23
+ add_activity(:block => 'sites', :name => server.name, :size => size.to_i) # Size of activity based on size of request
24
+ add_activity(:block => 'users', :name => user, :size => size.to_i)
25
+
26
+ add_activity(:block => 'content', :name => 'file')
27
+ add_activity(:block => 'status', :name => status, :type => 3) # don't show a blob
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ # gl_tail.rb - OpenGL visualization of your server traffic
2
+ # Copyright 2007 Erlend Simonsen <mr@fudgie.org>
3
+ #
4
+ # Licensed under the GNU General Public License v2 (see LICENSE)
5
+ #
6
+
7
+ # Parser which handles qmail logs
8
+ class QmailParser < Parser
9
+ def parse( line )
10
+ if line.include?(' logged in from ')
11
+ _, user, host, ip = /: User \'([^']+)\' of \'([^']+)\' logged in from (\d+.\d+.\d+.\d+)/.match(line).to_a
12
+ if host
13
+ add_activity(:block => 'logins', :name => user+'@'+host, :size => 0.05)
14
+ add_activity(:block => 'sites', :name => server.name, :size => 0.05)
15
+ end
16
+ elsif line.include?(' to local ')
17
+ _, prefix, host = / to local ([^@]+)@(.*)/.match(line).to_a
18
+ if host
19
+ add_activity(:block => 'mail to', :name => host, :size => 0.05)
20
+ add_activity(:block => 'sites', :name => server.name, :size => 0.05)
21
+ end
22
+ elsif line.include?(' to remote ')
23
+ _, prefix, host = / to remote ([^@]+)@(.*)/.match(line).to_a
24
+ if host
25
+ add_activity(:block => 'mail from', :name => host, :size => 0.05)
26
+ add_activity(:block => 'sites', :name => server.name, :size => 0.05)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,41 @@
1
+ # gl_tail.rb - OpenGL visualization of your server traffic
2
+ # Copyright 2007 Erlend Simonsen <mr@fudgie.org>
3
+ #
4
+ # Licensed under the GNU General Public License v2 (see LICENSE)
5
+ #
6
+
7
+ # Parser which handles Rails access logs
8
+ class RailsParser < Parser
9
+ def parse( line )
10
+ #Completed in 0.02100 (47 reqs/sec) | Rendering: 0.01374 (65%) | DB: 0.00570 (27%) | 200 OK [http://example.com/whatever/whatever]
11
+ _, ms, url = /^Completed in ([\d.]+) .* \[([^\]]+)\]/.match(line).to_a
12
+
13
+ if url
14
+ _, host, url = /^http[s]?:\/\/([^\/]+)(.*)/.match(url).to_a
15
+
16
+ add_activity(:block => 'sites', :name => host, :size => ms.to_f) # Size of activity based on request time.
17
+ add_activity(:block => 'urls', :name => HttpHelper.generalize_url(url), :size => ms.to_f)
18
+ add_activity(:block => 'slow requests', :name => url, :size => ms.to_f)
19
+ add_activity(:block => 'content', :name => 'page')
20
+
21
+ # Events to pop up
22
+ add_event(:block => 'info', :name => "Logins", :message => "Login...", :update_stats => true, :color => [0.5, 1.0, 0.5, 1.0]) if url.include?('/login')
23
+ add_event(:block => 'info', :name => "Sales", :message => "$", :update_stats => true, :color => [1.5, 0.0, 0.0, 1.0]) if url.include?('/checkout')
24
+ add_event(:block => 'info', :name => "Signups", :message => "New User...", :update_stats => true, :color => [1.0, 1.0, 1.0, 1.0]) if(url.include?('/signup') || url.include?('/users/create'))
25
+ elsif line.include?('Processing ')
26
+ #Processing TasksController#update_sheet_info (for 123.123.123.123 at 2007-10-05 22:34:33) [POST]
27
+ _, host = /^Processing .* \(for (\d+.\d+.\d+.\d+) at .*\).*$/.match(line).to_a
28
+ if host
29
+ add_activity(:block => 'users', :name => host)
30
+ end
31
+ elsif line.include?('Error (')
32
+ _, error, msg = /^([^ ]+Error) \((.*)\):/.match(line).to_a
33
+ if error
34
+ add_event(:block => 'info', :name => "Exceptions", :message => error, :update_stats => true, :color => [1.0, 0.0, 0.0, 1.0])
35
+ add_event(:block => 'info', :name => "Exceptions", :message => msg, :update_stats => false, :color => [1.0, 0.0, 0.0, 1.0])
36
+ add_activity(:block => 'warnings', :name => msg)
37
+
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,25 @@
1
+ # gl_tail.rb - OpenGL visualization of your server traffic
2
+ # Copyright 2007 Erlend Simonsen <mr@fudgie.org>
3
+ #
4
+ # Licensed under the GNU General Public License v2 (see LICENSE)
5
+ #
6
+
7
+ # Parser which handles squid logs
8
+ class SquidParser < Parser
9
+ def parse( line )
10
+ _, delay, host, size, method, uri, user = /\d+.\d+ +(\d+) +(\d+.\d+.\d+.\d+.\d+).+ (\d+) (.+) (.+) (.+) .+ .+/.match(line).to_a
11
+ if host
12
+ if method != 'ICP_QUERY'
13
+ size = size.to_f / 100000.0
14
+ #Uncomment if you authenticate to use the proxy
15
+ #add_activity(:block => 'users', :name => user, :size => size)
16
+ add_activity(:block => 'hosts', :name => host, :size => size)
17
+ add_activity(:block => 'types', :name => method, :size => size) if method
18
+ _, site = /http:\/\/(.+?)\/.+/.match(uri).to_a
19
+ if site:
20
+ add_activity(:block => 'sites', :name => site, :size => size)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # gl_tail.rb - OpenGL visualization of your server traffic
2
+ # Copyright 2007 Erlend Simonsen <mr@fudgie.org>
3
+ #
4
+ # Licensed under the GNU General Public License v2 (see LICENSE)
5
+ #
6
+
7
+ # Parser which handles tshark logs
8
+ class TSharkParser < Parser
9
+
10
+ def parse( line )
11
+ if(line.include?('->'))
12
+ time, srcip, arrow, destip, type, = line.split(" ")
13
+ add_activity(:block => 'users', :name => srcip)
14
+ add_activity(:block => 'types', :name => type)
15
+ end
16
+
17
+ if(line.include?('DNS Standard query A'))
18
+ foo, name = line.split(" A ")
19
+ if(name != nil)
20
+ add_event(:block => 'status', :name => "DNS Queries", :message => "DNS Request: " + name, :update_stats => true, :color => [1.5, 1.0, 0.5, 1.0])
21
+ end
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,69 @@
1
+ require 'resolv-replace'
2
+
3
+ class Resolver
4
+ include GlTail::Configurable
5
+
6
+ config_attribute :reverse_ip_lookups, "Lookup Hostnames"
7
+ config_attribute :reverse_timeout, "Wait how long for DNS reply [s]"
8
+
9
+ def self.instance
10
+ @@instance ||= Resolver.new
11
+ end
12
+
13
+ def initialize
14
+ @cache = { }
15
+ @thread = nil
16
+ @reverse_ip_lookups = true
17
+ @reverse_timeout = 1.5
18
+ @queue = Queue.new
19
+ end
20
+
21
+ attr_reader :queue, :cache
22
+
23
+ def start
24
+ @thread = Thread.new {
25
+ while @reverse_ip_lookups
26
+ ip, element = @queue.pop
27
+ if @cache.include? ip
28
+ element.name = @cache[ip]
29
+ else
30
+ begin
31
+ timeout(@reverse_timeout.to_f) {
32
+ puts "[Resolver] Looking for #{ip}" if $DBG > 0
33
+ hostname = Resolv.getname(ip)
34
+ puts "[Resolver] Got #{hostname}[#{ip}]" if $DBG > 0
35
+ @cache[ip] = hostname
36
+ element.name = hostname
37
+ }
38
+ rescue Timeout::Error
39
+ puts "[Resolver] Timeout!" if $DBG > 0
40
+ rescue Resolv::ResolvError
41
+ # No result, don't bother retrying
42
+ @cache[ip] = ip
43
+ end
44
+ end
45
+ end
46
+ }
47
+ end
48
+
49
+ def lookup(ip, element)
50
+ return ip if not @reverse_ip_lookups
51
+
52
+ if name = cache[ip]
53
+ return name
54
+ else
55
+ puts "[Resolver] Pushing #{ip} for lookup" if $DBG > 0
56
+ queue.push([ip, element])
57
+ end
58
+
59
+ return ip
60
+
61
+ end
62
+
63
+ def self.resolv(ip, element)
64
+ instance.lookup(ip, element)
65
+ end
66
+
67
+ end
68
+
69
+ Resolver.instance.start
@@ -0,0 +1,46 @@
1
+ # gl_tail.rb - OpenGL visualization of your server traffic
2
+ # Copyright 2007 Erlend Simonsen <mr@fudgie.org>
3
+ #
4
+ # Licensed under the GNU General Public License v2 (see LICENSE)
5
+ #
6
+
7
+ class Server
8
+ attr_reader :name, :host, :color, :parser
9
+
10
+
11
+ def initialize(options)
12
+ @name = options[:name] || options[:host]
13
+ @host = options[:host]
14
+ @color = options[:color] || [1.0, 1.0, 1.0, 1.0]
15
+ @parser = Parser.registry[ options[:parser] ] || Parser.registry[ :apache ]
16
+ @blocks = options[:blocks]
17
+ @max_size = 1.0
18
+
19
+ # instantiate the parser
20
+ @parser = @parser.new( self )
21
+
22
+ end
23
+
24
+ #block, message, size
25
+ def add_activity(options = { })
26
+ size = $CONFIG.min_blob_size
27
+ if options[:size]
28
+ size = options[:size].to_f
29
+ @max_size = size if size > @max_size
30
+ size = $CONFIG.min_blob_size + ((size / @max_size) * ($CONFIG.max_blob_size - $CONFIG.min_blob_size))
31
+ options[:size] = size
32
+ end
33
+
34
+ block = @blocks[options[:block]].add_activity( { :name => @name, :color => @color, :size => $CONFIG.min_blob_size }.update(options) ) if (options[:block] && @blocks[options[:block]])
35
+ end
36
+
37
+ #block, message
38
+ def add_event(options = { })
39
+ block = @blocks[options[:block]].add_event( { :name => @name, :color => @color, :size => $CONFIG.min_blob_size}.update(options) ) if (options[:block] && @blocks[options[:block]])
40
+ end
41
+
42
+ def update
43
+ @max_size = @max_size * 0.99 if(@max_size * 0.99 > 1.0)
44
+ end
45
+
46
+ end