broccoli 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +21 -0
- data/README +44 -0
- data/examples/broconn.bro +26 -0
- data/examples/broconn.rb +47 -0
- data/examples/broenum.rb +122 -0
- data/examples/brohose.bro +30 -0
- data/examples/brohose.rb +169 -0
- data/examples/broping-record.bro +56 -0
- data/examples/broping.bro +37 -0
- data/examples/broping.rb +148 -0
- data/examples/dns_requests.rb +35 -0
- data/ext/broccoli/autogen.sh +3 -0
- data/ext/broccoli/broccoli.i +507 -0
- data/ext/broccoli/broccoli_wrap.c +6125 -0
- data/ext/broccoli/extconf.rb +16 -0
- data/ext/broccoli/post-clean.rb +3 -0
- data/ext/broccoli/pre-config.rb +5 -0
- data/ext/broccoli/test/broconftest.rb +12 -0
- data/ext/broccoli/test/test.rb +174 -0
- data/lib/Bro/connection.rb +78 -0
- data/lib/Bro/event.rb +34 -0
- data/lib/Bro/record.rb +71 -0
- data/lib/bro.rb +87 -0
- data/setup.rb +1585 -0
- metadata +66 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2007 Seth Hall
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
rBroccoli is an interface for the Bro-IDS Broccoli library.
|
2
|
+
|
3
|
+
URL: http://rbroccoli.rubyforge.org
|
4
|
+
|
5
|
+
Author: Seth Hall <hall.692@osu.edu>
|
6
|
+
|
7
|
+
Version: 1.3.0
|
8
|
+
|
9
|
+
Date: 2007-08-03 23:16:50 EST
|
10
|
+
|
11
|
+
=About
|
12
|
+
This is the rBroccoli extension for ruby which provides access to the
|
13
|
+
Broccoli API. Broccoli is a library for communicating with the Bro Intrusion
|
14
|
+
Detection System. Broccoli is distributed with Bro now, so I'm going to be
|
15
|
+
releasing versions of rBroccoli that target Bro versions.
|
16
|
+
|
17
|
+
Bro IDS:: http://www.bro-ids.org
|
18
|
+
|
19
|
+
=Install
|
20
|
+
To install the extension
|
21
|
+
1. Make sure that the broccoli-config binary is in your path.
|
22
|
+
(export PATH=/usr/local/bro/bin:$PATH)
|
23
|
+
2. Run, "sudo ruby setup.rb"
|
24
|
+
|
25
|
+
To install the extension as a gem (<b>suggested</b>)
|
26
|
+
1. Install rubygems... http://rubygems.org/
|
27
|
+
2. Make sure that the broccoli-config binary is in your path.
|
28
|
+
(export PATH=/usr/local/bro/bin:$PATH)
|
29
|
+
3. Run, "sudo gem install rbroccoli"
|
30
|
+
|
31
|
+
=Usage
|
32
|
+
There aren't really any useful docs yet. Your best bet currently is
|
33
|
+
to to read through the examples.
|
34
|
+
|
35
|
+
One thing I should mention however is that I haven't done any optimization
|
36
|
+
yet. You may find that if you write code that is going to be sending or
|
37
|
+
receiving extremely large numbers of events, that it won't run fast enough and
|
38
|
+
will begin to fall behind the Bro server. The dns_requests.rb example is
|
39
|
+
a good performance test if your Bro server is sitting on a network with many
|
40
|
+
dns lookups.
|
41
|
+
|
42
|
+
=Contact
|
43
|
+
If you have a question/comment/patch, email me at:
|
44
|
+
hall.692@osu.edu
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Depending on whether you want to use encryption or not,
|
2
|
+
# include "listen-clear" or "listen-ssl":
|
3
|
+
#
|
4
|
+
# @load listen-ssl
|
5
|
+
@load listen-clear
|
6
|
+
@load conn
|
7
|
+
|
8
|
+
# Let's make sure we use the same port no matter whether we use encryption or not:
|
9
|
+
#
|
10
|
+
@ifdef (listen_port_clear)
|
11
|
+
redef listen_port_clear = 47758/tcp;
|
12
|
+
@endif
|
13
|
+
|
14
|
+
# If we're using encrypted communication, redef the SSL port and hook in
|
15
|
+
# the necessary certificates:
|
16
|
+
#
|
17
|
+
@ifdef (listen_port_ssl)
|
18
|
+
redef listen_port_ssl = 47758/tcp;
|
19
|
+
redef ssl_ca_certificate = "<path>/ca_cert.pem";
|
20
|
+
redef ssl_private_key = "<path>/bro.pem";
|
21
|
+
@endif
|
22
|
+
|
23
|
+
redef Remote::destinations += {
|
24
|
+
["broconn"] = [$host = 127.0.0.1, $connect=F, $ssl=F]
|
25
|
+
};
|
26
|
+
|
data/examples/broconn.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'bro' # If installed as a native extension
|
5
|
+
rescue LoadError
|
6
|
+
require 'rubygems' # If install as a gem
|
7
|
+
gem 'broccoli'
|
8
|
+
require 'bro'
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'ipaddr'
|
12
|
+
include Bro
|
13
|
+
|
14
|
+
Bro.debug_calltrace=false
|
15
|
+
Bro.debug_messages=false
|
16
|
+
|
17
|
+
SRC_STR = "%s/%s [%u/%u] -> "
|
18
|
+
DST_STR = "%s/%s [%u/%u], "
|
19
|
+
METADATA_STR = "%s start: %f, duration: %f, addl: '%s'\n"
|
20
|
+
|
21
|
+
def generic_conn(conn)
|
22
|
+
begin
|
23
|
+
ip = IPAddr.ntop(conn.id.orig_h).to_s
|
24
|
+
printf SRC_STR, ip, conn.id.orig_p, conn.orig.size, conn.orig.state
|
25
|
+
ip = IPAddr.ntop(conn.id.resp_h).to_s
|
26
|
+
printf DST_STR, ip, conn.id.resp_p, conn.resp.size, conn.resp.state
|
27
|
+
printf METADATA_STR, conn.service, conn.start_time, conn.duration, conn.addl
|
28
|
+
rescue
|
29
|
+
# For some reason, occasionally the IPAddr class doesn't like the
|
30
|
+
# network byte ordered strings that it receives.
|
31
|
+
puts "oops - this seems to be a bug :)"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
bc = Bro::Connection.new("127.0.0.1:47758", BRO_CFLAG_RECONNECT)
|
36
|
+
|
37
|
+
bc.event_handler_for("connection_attempt") { |conn| print "connection_attempt: "; generic_conn(conn) }
|
38
|
+
bc.event_handler_for("connection_established") { |conn| print "connection_established: "; generic_conn(conn) }
|
39
|
+
bc.event_handler_for("connection_finished") { |conn| print "connection_finished: "; generic_conn(conn) }
|
40
|
+
bc.event_handler_for("connection_rejected") { |conn| print "connection_rejected: "; generic_conn(conn) }
|
41
|
+
|
42
|
+
if bc.connect
|
43
|
+
puts "connected"
|
44
|
+
while bc.wait
|
45
|
+
bc.process_input
|
46
|
+
end
|
47
|
+
end
|
data/examples/broenum.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'bro' # If installed as a native extension
|
5
|
+
rescue LoadError
|
6
|
+
require 'rubygems' # If install as a gem
|
7
|
+
gem 'broccoli'
|
8
|
+
require 'bro'
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'logger'
|
12
|
+
require 'optparse'
|
13
|
+
require 'ostruct'
|
14
|
+
require 'ipaddr'
|
15
|
+
|
16
|
+
class BroenumApp < Logger::Application
|
17
|
+
include Bro
|
18
|
+
|
19
|
+
def run
|
20
|
+
opt = parse_opts()
|
21
|
+
|
22
|
+
# Set debugging vars
|
23
|
+
Bro.debug_messages=true if opt.debug > 0
|
24
|
+
Bro.debug_calltrace=true if opt.debug > 1
|
25
|
+
|
26
|
+
# Create the connection object
|
27
|
+
bc = Bro::Connection.new("#{opt.host}:#{opt.port}", BRO_CFLAG_NONE)
|
28
|
+
|
29
|
+
if bc.connect
|
30
|
+
#puts "connected"
|
31
|
+
ev = Bro::Event.new("enumtest")
|
32
|
+
ev.insert(opt.num, :enum, opt.type_name)
|
33
|
+
puts "Sending enum val #{opt.num} to remote peer."
|
34
|
+
bc.send(ev)
|
35
|
+
|
36
|
+
# Make sure the event isn't still queued
|
37
|
+
while bc.queue_length > 0
|
38
|
+
bc.queue_flush
|
39
|
+
end
|
40
|
+
|
41
|
+
bc.disconnect
|
42
|
+
else
|
43
|
+
puts "Couldn't connect to Bro server at #{opt.host}:#{opt.port}."
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def initialize
|
51
|
+
super('app')
|
52
|
+
STDERR.sync = true
|
53
|
+
self.level = Logger::FATAL
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse_opts
|
57
|
+
options = OpenStruct.new
|
58
|
+
options.debug = 0
|
59
|
+
options.host = "127.0.0.1"
|
60
|
+
options.port = 47758
|
61
|
+
options.type_name = "enumtest::enumtype"
|
62
|
+
options.num = 0
|
63
|
+
|
64
|
+
opts = OptionParser.new do |opts|
|
65
|
+
opts.banner = "broenum - sends enum vals to a Bro node, printing the corresponding
|
66
|
+
string value on the Bro side.
|
67
|
+
USAGE: #{$0} [-h] [-d] [-p port] [-t type] [-n num] host"
|
68
|
+
|
69
|
+
opts.separator ""
|
70
|
+
opts.separator "Specific options:"
|
71
|
+
|
72
|
+
opts.on('-p', '--port PORT',
|
73
|
+
'The port your bro agent is listening on') do |port|
|
74
|
+
options.port = port.to_i
|
75
|
+
end
|
76
|
+
|
77
|
+
opts.on('-n', '--num NUM',
|
78
|
+
'The enum value') do |n|
|
79
|
+
options.num = n.to_i
|
80
|
+
end
|
81
|
+
|
82
|
+
opts.on('-t', '--type TYPE',
|
83
|
+
'The enum type') do |t|
|
84
|
+
options.type_name = t
|
85
|
+
end
|
86
|
+
|
87
|
+
opts.separator ""
|
88
|
+
opts.separator "Common options:"
|
89
|
+
|
90
|
+
# No argument, shows at tail. This will print an options summary.
|
91
|
+
# Try it and see!
|
92
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
93
|
+
puts opts
|
94
|
+
exit
|
95
|
+
end
|
96
|
+
|
97
|
+
opts.on_tail('-d', '--debug',
|
98
|
+
'Use this option once for debug messages and twice for calltraces') do
|
99
|
+
options.debug += 1
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
begin
|
105
|
+
opts.parse!(ARGV)
|
106
|
+
raise(OptionParser::InvalidOption, "missing host") unless ARGV[0]
|
107
|
+
options.host = ARGV[0]
|
108
|
+
rescue OptionParser::InvalidOption => e
|
109
|
+
puts "Invalid option! (#{e})"
|
110
|
+
puts opts
|
111
|
+
exit -1
|
112
|
+
end
|
113
|
+
options
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
begin
|
119
|
+
BroenumApp.new.start
|
120
|
+
rescue Interrupt => e
|
121
|
+
# Catch interrupts quietly
|
122
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Depending on whether you want to use encryption or not,
|
2
|
+
# include "listen-clear" or "listen-ssl":
|
3
|
+
#
|
4
|
+
# @load listen-ssl
|
5
|
+
@load listen-clear
|
6
|
+
|
7
|
+
global brohose_log = open_log_file("brohose");
|
8
|
+
|
9
|
+
# Let's make sure we use the same port no matter whether we use encryption or not:
|
10
|
+
#
|
11
|
+
@ifdef (listen_port_clear)
|
12
|
+
redef listen_port_clear = 47758/tcp;
|
13
|
+
@endif
|
14
|
+
|
15
|
+
# If we're using encrypted communication, redef the SSL port and hook in
|
16
|
+
# the necessary certificates:
|
17
|
+
#
|
18
|
+
@ifdef (listen_port_ssl)
|
19
|
+
redef listen_port_ssl = 47758/tcp;
|
20
|
+
redef ssl_ca_certificate = "<path>/ca_cert.pem";
|
21
|
+
redef ssl_private_key = "<path>/bro.pem";
|
22
|
+
@endif
|
23
|
+
|
24
|
+
redef Remote::destinations += {
|
25
|
+
["brohose"] = [$host = 127.0.0.1, $events = /brohose/, $connect=F, $ssl=F]
|
26
|
+
};
|
27
|
+
|
28
|
+
event brohose(id: string) {
|
29
|
+
print brohose_log, fmt("%s %s", id, current_time());
|
30
|
+
}
|
data/examples/brohose.rb
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'bro' # If installed as a native extension
|
5
|
+
rescue LoadError
|
6
|
+
require 'rubygems' # If install as a gem
|
7
|
+
gem 'broccoli'
|
8
|
+
require 'bro'
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'logger'
|
12
|
+
require 'optparse'
|
13
|
+
require 'ostruct'
|
14
|
+
require 'ipaddr'
|
15
|
+
|
16
|
+
class BrohoseApp < Logger::Application
|
17
|
+
include Bro
|
18
|
+
|
19
|
+
def run
|
20
|
+
opt = parse_opts()
|
21
|
+
|
22
|
+
# Set debugging vars
|
23
|
+
Bro.debug_messages=true if opt.debug > 0
|
24
|
+
Bro.debug_calltrace=true if opt.debug > 1
|
25
|
+
|
26
|
+
printf("Will attempt to send %i events from %i processes, to %s\n",
|
27
|
+
opt.events, opt.processes, opt.host)
|
28
|
+
puts "enter to continue"
|
29
|
+
STDIN.gets
|
30
|
+
|
31
|
+
# Create the connection object
|
32
|
+
bc = Bro::Connection.new("#{opt.host}:#{opt.port}", BRO_CFLAG_SHAREABLE)
|
33
|
+
|
34
|
+
if bc.connect
|
35
|
+
#puts "connected"
|
36
|
+
|
37
|
+
(1..opt.processes).each do
|
38
|
+
@pid = fork()
|
39
|
+
|
40
|
+
if @pid.nil?
|
41
|
+
hose_away(bc, opt.events)
|
42
|
+
exit 0
|
43
|
+
end
|
44
|
+
|
45
|
+
if @pid < 0
|
46
|
+
puts "Unable to fork children, aborting."
|
47
|
+
exit -1
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
Process.wait
|
53
|
+
puts "All children finished... done."
|
54
|
+
exit 0
|
55
|
+
|
56
|
+
else
|
57
|
+
puts "Couldn't connect to Bro at #{opt.host}:#{opt.port}."
|
58
|
+
exit -1
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def initialize
|
66
|
+
super('app')
|
67
|
+
STDERR.sync = true
|
68
|
+
self.level = Logger::FATAL
|
69
|
+
|
70
|
+
@pid = 0
|
71
|
+
end
|
72
|
+
|
73
|
+
def hose_away(bc, events)
|
74
|
+
(1..events).each do |i|
|
75
|
+
ev = Bro::Event.new("brohose")
|
76
|
+
msg = sprintf("%u-%i-%i", @pid, i, bc.queue_length)
|
77
|
+
ev.insert(msg, :string)
|
78
|
+
bc.send(ev)
|
79
|
+
|
80
|
+
if (bc.queue_length > bc.queue_length_max/2)
|
81
|
+
while bc.queue_length > 0
|
82
|
+
bc.queue_flush
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
while bc.queue_length > 0
|
89
|
+
bc.queue_flush
|
90
|
+
end
|
91
|
+
|
92
|
+
printf("-- child %u, %i queued\n", @pid, bc.queue_length)
|
93
|
+
bc.disconnect
|
94
|
+
end
|
95
|
+
|
96
|
+
def parse_opts
|
97
|
+
options = OpenStruct.new
|
98
|
+
options.debug = 0
|
99
|
+
options.port = 47758
|
100
|
+
options.processes = 10
|
101
|
+
options.events = 1000
|
102
|
+
|
103
|
+
opts = OptionParser.new do |opts|
|
104
|
+
opts.banner = "brohose - Try to hose bro with data.\nUsage: #{$0} [options] host"
|
105
|
+
|
106
|
+
opts.separator ""
|
107
|
+
opts.separator "Specific options:"
|
108
|
+
|
109
|
+
opts.on('-p', '--port PORT',
|
110
|
+
'The port your bro agent is listening on') do |port|
|
111
|
+
options.port = port
|
112
|
+
end
|
113
|
+
|
114
|
+
opts.on('-n', '--number NUMBER',
|
115
|
+
'Number of processes to use (10)') do |n|
|
116
|
+
n = n.to_i
|
117
|
+
if n < 1 or n > 100
|
118
|
+
puts "Please restrict the number of processes to 1-100."
|
119
|
+
exit -1
|
120
|
+
end
|
121
|
+
options.processes = n
|
122
|
+
end
|
123
|
+
|
124
|
+
opts.on('-e', '--events EVENTS',
|
125
|
+
'Number of events per process (1000)') do |e|
|
126
|
+
e = e.to_i
|
127
|
+
if e < 1 or e > 10000
|
128
|
+
puts "Please restrict the number of events to 1-10,000."
|
129
|
+
exit -1
|
130
|
+
end
|
131
|
+
options.events = e
|
132
|
+
end
|
133
|
+
|
134
|
+
opts.separator ""
|
135
|
+
opts.separator "Common options:"
|
136
|
+
|
137
|
+
# No argument, shows at tail. This will print an options summary.
|
138
|
+
# Try it and see!
|
139
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
140
|
+
puts opts
|
141
|
+
exit
|
142
|
+
end
|
143
|
+
|
144
|
+
opts.on_tail('-d', '--debug',
|
145
|
+
'Use this option once for debug messages and twice for calltraces') do
|
146
|
+
options.debug += 1
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
begin
|
152
|
+
opts.parse!(ARGV)
|
153
|
+
raise(OptionParser::InvalidOption, "missing host") unless ARGV[0]
|
154
|
+
options.host = ARGV[0]
|
155
|
+
rescue OptionParser::InvalidOption => e
|
156
|
+
puts "Invalid option! (#{e})"
|
157
|
+
puts opts
|
158
|
+
exit
|
159
|
+
end
|
160
|
+
options
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
begin
|
166
|
+
BrohoseApp.new.start
|
167
|
+
rescue Interrupt => e
|
168
|
+
# Catch interrupts quietly
|
169
|
+
end
|