socksify 1.1.1 → 1.1.2

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.
Files changed (3) hide show
  1. data/lib/socksify.rb +82 -45
  2. metadata +18 -6
  3. data/lib/socksify.rb.orig +0 -244
data/lib/socksify.rb CHANGED
@@ -16,6 +16,7 @@
16
16
  =end
17
17
 
18
18
  require 'socket'
19
+ require 'resolv'
19
20
  require 'socksify_debug'
20
21
 
21
22
  class SOCKSError < RuntimeError
@@ -90,6 +91,14 @@ class SOCKSError < RuntimeError
90
91
  end
91
92
 
92
93
  class TCPSocket
94
+ @@socks_version ||= "5"
95
+
96
+ def self.socks_version
97
+ (@@socks_version == "4a" or @@socks_version == "4") ? "\004" : "\005"
98
+ end
99
+ def self.socks_version=(version)
100
+ @@socks_version = version.to_s
101
+ end
93
102
  def self.socks_server
94
103
  @@socks_server ||= nil
95
104
  end
@@ -121,7 +130,7 @@ class TCPSocket
121
130
  Socksify::debug_notice "Connecting to SOCKS server #{socks_server}:#{socks_port}"
122
131
  initialize_tcp socks_server, socks_port
123
132
 
124
- socks_authenticate
133
+ socks_authenticate unless @@socks_version =~ /^4/
125
134
 
126
135
  if host
127
136
  socks_connect(host, port)
@@ -150,20 +159,39 @@ class TCPSocket
150
159
  # Connect
151
160
  def socks_connect(host, port)
152
161
  Socksify::debug_debug "Sending destination address"
153
- write "\005\001\000"
162
+ write TCPSocket.socks_version
163
+ Socksify::debug_debug TCPSocket.socks_version.unpack "H*"
164
+ write "\001"
165
+ write "\000" if @@socks_version == "5"
166
+ write [port].pack('n') if @@socks_version =~ /^4/
167
+
168
+ if @@socks_version == "4"
169
+ host = Resolv::DNS.new.getaddress(host).to_s
170
+ end
171
+ Socksify::debug_debug host
154
172
  if host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ # to IPv4 address
155
- write "\001" + [$1.to_i,
156
- $2.to_i,
157
- $3.to_i,
158
- $4.to_i
159
- ].pack('CCCC')
173
+ write "\001" if @@socks_version == "5"
174
+ _ip = [$1.to_i,
175
+ $2.to_i,
176
+ $3.to_i,
177
+ $4.to_i
178
+ ].pack('CCCC')
179
+ write _ip
160
180
  elsif host =~ /^[:0-9a-f]+$/ # to IPv6 address
161
181
  raise "TCP/IPv6 over SOCKS is not yet supported (inet_pton missing in Ruby & not supported by Tor"
162
182
  write "\004"
163
183
  else # to hostname
164
- write "\003" + [host.size].pack('C') + host
184
+ if @@socks_version == "5"
185
+ write "\003" + [host.size].pack('C') + host
186
+ else
187
+ write "\000\000\000\001"
188
+ write "\007\000"
189
+ Socksify::debug_notice host
190
+ write host
191
+ write "\000"
192
+ end
165
193
  end
166
- write [port].pack('n')
194
+ write [port].pack('n') if @@socks_version == "5"
167
195
 
168
196
  socks_receive_reply
169
197
  Socksify::debug_notice "Connected to #{host}:#{port} over SOCKS"
@@ -172,44 +200,53 @@ class TCPSocket
172
200
  # returns [bind_addr: String, bind_port: Fixnum]
173
201
  def socks_receive_reply
174
202
  Socksify::debug_debug "Waiting for SOCKS reply"
