proxie 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+