em-socksify 0.2.1 → 0.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/README.md +43 -9
- data/em-socksify.gemspec +2 -1
- data/lib/em-socksify.rb +10 -0
- data/lib/em-socksify/connect.rb +28 -0
- data/lib/em-socksify/connectify.rb +41 -0
- data/lib/em-socksify/errors.rb +5 -0
- data/lib/em-socksify/version.rb +3 -5
- data/spec/socksify_spec.rb +34 -2
- metadata +22 -5
- data/.rspec +0 -0
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
#
|
1
|
+
# Transparent proxy support for any EventMachine protocol
|
2
2
|
|
3
|
-
Dealing with SOCKS proxies is pain. EM-Socksify provides a simple
|
3
|
+
Dealing with SOCKS and HTTP proxies is a pain. EM-Socksify provides a simple ship to setup and negotiation a SOCKS / HTTP connection for any EventMachine protocol.
|
4
4
|
|
5
|
-
|
5
|
+
### Example: Routing HTTP request via SOCKS5 proxy
|
6
6
|
|
7
7
|
```ruby
|
8
8
|
class Handler < EM::Connection
|
@@ -24,9 +24,9 @@ EM.run do
|
|
24
24
|
end
|
25
25
|
```
|
26
26
|
|
27
|
-
What's happening here? First, we open a raw TCP connection to the SOCKS proxy
|
27
|
+
What's happening here? First, we open a raw TCP connection to the SOCKS proxy. Once the TCP connection is established, EventMachine calls the **connection_completed** method in our handler, at which point we call the helper method (**socksify**) with the actual destination and host and port (address that we actually want to get to), and the module does the rest.
|
28
28
|
|
29
|
-
|
29
|
+
socksify temporarily intercepts your receive_data callbacks, negotiates the SOCKS connection (version, authentication, etc), and then once all of that is done, returns control back to your code.
|
30
30
|
|
31
31
|
For SOCKS proxies which require authentication, use:
|
32
32
|
|
@@ -34,17 +34,51 @@ For SOCKS proxies which require authentication, use:
|
|
34
34
|
socksify(destination_host, destination_port, username, password, version)
|
35
35
|
```
|
36
36
|
|
37
|
-
|
37
|
+
### Example: Routing HTTPS request via a squid CONNECT proxy
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
class Handler < EM::Connection
|
41
|
+
include EM::Connectify
|
42
|
+
|
43
|
+
def connection_completed
|
44
|
+
connectify('www.google.ca', 443) do
|
45
|
+
start_tls
|
46
|
+
send_data "GET / HTTP/1.1\r\nConnection:close\r\nHost: www.google.ca\r\n\r\n"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def receive_data(data)
|
51
|
+
p data
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
EM.run do
|
56
|
+
EventMachine.connect PROXY_HOST, PROXY_PORT, Handler
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
For CONNECT proxies which require authentication, use:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
connectify(destination_host, destination_port, username, password)
|
64
|
+
```
|
65
|
+
|
66
|
+
### Wishlist
|
38
67
|
|
39
68
|
- IPV6 support
|
40
69
|
- SOCKS4 support
|
41
70
|
|
42
|
-
|
71
|
+
### Resources
|
43
72
|
|
44
73
|
- [SOCKS on Wikipedia](http://en.wikipedia.org/wiki/SOCKS)
|
45
74
|
- [Socksify-Ruby](https://github.com/astro/socksify-ruby) for regular Ruby TCPSocket
|
75
|
+
- [HTTP Connect Tunneling](http://en.wikipedia.org/wiki/HTTP_tunnel#HTTP_CONNECT_Tunneling)
|
76
|
+
|
77
|
+
### Contributors
|
78
|
+
|
79
|
+
- [Ilya Grigorik](https://github.com/igrigorik)
|
80
|
+
- [Conrad Irwin](https://github.com/ConradIrwin)
|
46
81
|
|
47
|
-
|
82
|
+
### License
|
48
83
|
|
49
84
|
(The MIT License)
|
50
|
-
Copyright © 2011 Ilya Grigorik
|
data/em-socksify.gemspec
CHANGED
@@ -9,13 +9,14 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.authors = ["Ilya Grigorik"]
|
10
10
|
s.email = ["ilya@igvita.com"]
|
11
11
|
s.homepage = "http://github.com/igrigorik/em-socksify"
|
12
|
-
s.summary = "
|
12
|
+
s.summary = "Transparent proxy support for any EventMachine protocol"
|
13
13
|
s.description = s.summary
|
14
14
|
|
15
15
|
s.rubyforge_project = "em-socksify"
|
16
16
|
|
17
17
|
s.add_dependency "eventmachine", ">= 1.0.0.beta.4"
|
18
18
|
s.add_development_dependency "rspec"
|
19
|
+
s.add_development_dependency "rake"
|
19
20
|
|
20
21
|
s.files = `git ls-files`.split("\n")
|
21
22
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
data/lib/em-socksify.rb
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
require 'eventmachine'
|
2
|
+
require 'base64'
|
2
3
|
|
3
4
|
require 'em-socksify/socksify'
|
4
5
|
require 'em-socksify/errors'
|
5
6
|
require 'em-socksify/socks5'
|
7
|
+
require 'em-socksify/connectify'
|
8
|
+
require 'em-socksify/connect'
|
9
|
+
|
10
|
+
# Backport from ruby-1.9 to ruby-1.8 (which doesn't support pack('m0') either)
|
11
|
+
unless Base64.respond_to?(:strict_encode64)
|
12
|
+
def Base64.strict_encode64(str)
|
13
|
+
Base64.encode64(str).gsub("\n", "")
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module EventMachine
|
2
|
+
module Connectify
|
3
|
+
module CONNECT
|
4
|
+
def connect_send_handshake
|
5
|
+
header = "CONNECT #{@connect_target_host}:#{@connect_target_port} HTTP/1.0\r\n"
|
6
|
+
if @connect_username || @connect_password
|
7
|
+
encoded_credentials = Base64.strict_encode64([@connect_username, @connect_password].join(":"))
|
8
|
+
header << "Proxy-Authorization: Basic #{encoded_credentials}\r\n"
|
9
|
+
end
|
10
|
+
|
11
|
+
header << "\r\n"
|
12
|
+
send_data(header)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def connect_parse_response
|
18
|
+
unless @connect_data =~ %r{\AHTTP/1\.[01] 200 .*\r\n\r\n}m
|
19
|
+
raise CONNECTError.new, "Unexpected response: #{@connect_data}"
|
20
|
+
end
|
21
|
+
|
22
|
+
connect_unhook
|
23
|
+
rescue => e
|
24
|
+
@connect_deferrable.fail e
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module EventMachine
|
2
|
+
|
3
|
+
module Connectify
|
4
|
+
def connectify(host, port, username=nil, password=nil, &blk)
|
5
|
+
@connect_target_host = host
|
6
|
+
@connect_target_port = port
|
7
|
+
@connect_username = username
|
8
|
+
@connect_password = password
|
9
|
+
@connect_data = ''
|
10
|
+
|
11
|
+
connect_hook
|
12
|
+
connect_send_handshake
|
13
|
+
|
14
|
+
@connect_deferrable = DefaultDeferrable.new
|
15
|
+
@connect_deferrable.callback(&blk) if blk
|
16
|
+
@connect_deferrable
|
17
|
+
end
|
18
|
+
|
19
|
+
def connect_hook
|
20
|
+
extend CONNECT
|
21
|
+
|
22
|
+
class << self
|
23
|
+
alias receive_data connect_receive_data
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def connect_unhook
|
28
|
+
class << self
|
29
|
+
remove_method :receive_data
|
30
|
+
end
|
31
|
+
|
32
|
+
@connect_deferrable.succeed
|
33
|
+
end
|
34
|
+
|
35
|
+
def connect_receive_data(data)
|
36
|
+
@connect_data << data
|
37
|
+
connect_parse_response
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/lib/em-socksify/errors.rb
CHANGED
data/lib/em-socksify/version.rb
CHANGED
data/spec/socksify_spec.rb
CHANGED
@@ -2,14 +2,15 @@ require 'helper'
|
|
2
2
|
|
3
3
|
describe EventMachine do
|
4
4
|
|
5
|
+
# requires: ssh -D 8080 localhost
|
5
6
|
it "should negotiate a socks connection" do
|
6
7
|
|
7
8
|
class Handler < EM::Connection
|
8
9
|
include EM::Socksify
|
9
10
|
|
10
11
|
def connection_completed
|
11
|
-
socksify('google.
|
12
|
-
send_data "GET / HTTP/1.1\r\nConnection:close\r\nHost: google.
|
12
|
+
socksify('google.com', 80) do |ip|
|
13
|
+
send_data "GET / HTTP/1.1\r\nConnection:close\r\nHost: google.com\r\n\r\n"
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
@@ -30,4 +31,35 @@ describe EventMachine do
|
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
34
|
+
# requires squid running on localhost with default config
|
35
|
+
it "should negotiate a connect connection" do
|
36
|
+
|
37
|
+
class Handler < EM::Connection
|
38
|
+
include EM::Connectify
|
39
|
+
|
40
|
+
def connection_completed
|
41
|
+
connectify('www.google.com', 443) do
|
42
|
+
start_tls
|
43
|
+
send_data "GET / HTTP/1.1\r\nConnection:close\r\nHost: www.google.com\r\n\r\n"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def receive_data(data)
|
48
|
+
@received ||= ''
|
49
|
+
@received << data
|
50
|
+
end
|
51
|
+
|
52
|
+
def unbind
|
53
|
+
@received.size.should > 0
|
54
|
+
@received[0,4].should == 'HTTP'
|
55
|
+
EM.stop
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
EM::run do
|
60
|
+
EventMachine.connect '127.0.0.1', 8081, Handler
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
33
65
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-socksify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-06-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|
@@ -43,7 +43,23 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
-
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: Transparent proxy support for any EventMachine protocol
|
47
63
|
email:
|
48
64
|
- ilya@igvita.com
|
49
65
|
executables: []
|
@@ -51,12 +67,13 @@ extensions: []
|
|
51
67
|
extra_rdoc_files: []
|
52
68
|
files:
|
53
69
|
- .gitignore
|
54
|
-
- .rspec
|
55
70
|
- Gemfile
|
56
71
|
- README.md
|
57
72
|
- Rakefile
|
58
73
|
- em-socksify.gemspec
|
59
74
|
- lib/em-socksify.rb
|
75
|
+
- lib/em-socksify/connect.rb
|
76
|
+
- lib/em-socksify/connectify.rb
|
60
77
|
- lib/em-socksify/errors.rb
|
61
78
|
- lib/em-socksify/socks5.rb
|
62
79
|
- lib/em-socksify/socksify.rb
|
@@ -86,7 +103,7 @@ rubyforge_project: em-socksify
|
|
86
103
|
rubygems_version: 1.8.24
|
87
104
|
signing_key:
|
88
105
|
specification_version: 3
|
89
|
-
summary:
|
106
|
+
summary: Transparent proxy support for any EventMachine protocol
|
90
107
|
test_files:
|
91
108
|
- spec/helper.rb
|
92
109
|
- spec/socksify_spec.rb
|
data/.rspec
DELETED
File without changes
|