175
- connect_reply = recv(4)
176
- if connect_reply[0..0] != "\005"
177
- raise SOCKSError.new("SOCKS version #{connect_reply[0..0]} is not 5")
178
- end
179
- if connect_reply[1..1] != "\000"
180
- raise SOCKSError.for_response_code(connect_reply.bytes.to_a[1])
181
- end
182
- Socksify::debug_debug "Waiting for bind_addr"
183
- bind_addr_len = case connect_reply[3..3]
184
- when "\001"
185
- 4
186
- when "\003"
187
- recv(1).bytes.first
188
- when "\004"
189
- 16
190
- else
191
- raise SOCKSError.for_response_code(connect_reply.bytes.to_a[3])
192
- end
193
- bind_addr_s = recv(bind_addr_len)
194
- bind_addr = case connect_reply[3..3]
195
- when "\001"
196
- bind_addr_s.bytes.to_a.join('.')
197
- when "\003"
198
- bind_addr_s
199
- when "\004" # Untested!
200
- i = 0
201
- ip6 = ""
202
- bind_addr_s.each_byte do |b|
203
- if i > 0 and i % 2 == 0
204
- ip6 += ":"
205
- end
206
- i += 1
203
+ if @@socks_version == "5"
204
+ connect_reply = recv(4)
205
+ Socksify::debug_debug connect_reply.unpack "H*"
206
+ if connect_reply[0..0] != "\005"
207
+ raise SOCKSError.new("SOCKS version #{connect_reply[0..0]} is not 5")
208
+ end
209
+ if connect_reply[1..1] != "\000"
210
+ raise SOCKSError.for_response_code(connect_reply.bytes.to_a[1])
211
+ end
212
+ Socksify::debug_debug "Waiting for bind_addr"
213
+ bind_addr_len = case connect_reply[3..3]
214
+ when "\001"
215
+ 4
216
+ when "\003"
217
+ recv(1).bytes.first
218
+ when "\004"
219
+ 16
220
+ else
221
+ raise SOCKSError.for_response_code(connect_reply.bytes.to_a[3])
222
+ end
223
+ bind_addr_s = recv(bind_addr_len)
224
+ bind_addr = case connect_reply[3..3]
225
+ when "\001"
226
+ bind_addr_s.bytes.to_a.join('.')
227
+ when "\003"
228
+ bind_addr_s
229
+ when "\004" # Untested!
230
+ i = 0
231
+ ip6 = ""
232
+ bind_addr_s.each_byte do |b|
233
+ if i > 0 and i % 2 == 0
234
+ ip6 += ":"
235
+ end
236
+ i += 1
207
237
 
208
- ip6 += b.to_s(16).rjust(2, '0')
238
+ ip6 += b.to_s(16).rjust(2, '0')
239
+ end
209
240
  end
210
- end
211
- bind_port = recv(bind_addr_len + 2)
212
- [bind_addr, bind_port.unpack('n')]
241
+ bind_port = recv(bind_addr_len + 2)
242
+ [bind_addr, bind_port.unpack('n')]
243
+ else
244
+ connect_reply = recv(8)
245
+ unless connect_reply[0] == "\000" and connect_reply[1] == "\x5A"
246
+ Socksify::debug_debug connect_reply.unpack 'H'
247
+ raise SOCKSError.new("Failed while connecting througth socks")
248
+ end
249
+ end
213
250
  end
214
251
  end
215
252
 
metadata CHANGED
@@ -1,15 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: socksify
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 1
9
+ - 2
10
+ version: 1.1.2
5
11
  platform: ruby
6
12
  authors:
7
13
  - Stephan Maka
14
+ - Andrey Kouznetsov
8
15
  autorequire:
9
16
  bindir: bin
10
17
  cert_chain: []
11
18
 
12
- date: 2010-03-15 00:00:00 +01:00
19
+ date: 2010-10-20 00:00:00 +02:00
13
20
  default_executable:
14
21
  dependencies: []
15
22
 
@@ -26,7 +33,6 @@ extra_rdoc_files:
26
33
  files:
27
34
  - COPYING
28
35
  - lib/socksify_debug.rb
29
- - lib/socksify.rb.orig
30
36
  - lib/socksify.rb
31
37
  - bin/socksify_ruby
32
38
  - doc/index.css
@@ -41,21 +47,27 @@ rdoc_options: []
41
47
  require_paths:
42
48
  - lib
43
49
  required_ruby_version: !ruby/object:Gem::Requirement
50
+ none: false
44
51
  requirements:
45
52
  - - ">="
46
53
  - !ruby/object:Gem::Version
54
+ hash: 3
55
+ segments:
56
+ - 0
47
57
  version: "0"
48
- version:
49
58
  required_rubygems_version: !ruby/object:Gem::Requirement
59
+ none: false
50
60
  requirements:
51
61
  - - ">="
