checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
---
2
2
SHA256:
3
- metadata.gz: cb07bd5b043baa9c23a210d3b69a63bfa1a4659b21431402aa52cf4def01a3aa
4
- data.tar.gz: e99b79f9638840da4aeda3dc8991482ebe2c5f2f91ad262596c7c2d3b7ee9107
3
+ metadata.gz: 5b123ce6c20f6502e2d9113a4776a23460b0decdd1aa47becebccc4aa682ed85
4
+ data.tar.gz: d866a719eae28e9841f2969ebe9873a5bff63cb85044f2e8253632cf4f8c86a8
5
5
SHA512:
6
- metadata.gz: d31e65816117bd0bb460098f0f694d3ca3663b04f67054b44577ae76dc27cdec8b3fa1ba8944616ee5282a94c55a53577100fdcaeac7e076907cb1e91fd62e18
7
- data.tar.gz: 9aa60e5d9fa736118e394292a12f185864de809ba8335add50f5ad1885c993c1b4c84476b1a8d7b2c395a814da7d580b4a43474cc9b8f3805181fad6b489045e
6
+ metadata.gz: eb343ce13ca2a3974703538709958e7dc974e630d7caa7c928a3494cdaf473d2f156f195becb274f2d7286d93aa770a992696c11730fedef31d0e3d6bc2c8f27
7
+ data.tar.gz: e989aa22f362ac3f7f74290866a86b52b06bd48d219852bc4573770c64e6696abb62b35c2b23b94b8cb60310bfe114d121424fb52eb174a2074cfdb49979cb82
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *.gem
2
+ .rspec_status
data/.rspec_status CHANGED
@@ -1,3 +1,3 @@
1
1
example_id | status | run_time |
2
2
---------------------------- | ------ | --------------- |
3
- ./spec/socket_spec.rb[1:1:1] | passed | 0.04133 seconds |
3
+ ./spec/socket_spec.rb[1:1:1] | passed | 0.13532 seconds |
data/dress_socks-0.1.0.gem DELETED
Binary file
data/lib/dress_socks/socket.rb ADDED
@@ -0,0 +1,164 @@
1
+ module DressSocks
2
+ class Socket < ::TCPSocket
3
+ attr_accessor :socks_server, :socks_port, :socks_version, :socks_ignores, :socks_username, :socks_password
4
+
5
+ alias :initialize_tcp :initialize
6
+
7
+
8
+ def encoded_socks_version
9
+ (self.socks_version == "4a" or self.socks_version == "4") ? "\004" : "\005"
10
+ end
11
+
12
+ # See http://tools.ietf.org/html/rfc1928
13
+ def initialize(remote_host=nil, remote_port=0, local_host=nil, local_port=nil,
14
+ socks_username: nil, socks_password: nil, socks_server: nil, socks_port: nil,
15
+ socks_ignores: [], socks_version: '5')
16
+
17
+ self.socks_server = socks_server
18
+ self.socks_port = socks_port
19
+ self.socks_username = socks_username
20
+ self.socks_password = socks_password
21
+ self.socks_ignores = socks_ignores
22
+ self.socks_version = socks_version
23
+
24
+
25
+ if socks_server and socks_port and not socks_ignores.include?(remote_host)
26
+ initialize_tcp socks_server, socks_port
27
+
28
+ socks_authenticate unless socks_version =~ /^4/
29
+
30
+ if remote_host
31
+ socks_connect(remote_host, remote_port)
32
+ end
33
+ else
34
+ initialize_tcp remote_host, remote_port, local_host, local_port
35
+ end
36
+ end
37
+
38
+ # Authentication
39
+ def socks_authenticate
40
+ if self.socks_username || self.socks_password
41
+ write "\005\001\002"
42
+ else
43
+ write "\005\001\000"
44
+ end
45
+ auth_reply = recv(2)
46
+ if auth_reply.empty?
47
+ raise DressSocks::SOCKSError.new("Server doesn't reply authentication")
48
+ end
49
+ if auth_reply[0..0] != "\004" and auth_reply[0..0] != "\005"
50
+ raise DressSocks::SOCKSError.new("SOCKS version #{auth_reply[0..0]} not supported")
51
+ end
52
+ if self.socks_username || self.socks_password
53
+ if auth_reply[1..1] != "\002"
54
+ raise DressSocks::SOCKSError.new("SOCKS authentication method #{auth_reply[1..1]} neither requested nor supported")
55
+ end
56
+ auth = "\001"
57
+ auth += self.socks_username.to_s.length.chr
58
+ auth += self.socks_username.to_s
59
+ auth += self.socks_password.to_s.length.chr
60
+ auth += self.socks_password.to_s
61
+ write auth
62
+ auth_reply = recv(2)
63
+ if auth_reply[1..1] != "\000"
64
+ raise DressSocks::SOCKSError.new("SOCKS authentication failed")
65
+ end
66
+ else
67
+ if auth_reply[1..1] != "\000"
68
+ raise DressSocks::SOCKSError.new("SOCKS authentication method #{auth_reply[1..1]} neither requested nor supported")
69
+ end
70
+ end
71
+ end
72
+
73
+ # Connect
74
+ def socks_connect(host, port)
75
+ port = ::Socket.getservbyname(port) if port.is_a?(String)
76
+ req = String.new
77
+ req << self.encoded_socks_version
78
+ req << "\001"
79
+ req << "\000" if self.socks_version == "5"
80
+ req << [port].pack('n') if self.socks_version =~ /^4/
81
+
82
+ if self.socks_version == "4"
83
+ host = Resolv::DNS.new.getaddress(host).to_s
84
+ end
85
+ if host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)#x2F; # to IPv4 address
86
+ req << "\001" if self.socks_version == "5"
87
+ _ip = [$1.to_i,
88
+ $2.to_i,
89
+ $3.to_i,
90
+ $4.to_i
91
+ ].pack('CCCC')
92
+ req << _ip
93
+ elsif host =~ /^[:0-9a-f]+#x2F; # to IPv6 address
94
+ raise "TCP/IPv6 over SOCKS is not yet supported (inet_pton missing in Ruby & not supported by Tor"
95
+ req << "\004"
96
+ else # to hostname
97
+ if self.socks_version == "5"
98
+ req << "\003" + [host.size].pack('C') + host
99
+ else
100
+ req << "\000\000\000\001"
101
+ req << "\007\000"
102
+ req << host
103
+ req << "\000"
104
+ end
105
+ end
106
+ req << [port].pack('n') if self.socks_version == "5"
107
+
108
+ write req
109
+
110
+ socks_receive_reply
111
+ end
112
+
113
+ # returns [bind_addr: String, bind_port: Fixnum]
114
+ def socks_receive_reply
115
+ if self.socks_version == "5"
116
+ connect_reply = recv(4)
117
+ if connect_reply.empty?
118
+ raise DressSocks::SOCKSError.new("Server doesn't reply")
119
+ end
120
+ if connect_reply[0..0] != "\005"
121
+ raise DressSocks::SOCKSError.new("SOCKS version #{connect_reply[0..0]} is not 5")
122
+ end
123
+ if connect_reply[1..1] != "\000"
124
+ raise DressSocks::SOCKSError.for_response_code(connect_reply.bytes.to_a[1])
125
+ end
126
+ bind_addr_len = case connect_reply[3..3]
127
+ when "\001"
128
+ 4
129
+ when "\003"
130
+ recv(1).bytes.first
131
+ when "\004"
132
+ 16
133
+ else
134
+ raise DressSocks::SOCKSError.for_response_code(connect_reply.bytes.to_a[3])
135
+ end
136
+ bind_addr_s = recv(bind_addr_len)
137
+ bind_addr = case connect_reply[3..3]
138
+ when "\001"
139
+ bind_addr_s.bytes.to_a.join('.')
140
+ when "\003"
141
+ bind_addr_s
142
+ when "\004" # Untested!
143
+ i = 0
144
+ ip6 = ""
145
+ bind_addr_s.each_byte do |b|
146
+ if i > 0 and i % 2 == 0
147
+ ip6 += ":"
148
+ end
149
+ i += 1
150
+
151
+ ip6 += b.to_s(16).rjust(2, '0')
152
+ end
153
+ end
154
+ bind_port = recv(bind_addr_len + 2)
155
+ [bind_addr, bind_port.unpack('n')]
156
+ else
157
+ connect_reply = recv(8)
158
+ unless connect_reply[0] == "\000" and connect_reply[1] == "\x5A"
159
+ raise DressSocks::SOCKSError.new("Failed while connecting througth socks")
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
data/lib/dress_socks/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
module DressSocks
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
--- !ruby/object:Gem::Specification
2
2
name: dress_socks
3
3
version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
platform: ruby
6
6
authors:
7
7
- Justin McNally
@@ -60,6 +60,7 @@ executables: []
60
60
extensions: []
61
61
extra_rdoc_files: []
62
62
files:
63
+ - ".gitignore"
63
64
- ".rspec"
64
65
- ".rspec_status"
65
66
- Changelog.md
@@ -70,10 +71,10 @@ files:
70
71
- Rakefile
71
72
- bin/console
72
73
- bin/setup
73
- - dress_socks-0.1.0.gem
74
74
- dress_socks.gemspec
75
75
- lib/dress_socks.rb
76
76
- lib/dress_socks/errors.rb
77
+ - lib/dress_socks/socket.rb
77
78
- lib/dress_socks/version.rb
78
79
homepage: https://github.com/chowly/dress_socks
79
80
licenses: