proxie 0.1.1

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.
@@ -0,0 +1,42 @@
1
+ = Proxie: HTTP proxy and debugging tool
2
+
3
+ Proxie allows you to setup HTTP proxy server on specified port, filter traffic by type, store information into SQLite3 database.
4
+ Databases web access is powered by Sinatra web framework.
5
+
6
+ = Installation
7
+
8
+ gem install proxie
9
+
10
+ = Usage
11
+
12
+ Just type 'proxie' in your terminal and proxy server will be spawned.
13
+ For additional information type:
14
+
15
+ proxie --help
16
+
17
+ Output:
18
+
19
+ Usage: proxie [options]
20
+ -i, --info Display this information.
21
+ -p, --port PORT Listen on port (8080 default)
22
+ -d, --db NAME Store results to database
23
+ -w, --web Start a Web UI for databases
24
+ -f, --flush Delete all local databases
25
+
26
+ = Examples
27
+
28
+ Setup proxy server on port 9090 and write all http data into 'sample' database
29
+
30
+ proxie -p 9090 -d sample
31
+
32
+ Activate web interface (localhost:4567/):
33
+
34
+ proxie --web
35
+
36
+ Remove all existing databases:
37
+
38
+ proxie --flush
39
+
40
+ = Credits
41
+
42
+ * Dan Sosedoff - http://github.com/sosedoff
@@ -0,0 +1,3 @@
1
+ task :build do
2
+ `gem build proxie.gemspec`
3
+ end
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
5
+
6
+ require 'rubygems'
7
+ require 'sequel'
8
+ require 'optparse'
9
+ require 'cgi'
10
+ require 'proxie'
11
+
12
+ Proxie.init
13
+
14
+ options = {
15
+ :port => 8080,
16
+ :db => "db_#{Time.now.to_i}",
17
+ :listen => true
18
+ }
19
+
20
+ optparse = OptionParser.new do |opts|
21
+ opts.banner = "Proxie v#{Proxie::VERSION}\nUsage: proxie [options]"
22
+ opts.on('-i', '--info', 'Display this information.') { puts opts; exit }
23
+ opts.on('-p', '--port PORT', 'Listen on port') { |v| options[:port] = v }
24
+ opts.on('-d', '--db NAME', 'Store results to database') { |v| options[:db] = v }
25
+ opts.on('-w', '--web', 'Start a Web UI for databases') { options[:listen] = false }
26
+ opts.on('-f', '--flush', 'Delete all local databases') do
27
+ puts "Deleting databases..."
28
+ Dir.glob("#{Proxie.root}/*.sqlite").each do |f|
29
+ puts "-> #{File.basename(f)} : #{File.delete(f)}"
30
+ end
31
+ exit
32
+ end
33
+ end
34
+
35
+ begin
36
+ optparse.parse!
37
+ if options[:listen]
38
+ server = Proxie::Server.new(options[:port])
39
+ server.logger = Proxie::SQLiteLogger.new("#{Proxie.root}/#{options[:db]}.sqlite")
40
+ trap("INT") { server.stop }
41
+ server.start
42
+ end
43
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument
44
+ puts optparse
45
+ rescue RuntimeError => err
46
+ puts "ERROR: #{err.message}"
47
+ end
48
+
49
+ require 'proxie/web' if !options[:listen]
@@ -0,0 +1,8 @@
1
+ require 'webrick/httpproxy'
2
+ require 'sequel'
3
+ require 'json'
4
+
5
+ require 'proxie/version'
6
+ require 'proxie/proxie'
7
+ require 'proxie/server'
8
+ require 'proxie/logger'
@@ -0,0 +1,40 @@
1
+ module Proxie
2
+ class Logger
3
+ def packet(req, resp)
4
+ # DEFAULT LOGGER IS NOT IMPLEMENTED YET
5
+ # OVERRIDE!
6
+ end
7
+ end
8
+
9
+ class SQLiteLogger < Logger
10
+ attr_reader :db, :records
11
+
12
+ # Initialize SQLite3 logger
13
+ def initialize(path, overwrite=true)
14
+ raise 'Database file with this name already exists!' if File.exists?(path) && !overwrite
15
+ File.delete(path) if File.exists?(path)
16
+
17
+ @db = Sequel.sqlite(path)
18
+ @db.create_table :requests do
19
+ primary_key :id
20
+ string :request_headers
21
+ string :request_url
22
+ string :request_body
23
+ string :response_headers
24
+ string :response_body
25
+ end
26
+ @records = @db[:requests]
27
+ end
28
+
29
+ # Save request and response data
30
+ def packet(req, resp)
31
+ @records.insert(
32
+ :request_headers => req.header.to_json,
33
+ :request_url => req.request_line,
34
+ :request_body => req.body.inspect,
35
+ :response_headers => resp.header.to_json,
36
+ :response_body => resp.body.inspect
37
+ )
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,22 @@
1
+ module Proxie
2
+ # Regular expression to detect static
3
+ REGEX_DEFAULT = /\.(png|jpeg|jpg|gif|ico|css|swf)/i
4
+
5
+ # Regular expression to detect javascripts
6
+ REGEX_JS = /\.js/i
7
+
8
+ # Regular expression to detect html
9
+ REGEX_HTML = /(<html>|<body>)/i
10
+
11
+ # Get user work dir
12
+ def self.root
13
+ "#{ENV['HOME']}/.proxie"
14
+ end
15
+
16
+ # Setup Proxie work dir
17
+ def self.init
18
+ unless File.exists?(root) && File.directory?(root)
19
+ Dir.mkdir(root)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,54 @@
1
+ module Proxie
2
+ class Server
3
+ attr_reader :port
4
+ attr_reader :options
5
+ attr_reader :logger
6
+
7
+ # Initialize server instance
8
+ # Options:
9
+ # :default => true Skip static filess like images, stylesheets, swf, etc
10
+ # :html => true Skip if html in body
11
+ # :js => true Skip javascripts
12
+ def initialize(port=8080, args={})
13
+ @options = {
14
+ :default => args[:default] || true,
15
+ :js => args[:js] || true,
16
+ :images => args[:images] || true
17
+ }
18
+
19
+ @server = WEBrick::HTTPProxyServer.new(
20
+ :Port => port,
21
+ :AccessLog => [],
22
+ :ProxyContentHandler => Proc.new { |req, resp| process(req, resp) }
23
+ )
24
+ end
25
+
26
+ # Setup traffic logger
27
+ def logger=(obj)
28
+ raise ArgumentError, 'Logger required!' if obj.nil?
29
+ raise ArgumentError, 'Logger method [packet] is not defined!' unless obj.respond_to?(:packet)
30
+ @logger = obj
31
+ end
32
+
33
+ # Start proxy server
34
+ def start
35
+ raise RuntimeError, 'Logger is not defined!' if @logger.nil?
36
+ @server.start
37
+ end
38
+
39
+ # Stop proxy server
40
+ def stop
41
+ @server.shutdown
42
+ end
43
+
44
+ private
45
+
46
+ # Log traffic request-response sequence
47
+ def process(req, resp)
48
+ return if @options[:default] && req.request_line.match(REGEX_DEFAULT)
49
+ return if @options[:js] && req.request_line.match(REGEX_JS)
50
+ return if @options[:html] && resp.body.match(REGEX_HTML)
51
+ @logger.packet(req, resp)
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,3 @@
1
+ module Proxie
2
+ VERSION = '0.1.1'
3
+ end
@@ -0,0 +1,94 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+
4
+ enable :run
5
+ set :logging, false
6
+ set :dump_errors, false
7
+
8
+ get '/' do
9
+ @files = Dir.glob("#{Proxie.root}/*.sqlite").map do |f|
10
+ {:name => File.basename(f), :size => File.size(f) / 1024 }
11
+ end
12
+ erb :index
13
+ end
14
+
15
+ get '/db/:name' do
16
+ db = Sequel.sqlite("#{Proxie.root}/#{params[:name]}")
17
+ @rows = db[:requests].all
18
+ erb :records
19
+ end
20
+
21
+ __END__
22
+
23
+ @@ layout
24
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
25
+ <html xmlns="http://www.w3.org/1999/xhtml">
26
+ <head>
27
+ <title>Proxie Web</title>
28
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
29
+ <style>
30
+ html { background: #e5e5e5; }
31
+ body { background: transparent; font:13px 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; position: relative; }
32
+ .wrapper { padding: 10px; }
33
+ h1 { border-bottom: 2px solid #ccc; }
34
+ .db { padding: 2px 0px; }
35
+ .db span { font-color: #555; font-size: 11px; }
36
+ .req { background: #fff; border: 1px solid #ccc; margin-bottom: 8px; }
37
+ .req .url { padding: 4px; background: #f1f1f1; }
38
+ .req pre { padding: 4px; white-space: normal; overflow-x: auto; }
39
+ table.headers { }
40
+ table.headers td { border-collapse: 0px; padding: 2px; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; }
41
+ </style>
42
+ </head>
43
+ <body>
44
+ <div class="wrapper">
45
+ <h1>Proxie v<%= Proxie::VERSION %></h1>
46
+ <%= yield %>
47
+ </div>
48
+ </body>
49
+ </html>
50
+
51
+ @@ index
52
+ <h2>Your databases:</h2>
53
+ <% unless @files.empty? %>
54
+ <% @files.each do |f| %>
55
+ <div class="db">
56
+ <a href="/db/<%= f[:name] %>"><%= f[:name] %></a> -
57
+ <span><%= f[:size] %> Kb</span>
58
+ </div>
59
+ <% end %>
60
+ <% else %>
61
+ <p>You dont have any databases yet.</p>
62
+ <% end %>
63
+
64
+ @@records
65
+ <h2><a href="/">Databases</a> :: <%= params[:name] %></h2>
66
+ <% @rows.each do |r| %>
67
+ <div class="req">
68
+ <div class="url"><%= r[:id] %>. <%= r[:request_url] %></div>
69
+ <pre>
70
+ <b>Request Headers:</b><br/>
71
+ <table class="headers">
72
+ <% JSON.parse(r[:request_headers]).each_pair do |k,v| %>
73
+ <tr>
74
+ <td><%= k %></td>
75
+ <td><%= v %></td>
76
+ </tr>
77
+ <% end %>
78
+ </table>
79
+ </pre>
80
+ <pre><b>Request Body:</b><%= r[:request_body] %></pre>
81
+ <pre>
82
+ <b>Request Headers:</b><br/>
83
+ <table class="headers">
84
+ <% JSON.parse(r[:response_headers]).each_pair do |k,v| %>
85
+ <tr>
86
+ <td><%= k %></td>
87
+ <td><%= v %></td>
88
+ </tr>
89
+ <% end %>
90
+ </table>
91
+ </pre>
92
+ <pre><b>Response Body:</b><br/><%= r[:response_body] %></pre>
93
+ </div>
94
+ <% end %>
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: proxie
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 1
10
+ version: 0.1.1
11
+ platform: ruby
12
+ authors:
13
+ - Dan Sosedoff
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-25 00:00:00 -06:00
19
+ default_executable: proxie
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: sinatra
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 51
30
+ segments:
31
+ - 0
32
+ - 9
33
+ - 4
34
+ version: 0.9.4
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: sequel
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - "="
44
+ - !ruby/object:Gem::Version
45
+ hash: 75
46
+ segments:
47
+ - 3
48
+ - 19
49
+ - 0
50
+ version: 3.19.0
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: json
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - "="
60
+ - !ruby/object:Gem::Version
61
+ hash: 11
62
+ segments:
63
+ - 1
64
+ - 4
65
+ - 6
66
+ version: 1.4.6
67
+ type: :runtime
68
+ version_requirements: *id003
69
+ description: Proxie is a HTTP proxy server with sqlite-powered storage and web interface for debugging.
70
+ email: dan.sosedoff@gmail.com
71
+ executables:
72
+ - proxie
73
+ extensions: []
74
+
75
+ extra_rdoc_files: []
76
+
77
+ files:
78
+ - Rakefile
79
+ - bin/proxie
80
+ - lib/proxie/logger.rb
81
+ - lib/proxie/proxie.rb
82
+ - lib/proxie/server.rb
83
+ - lib/proxie/version.rb
84
+ - lib/proxie/web.rb
85
+ - lib/proxie.rb
86
+ - README.rdoc
87
+ has_rdoc: true
88
+ homepage: http://github.com/sosedoff/proxie
89
+ licenses: []
90
+
91
+ post_install_message:
92
+ rdoc_options: []
93
+
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ hash: 3
102
+ segments:
103
+ - 0
104
+ version: "0"
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ hash: 3
111
+ segments:
112
+ - 0
113
+ version: "0"
114
+ requirements: []
115
+
116
+ rubyforge_project:
117
+ rubygems_version: 1.4.1
118
+ signing_key:
119
+ specification_version: 3
120
+ summary: Proxie - Simple http proxy server
121
+ test_files: []
122
+