52
62
  - !ruby/object:Gem::Version
63
+ hash: 3
64
+ segments:
65
+ - 0
53
66
  version: "0"
54
- version:
55
67
  requirements: []
56
68
 
57
69
  rubyforge_project: socksify
58
- rubygems_version: 1.3.5
70
+ rubygems_version: 1.3.7
59
71
  signing_key:
60
72
  specification_version: 3
61
73
  summary: Redirect all TCPSockets through a SOCKS5 proxy
data/lib/socksify.rb.orig DELETED
@@ -1,244 +0,0 @@
1
- =begin
2
- Copyright (C) 2007 Stephan Maka <stephan@spaceboyz.net>
3
-
4
- This program is free software: you can redistribute it and/or modify
5
- it under the terms of the GNU General Public License as published by
6
- the Free Software Foundation, either version 3 of the License, or
7
- (at your option) any later version.
8
-
9
- This program is distributed in the hope that it will be useful,
10
- but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- GNU General Public License for more details.
13
-
14
- You should have received a copy of the GNU General Public License
15
- along with this program. If not, see <http://www.gnu.org/licenses/>.
16
- =end
17
-
18
- require 'socket'
19
- require 'socksify_debug'
20
-
21
- class SOCKSError < RuntimeError
22
- def initialize(msg)
23
- Socksify::debug_error("#{self.class}: #{msg}")
24
- super
25
- end
26
-
27
- class ServerFailure < SOCKSError
28
- def initialize
29
- super("general SOCKS server failure")
30
- end
31
- end
32
- class NotAllowed < SOCKSError
33
- def initialize
34
- super("connection not allowed by ruleset")
35
- end
36
- end
37
- class NetworkUnreachable < SOCKSError
38
- def initialize
39
- super("Network unreachable")
40
- end
41
- end
42
- class HostUnreachable < SOCKSError
43
- def initialize
44
- super("Host unreachable")
45
- end
46
- end
47
- class ConnectionRefused < SOCKSError
48
- def initialize
49
- super("Connection refused")
50
- end
51
- end
52
- class TTLExpired < SOCKSError
53
- def initialize
54
- super("TTL expired")
55
- end
56
- end
57
- class CommandNotSupported < SOCKSError
58
- def initialize
59
- super("Command not supported")
60
- end
61
- end
62
- class AddressTypeNotSupported < SOCKSError
63
- def initialize
64
- super("Address type not supported")
65
- end
66
- end
67
-
68
- def self.for_response_code(code)
69
- case code
70
- when 1
71
- ServerFailure
72
- when 2
73
- NotAllowed
74
- when 3
75
- NetworkUnreachable
76
- when 4
77
- HostUnreachable
78
- when 5
79
- ConnectionRefused
80
- when 6
81
- TTLExpired
82
- when 7
83
- CommandNotSupported
84
- when 8
85
- AddressTypeNotSupported
86
- else
87
- self
88
- end
89
- end
90
- end
91
-
92
- class TCPSocket
93
- def self.socks_server
94
- @@socks_server
95
- end
96
- def self.socks_server=(host)
97
- @@socks_server = host
98
- end
99
- def self.socks_port
100
- @@socks_port
101
- end
102
- def self.socks_port=(port)
103
- @@socks_port = port
104
- end
105
- def self.socks_ignores
106
- @@socks_ignores ||= []
107
- end
108
- def self.socks_ignores=(ignores)
109
- @@socks_ignores = ignores
110
- end
111
-
112
- alias :initialize_tcp :initialize
113
-
114
- # See http://tools.ietf.org/html/rfc1928
115
- def initialize(host=nil, port=0, local_host="0.0.0.0", local_port=0)
116
- socks_server = self.class.socks_server
117
- socks_port = self.class.socks_port
118
- socks_ignores = self.class.socks_ignores
119
-
120
- if socks_server and socks_port and not socks_ignores.include?(host)
121
- Socksify::debug_notice "Connecting to SOCKS server #{socks_server}:#{socks_port}"
122
- initialize_tcp socks_server, socks_port
123
-
124
- socks_authenticate
125
-
126
- if host
127
- socks_connect(host, port)
128
- end
129
- else
130
- Socksify::debug_notice "Connecting directly to #{host}:#{port}"
131
- initialize_tcp host, port, local_host, local_port
132
- Socksify::debug_debug "Connected to #{host}:#{port}"
133
- end
134
- end
135
-
136
- # Authentication
137
- def socks_authenticate
138
- Socksify::debug_debug "Sending no authentication"
139
- write "\005\001\000"
140
- Socksify::debug_debug "Waiting for authentication reply"
141
- auth_reply = recv(2)
142
- if auth_reply[0] != 4 and auth_reply[0] != 5
143
- raise SOCKSError.new("SOCKS version #{auth_reply[0]} not supported")
144
- end
145
- if auth_reply[1] != 0
146
- raise SOCKSError.new("SOCKS authentication method #{auth_reply[1]} neither requested nor supported")
147
- end
148
- end
149
-
150
- # Connect
151
- def socks_connect(host, port)
152
- Socksify::debug_debug "Sending destination address"
153
- write "\005\001\000"
154
- if host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ # to IPv4 address
155
- write "\001" + [$1.to_i,
156
- $2.to_i,
157
- $3.to_i,
158
- $4.to_i
159
- ].pack('CCCC')
160
- elsif host =~ /^[:0-9a-f]+$/ # to IPv6 address
161
- raise "TCP/IPv6 over SOCKS is not yet supported (inet_pton missing in Ruby & not supported by Tor"
162
- write "\004"
163
- else # to hostname
164
- write "\003" + [host.size].pack('C') + host
165
- end
166
- write [port].pack('n')
167
-
168
- socks_receive_reply
169
- Socksify::debug_notice "Connected to #{host}:#{port} over SOCKS"
170
- end
171
-
172
- # returns [bind_addr: String, bind_port: Fixnum]
173
- def socks_receive_reply
174
- Socksify::debug_debug "Waiting for SOCKS reply"
175
- connect_reply = recv(4)
176
- if connect_reply[0] != 5
177
- raise SOCKSError.new("SOCKS version #{connect_reply[0]} is not 5")
178
- end
179
- if connect_reply[1] != 0
180
- raise SOCKSError.for_response_code(connect_reply[1])
181
- end
182
- Socksify::debug_debug "Waiting for bind_addr"
183
- bind_addr_len = case connect_reply[3]
184
- when 1
185
- 4
186
- when 3
187
- recv(1)[0]
188
- when 4
189
- 16
190
- else
191
- raise SOCKSError.for_response_code(connect_reply[3])
192
- end
193
- bind_addr_s = recv(bind_addr_len)
194
- bind_addr = case connect_reply[3]
195
- when 1
196
- "#{bind_addr_s[0]}.#{bind_addr_s[1]}.#{bind_addr_s[2]}.#{bind_addr_s[3]}"
197
- when 3
198
- bind_addr_s
199
- when 4 # Untested!
200
- i = 0
201
- ip6 = ""
202
- bind_addr_s.each_byte do |b|
203
- if i > 0 and i % 2 == 0
204
- ip6 += ":"
205
- end
206
- i += 1
207
-
208
- ip6 += b.to_s(16).rjust(2, '0')
209
- end
210
- end
211
- bind_port = recv(bind_addr_len + 2)
212
- [bind_addr, bind_port.unpack('n')]
213
- end
214
- end
215
-
216
- module Socksify
217
- def self.resolve(host)
218
- s = TCPSocket.new
219
-
220
- begin
221
- Socksify::debug_debug "Sending hostname to resolve: #{host}"
222
- s.write "\005"
223
- if host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ # to IPv4 address
224
- s.write "\xF1\000\001" + [$1.to_i,
225
- $2.to_i,
226
- $3.to_i,
227
- $4.to_i
228
- ].pack('CCCC')
229
- elsif host =~ /^[:0-9a-f]+$/ # to IPv6 address
230
- raise "TCP/IPv6 over SOCKS is not yet supported (inet_pton missing in Ruby & not supported by Tor"
231
- s.write "\004"
232
- else # to hostname
233
- s.write "\xF0\000\003" + [host.size].pack('C') + host
234
- end
235
- s.write [0].pack('n') # Port
236
-
237
- addr, port = s.socks_receive_reply
238
- Socksify::debug_notice "Resolved #{host} as #{addr} over SOCKS"
239
- addr
240
- ensure
241
- s.close
242
- end
243
- end
244
- end