packet_genie 1.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7bcdf7dc08b4aff6aafbcf00d906c90a16e1f6cf
4
+ data.tar.gz: 5aa8b5e59b850fa16e793f2c9b04484d74e61761
5
+ SHA512:
6
+ metadata.gz: a523b589075c6e0b42973b1b762c0bdbc49a9cd52f4c6a46302496df0edc723a21533a9a192abdcddfc6dbbea0d25dad36e12280d9ea628754129d66d84b0137
7
+ data.tar.gz: e7c7898102c43900bb894681a4237581ab6fc4e9224a5a107a1189b2c935b9cd95007bb0282d6f21242e4fc7d049f2761f3e0436342d5d1cbfe2332f5b7ec9ae
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.0
5
+ before_install: gem install bundler -v 1.14.6
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at kgruber1@emich.edu. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in packet_genie.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Kent Gruber
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,55 @@
1
+ ![Genie Lamp](https://i.imgur.com/jtBKrjU.png)
2
+
3
+ # Packet Genie
4
+
5
+ Packet Genie is a simple packet capturing solution that implements a streaming REST API to orchestrate packet captures in a magical way.
6
+
7
+ ## Why?
8
+
9
+ Have you ever wanted to stream live packet captures on multiple hosts? Ever just wanted to do that over HTTP(s) with a REST API to make it easy to do?
10
+
11
+ ### 🚧 Development Notice
12
+
13
+ Currently, a pre-release gem is avaiable to install with the --pre flag to help with early testing.
14
+
15
+ ## Installation
16
+
17
+ $ gem install packet_genie --pre
18
+
19
+ ## Usage
20
+
21
+ ### Server
22
+
23
+ The Packet Genie server will stream packets on the host running the Packet Genie server. This allows you to perform a live, remote packet capture over HTTP(s).
24
+
25
+ ```ruby
26
+ require 'packet_genie'
27
+
28
+ # Start server without SSL
29
+ PacketGenie.server.run!(ssl: false)
30
+ ```
31
+
32
+ Then, easily start a packet capture with CURL ( for example ):
33
+
34
+ ```shell
35
+ $ curl localhost:4567/packets
36
+ ```
37
+
38
+ ### Client
39
+
40
+ Don't want to mess around with CURL? Why not use the Packet Genie client?
41
+
42
+ ```ruby
43
+ require 'packet_genie'
44
+
45
+ client = PacketGenie.client.new(uri: "http://localhost:4567")
46
+
47
+ client.packets do |packet|
48
+ puts packet # do something with json
49
+ end
50
+ ```
51
+
52
+ ## License
53
+
54
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
55
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/lamp ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'packet_genie'
4
+ require 'colorize'
5
+ require 'pry'
6
+
7
+ prompt_name = "magic lamp ".bold + ">>".red
8
+
9
+ Pry.config.prompt = [
10
+ proc { |target_self, nest_level, pry|
11
+ "#{prompt_name}#{":#{nest_level}" unless nest_level.zero?} "
12
+ },
13
+ proc { |target_self, nest_level, pry|
14
+ "#{prompt_name}(#{Pry.view_clip(target_self)})#{":#{nest_level}" unless nest_level.zero?}* "
15
+ }
16
+ ]
17
+ Pry.config.prompt_name = prompt_name
18
+
19
+ Pry.start
data/bin/pg-client ADDED
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'packet_genie'
4
+ require 'colorize'
5
+ require 'trollop'
6
+
7
+ application_name = 'Packet Genine Client'
8
+
9
+ # Default to a help menu if no argument is given.
10
+ ARGV[0] = '-h' if ARGV.empty?
11
+
12
+ # Option parsing.
13
+ opts = Trollop::options do
14
+ banner "#{application_name}".red
15
+ version "#{application_name} CLI 1.0.0 (c) 2017 Kent 'picat' Gruber"
16
+ opt :ip, "Packet Genie server IP", type: :string, default: "localhost"
17
+ opt :port, "port to connect on", type: :int, default: 4567
18
+ opt :ssl, "enable SSL support", type: :bool, default: false
19
+ opt :check, "check connection", type: :bool, default: false
20
+ opt :Config, "check configuration", type: :bool, default: false
21
+ opt :Interface, "change interface", type: :string
22
+ opt :Snaplen, "change snaplen", type: :int
23
+ opt :Promisc, "promisc mode", type: :boolean, default: false
24
+ opt :Timeout, "timeout value", type: :int
25
+ opt :run, "start packet capture", type: :boolean, default: false
26
+ opt :Verbose, "verbose output option", type: :bool, default: false
27
+ end
28
+
29
+ base = if opts[:ssl]
30
+ "https://"
31
+ else
32
+ "http://"
33
+ end
34
+
35
+ client = PacketGenie.client.new(uri: "#{base}#{opts[:ip]}:#{opts[:port]}")
36
+
37
+ if opts[:check]
38
+ begin
39
+ puts "[#{"+".green}] Able to connect to: #{client.uri}" if client.config
40
+ rescue
41
+ puts "[#{"-".red}] Unable to connect to: #{client.uri}"
42
+ end
43
+ end
44
+
45
+ if opts[:Config]
46
+ begin
47
+ client.config.each do |key, value|
48
+ puts "#{key.rjust(9)}: #{value}"
49
+ end
50
+ rescue
51
+ puts "[#{"-".red}] Unable to connect to: #{client.uri}"
52
+ end
53
+ end
54
+
55
+ if opts[:Interface] || opts[:Snaplen] || opts[:Timeout] || opts[:Promisc]
56
+ config = {}
57
+ [:Interface, :Snaplen, :Timeout, :Promisc].each do |option|
58
+ config[option.to_s.downcase.to_sym] = opts[option] if opts[option]
59
+ end
60
+ resp = client.set_config(config: config)
61
+ resp.each do |key, value|
62
+ puts "#{key.rjust(9)}: #{value}"
63
+ end
64
+ end
65
+
66
+ if opts[:run]
67
+ client.packets do |packet|
68
+ puts packet
69
+ end
70
+ end
data/bin/pg-server ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'packet_genie'
4
+ require 'colorize'
5
+ require 'trollop'
6
+
7
+ application_name = 'Packet Genine Server'
8
+
9
+ # Default to a help menu if no argument is given.
10
+ ARGV[0] = '-h' if ARGV.empty?
11
+
12
+ # Option parsing.
13
+ opts = Trollop::options do
14
+ banner "#{application_name}".red
15
+ version "#{application_name} CLI 1.0.0 (c) 2017 Kent 'picat' Gruber"
16
+ opt :ip, "IP address to bind to", type: :string, default: "localhost"
17
+ opt :port, "port to listen on", type: :int, default: 4567
18
+ opt :ssl, "enable SSL support", type: :bool, default: false
19
+ opt :cert, "SSL cert chain file", type: :string
20
+ opt :key, "SSL private key file", type: :string
21
+ opt :Verbose, "verbose output option", type: :bool, default: false
22
+ opt :run, "start the server", type: :bool, default: false
23
+ end
24
+
25
+ if opts[:ssl] and opts[:run]
26
+ [:cert, :key].each do |option|
27
+ raise "Unable to read file for #{option}: #{opts[option]}" unless File.readable?(opts[option])
28
+ end
29
+ PacketGenie.server.run!(bind: opts[:ip], port: opts[:port], cert_chain: opts[:cert], private_key: opts[:key])
30
+ elsif opts[:run]
31
+ PacketGenie.server.run!(bind: opts[:ip], port: opts[:port], ssl: false)
32
+ end
@@ -0,0 +1,7 @@
1
+ $: << File.expand_path("../../../lib", __FILE__)
2
+ require "packet_genie"
3
+
4
+ client = PacketGenie.client.new(uri: "http://localhost:4567")
5
+ client.packets do |packet|
6
+ puts packet # do something with packet json
7
+ end
@@ -0,0 +1,4 @@
1
+ $: << File.expand_path("../../../lib", __FILE__)
2
+ require "packet_genie"
3
+
4
+ PacketGenie.server.run!(ssl: false)
@@ -0,0 +1,5 @@
1
+ $: << File.expand_path("../../../lib", __FILE__)
2
+ require "packet_genie"
3
+
4
+ PacketGenie.server.run!(cert_chain: "./examples/server/legit.cert.pem",
5
+ private_key: "./examples/server/legit.key.pem")
@@ -0,0 +1,27 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEpzCCA4+gAwIBAgIJAKF4JXdzBZvIMA0GCSqGSIb3DQEBCwUAMIGTMQswCQYD
3
+ VQQGEwJNSTERMA8GA1UECBMITWljaGlnYW4xEjAQBgNVBAcTCVlwc2lsYW50aTEr
4
+ MCkGA1UEChMiU3VwZXIgVHJ1c3R3b3J0aHkgU2VjdXJpdHkgQ29tcGFueTEMMAoG
5
+ A1UECxMDTG9sMQ4wDAYDVQQDEwU0Y2hhbjESMBAGCSqGSIb3DQEJARYDbWVoMB4X
6
+ DTE2MTAwNDAxMTYwN1oXDTE3MTAwNDAxMTYwN1owgZMxCzAJBgNVBAYTAk1JMREw
7
+ DwYDVQQIEwhNaWNoaWdhbjESMBAGA1UEBxMJWXBzaWxhbnRpMSswKQYDVQQKEyJT
8
+ dXBlciBUcnVzdHdvcnRoeSBTZWN1cml0eSBDb21wYW55MQwwCgYDVQQLEwNMb2wx
9
+ DjAMBgNVBAMTBTRjaGFuMRIwEAYJKoZIhvcNAQkBFgNtZWgwggEiMA0GCSqGSIb3
10
+ DQEBAQUAA4IBDwAwggEKAoIBAQDCr4XSfYlSxdi/OklR8R3qKTEo7CFeqgqoGpdq
11
+ fb2jn4KACaLZU8m2kfBSYX+ukfQX0wT4j4yBvAc3uvRJGwFRDqIiNvS+ZEU//fVU
12
+ XhtZpPo3P90MazCTWcGbslmisVVPhEhGrE8VoqgsIoqp3Es6uNPVuG1qJ9vjQ6PS
13
+ f8vyTfEt+LLbRUEFDOsfjtLxuVc13wjdIUi2GruZyFZUC6q1RIyebNwNy4vAqUpa
14
+ oBHvekKcFQaKyMmDsH7UB1uoTCeMvT3n472jQcqWvsO+cohsjPlqTuASwI3BpXF5
15
+ q6tbJkhj8VgnNkyIUVlilitJxrjor6gsl1TN8lsoQiQj2lurAgMBAAGjgfswgfgw
16
+ HQYDVR0OBBYEFBB+RqdnyCO5iOOMpQ99GODiEPaEMIHIBgNVHSMEgcAwgb2AFBB+
17
+ RqdnyCO5iOOMpQ99GODiEPaEoYGZpIGWMIGTMQswCQYDVQQGEwJNSTERMA8GA1UE
18
+ CBMITWljaGlnYW4xEjAQBgNVBAcTCVlwc2lsYW50aTErMCkGA1UEChMiU3VwZXIg
19
+ VHJ1c3R3b3J0aHkgU2VjdXJpdHkgQ29tcGFueTEMMAoGA1UECxMDTG9sMQ4wDAYD
20
+ VQQDEwU0Y2hhbjESMBAGCSqGSIb3DQEJARYDbWVoggkAoXgld3MFm8gwDAYDVR0T
21
+ BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEApmM8a+7y8X51XJmSyyVzNfA7k1We
22
+ UJLMHhZfxOAK1inQNoyVjZhbkEsOjOrWz3PAxyrw7qpMBQuQ7ioNdvF/eTZHQQEj
23
+ hImSHbF/OV/bfhqnwO8RSVGP3TXr4QH/DvjJr8VdBTg7XTGIFHNLGkNTwPrcvWTV
24
+ 4BGN7Y3T+6LjfESmGWwLAFZ06uGc0xbsgI6N+UnTuNv3BWsx7I1nbTpVLqyH2Bfq
25
+ oTXnDMJCsv4LL/3iLAJFCC9S62KObAN1rwNH37kPXt6lxB0bnWTvWbMJoRWMuKrL
26
+ yXbgVZIoUj57g0hEo9Js6EuYLlu/O6NyUYK/AYNHuW443jkrYRSR5xF+LQ==
27
+ -----END CERTIFICATE-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEowIBAAKCAQEAwq+F0n2JUsXYvzpJUfEd6ikxKOwhXqoKqBqXan29o5+CgAmi
3
+ 2VPJtpHwUmF/rpH0F9ME+I+MgbwHN7r0SRsBUQ6iIjb0vmRFP/31VF4bWaT6Nz/d
4
+ DGswk1nBm7JZorFVT4RIRqxPFaKoLCKKqdxLOrjT1bhtaifb40Oj0n/L8k3xLfiy
5
+ 20VBBQzrH47S8blXNd8I3SFIthq7mchWVAuqtUSMnmzcDcuLwKlKWqAR73pCnBUG
6
+ isjJg7B+1AdbqEwnjL095+O9o0HKlr7DvnKIbIz5ak7gEsCNwaVxeaurWyZIY/FY
7
+ JzZMiFFZYpYrSca46K+oLJdUzfJbKEIkI9pbqwIDAQABAoIBAGzxDWCBMRPpdGVl
8
+ t1usIkJDNKgionW3j2kMIEjN/g2Ol9cQDVmxokGQnrtqpalJMR8XzUNOCKEcV6me
9
+ 603xV6ZFGwMsX34e3AV4Fg1U79cVE5NRIF/vp2n9IvL+NVxuAUAS1OL/Tu3bbGHu
10
+ Hkv44vwEKz4ACvIJRemBky2ap8R5UNhy53Yxu2GCBXT3hVFt8qpjbmV12LtgLcSu
11
+ 3PjjidNFwE/Y4cR0aR76LZ4rnhz7W38hx1D6XhdTvtOe5LOMt5LhiUfPq6Sr7ewr
12
+ 5JFHx1w+OlGG6K2hooDu1/6UwQpSp2mpU0u3k3hrMmmWl58RPhkRN1DcaYCpSk9h
13
+ 73Q+MhECgYEA6zIYYIcuzsM4zjaCgoIAbQXcNPsFabENVBe3z6QLfQXG8WSSgGBs
14
+ /LBWSc+58qEHT1TLNwrOKoR0LeNwH2C7HK7WJNTchUXTdz0Dz43IvgJABsb2lOFi
15
+ rincXRP2IIwzsKgVnKjVu4FK+yOrL3iT/cUSI/+rbS7OoC4JXOjAuckCgYEA0+gY
16
+ ToX6DVnIgSGOargBNJIS8okuYBxTi2V3seuQDQZIl2yitFJZEWyLAqmJAYQXfKrf
17
+ L3++bUFba7Nvga1+mxUDjojgEBBBnFFyEjScon4yvRk2AObBdwFiwFrQbV0WyDR6
18
+ aLQLiMweKMTQILZLvAJw9NXFPJM+/Wg/nQgk49MCgYBDDy+AJkskTOlfco9XorV4
19
+ YFlfCcuLTR4dwf14yK814HXO0fwrelLY4XZY6U99bIhnCChA82XBHa76foSzjaMM
20
+ FJWePsr5fOVEdDMn9Kct9fpHdGdOH81BF1Jrf4uH0DHUxrgSyNjX849rd8oRaPHZ
21
+ Q11ewkEgil4DsdydjweUcQKBgFTalJkk9wtPj4V97Wx4gCsP7zxliEd+MEoaeIKr
22
+ ZESC5qCUJNb2PqpGf6eyQaV0wn7uYW7AxX00dao78QPJeHAbSxBRaP+lstAooPf/
23
+ T1WWGTU1mjVkMcY4rNV/yARzCUNkGDxDFHdT3SPQI9NljBAeHiM8Ur297LRGgWqd
24
+ L0B3AoGBAONCEBHBFiT1YySN6MheqG8Zdd8OEoDSJIRK4zMKckbAWdo3UNiW+Mvt
25
+ f2raviQt3nXl7YpAZBDcQk76JrvFyupgGMBJzLQNe1J7MlZ67A4Stg3g7fpXXY4c
26
+ Ec70JoSTpW4+h4qrOAD8lKUS3v4hL1oIGzIL1hvv4fuvFWDiS2zX
27
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,78 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'json'
4
+ require 'base64'
5
+
6
+ module PacketGenie
7
+
8
+ class Client
9
+ CONFIG = "/config"
10
+ PACKETS = "/packets"
11
+
12
+ attr_accessor :uri, :options, :response
13
+
14
+ def initialize(uri:, options: false)
15
+ @uri = URI.parse(uri)
16
+ @options = if options
17
+ options
18
+ else
19
+ { use_ssl: @uri.scheme == "https" }
20
+ end
21
+ end
22
+
23
+ def config(parsed: true)
24
+ @response = Net::HTTP.get_response(uri + "/config")
25
+ if parsed
26
+ JSON.parse(@response.body)
27
+ else
28
+ @response
29
+ end
30
+ end
31
+
32
+ def set_config(config:, parsed: true)
33
+ old_path = @uri.path
34
+ @uri.path = CONFIG
35
+ @request = Net::HTTP::Post.new(@uri)
36
+ @request.body = JSON.dump(config)
37
+ @response = Net::HTTP.start(@uri.hostname, @uri.port, @options) { |http| http.request(@request) }
38
+ if parsed
39
+ JSON.parse(@response.body)
40
+ else
41
+ @response
42
+ end
43
+ end
44
+
45
+ def send_request(path:, request: @request)
46
+ old_path = @uri.path
47
+ @uri.path = path
48
+ Net::HTTP.start(@uri.hostname, @uri.port, @options) { |http| http.request(request) }
49
+ @uri.path = old_path
50
+ end
51
+
52
+ def response?
53
+ !!@response
54
+ end
55
+
56
+ def packets
57
+ old_path = @uri.path
58
+ @uri.path = "/packets"
59
+ @request = Net::HTTP::Get.new(@uri)
60
+ begin
61
+ Net::HTTP.start(@uri.hostname, @uri.port, @options) do |http|
62
+ http.request(@request) do |resp|
63
+ resp.read_body do |chunk|
64
+ chunk.split.each do |packet|
65
+ yield packet
66
+ end
67
+ end
68
+ end
69
+ end
70
+ ensure
71
+ @uri.path = old_path
72
+ true
73
+ end
74
+ end
75
+
76
+ end
77
+
78
+ end
@@ -0,0 +1,75 @@
1
+ require 'sinatra/base'
2
+ require 'pcaprub'
3
+ require 'base64'
4
+ require 'json'
5
+ require 'pry'
6
+
7
+ module PacketGenie
8
+
9
+ class Server < Sinatra::Base
10
+
11
+ def jsonify(mesg)
12
+ mesg.to_json + "\n"
13
+ end
14
+
15
+ def read_json(body)
16
+ JSON.parse(body)
17
+ rescue # don't tell me what to do
18
+ false
19
+ end
20
+
21
+ before do
22
+ content_type :json
23
+ end
24
+
25
+ set :config, { "interface": Pcap.lookupdev,
26
+ "snaplen": 65535,
27
+ "promisc": true,
28
+ "timeout": 0 }
29
+
30
+ get '/config' do
31
+ jsonify(settings.config)
32
+ end
33
+
34
+ post '/config' do
35
+ halt 400 unless body = read_json(request.body.read)
36
+ ["interface", "snaplen", "promisc", "timeout"].each do |opt|
37
+ settings.config[opt.to_sym] = body[opt] if body.keys.include?(opt)
38
+ end
39
+ jsonify(settings.config)
40
+ end
41
+
42
+ get '/packets' do
43
+ cap = PCAPRUB::Pcap.open_live(*settings.config.values)
44
+ stream do |out|
45
+ while true
46
+ if pkt = cap.next
47
+ out << jsonify({ packet: Base64.encode64(pkt) })
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ def self.run!(bind: 'localhost', port: 4567, ssl: true, cert_chain: false, private_key: false, verify_peer: false)
54
+ set :bind, bind
55
+ set :port, port
56
+ if ssl
57
+ [ cert_chain, private_key ].each do |required_file|
58
+ raise "Required file #{required_file} is not a file!" unless File.exists?(required_file)
59
+ end
60
+ end
61
+ super do |server|
62
+ if ssl
63
+ server.ssl = true
64
+ server.ssl_options = {
65
+ :cert_chain_file => cert_chain,
66
+ :private_key_file => private_key,
67
+ :verify_peer => verify_peer
68
+ }
69
+ end
70
+ end
71
+ end
72
+
73
+ end
74
+
75
+ end
@@ -0,0 +1,3 @@
1
+ module PacketGenie
2
+ VERSION = "1.0.0.pre"
3
+ end
@@ -0,0 +1,15 @@
1
+ require "packet_genie/version"
2
+ require "packet_genie/client"
3
+ require "packet_genie/server"
4
+
5
+ module PacketGenie
6
+
7
+ def self.server
8
+ Server
9
+ end
10
+
11
+ def self.client
12
+ Client
13
+ end
14
+
15
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'packet_genie/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "packet_genie"
8
+ spec.version = PacketGenie::VERSION
9
+ spec.authors = ["Kent 'picat' Gruber"]
10
+ spec.email = ["kgruber1@emich.edu"]
11
+
12
+ spec.summary = %q{Magically streaming live packet captures with a simple REST API}
13
+ spec.homepage = "https://github.com/picatz/packet_genie"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "bin"
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'pcaprub'
22
+ spec.add_dependency 'sinatra'
23
+ spec.add_dependency 'pry'
24
+ spec.add_dependency 'colorize'
25
+ spec.add_dependency 'trollop'
26
+
27
+ spec.add_development_dependency "bundler", "~> 1.14"
28
+ spec.add_development_dependency "rake", "~> 10.0"
29
+ spec.add_development_dependency "rspec", "~> 3.0"
30
+ end
metadata ADDED
@@ -0,0 +1,180 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: packet_genie
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.pre
5
+ platform: ruby
6
+ authors:
7
+ - Kent 'picat' Gruber
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pcaprub
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sinatra
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: colorize
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: trollop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.14'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.14'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '10.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '10.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '3.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '3.0'
125
+ description:
126
+ email:
127
+ - kgruber1@emich.edu
128
+ executables:
129
+ - lamp
130
+ - pg-client
131
+ - pg-server
132
+ extensions: []
133
+ extra_rdoc_files: []
134
+ files:
135
+ - ".gitignore"
136
+ - ".rspec"
137
+ - ".travis.yml"
138
+ - CODE_OF_CONDUCT.md
139
+ - Gemfile
140
+ - LICENSE.txt
141
+ - README.md
142
+ - Rakefile
143
+ - bin/lamp
144
+ - bin/pg-client
145
+ - bin/pg-server
146
+ - examples/client/example_client.rb
147
+ - examples/server/example_server.rb
148
+ - examples/server/example_server_ssl.rb
149
+ - examples/server/legit.cert.pem
150
+ - examples/server/legit.key.pem
151
+ - lib/packet_genie.rb
152
+ - lib/packet_genie/client.rb
153
+ - lib/packet_genie/server.rb
154
+ - lib/packet_genie/version.rb
155
+ - packet_genie.gemspec
156
+ homepage: https://github.com/picatz/packet_genie
157
+ licenses:
158
+ - MIT
159
+ metadata: {}
160
+ post_install_message:
161
+ rdoc_options: []
162
+ require_paths:
163
+ - lib
164
+ required_ruby_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ required_rubygems_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">"
172
+ - !ruby/object:Gem::Version
173
+ version: 1.3.1
174
+ requirements: []
175
+ rubyforge_project:
176
+ rubygems_version: 2.6.8
177
+ signing_key:
178
+ specification_version: 4
179
+ summary: Magically streaming live packet captures with a simple REST API
180
+ test_files: []