sockit 0.0.4 → 1.0.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.
- checksums.yaml +7 -0
- data/.rspec +1 -1
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +12 -10
- data/.yardopts +2 -0
- data/README.md +25 -16
- data/bin/sockit +3 -2
- data/lib/sockit/connection.rb +43 -0
- data/lib/sockit/support.rb +53 -0
- data/lib/sockit/v4/connection.rb +62 -0
- data/lib/sockit/v4/support.rb +31 -0
- data/lib/sockit/v5/authentication.rb +105 -0
- data/lib/sockit/v5/connection.rb +98 -0
- data/lib/sockit/v5/support.rb +82 -0
- data/lib/sockit/version.rb +5 -1
- data/lib/sockit.rb +46 -316
- data/sockit.gemspec +26 -16
- data/spec/sockit/sockit_spec.rb +211 -0
- data/spec/spec_helper.rb +43 -0
- data/spec/support/before_install.sh +33 -0
- data/spec/support/ss5-3.8.9-8.tar.gz +0 -0
- metadata +127 -37
- data/.rvmrc.template +0 -1
- data/bin/setup-travis-ci.sh +0 -11
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 50833e20c884206e0980ecc9f51dac27923f9576
|
4
|
+
data.tar.gz: 5655f2fb0c447475ebe9d917ee36cdb4ddb6a4fe
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f99c488283970a80aa8f78a4e33833e4de12d5aa771163fcc538a7618783e064e40b973aad0e1256e2c72836beb812bca327d808fa74815c06c9c521b7a9785a
|
7
|
+
data.tar.gz: 2a2c634c3dcc3ae1f82206229ca69aaafc93f7fb616de09855b696ca0b2575f82c2e7bbc7bb89cd65e893919ee47b29ad7c6c73c5bd053ad5883e873793ef330
|
data/.rspec
CHANGED
@@ -1 +1 @@
|
|
1
|
-
-c -b -fd
|
1
|
+
-c -b -fd --require spec_helper
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
sockit
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.3.0
|
data/.travis.yml
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
language: ruby
|
2
|
-
|
3
2
|
rvm:
|
4
|
-
-
|
5
|
-
-
|
6
|
-
-
|
7
|
-
- 1.9.3
|
8
|
-
|
3
|
+
- 2.0.0
|
4
|
+
- 2.2.4
|
5
|
+
- 2.3.0
|
9
6
|
branches:
|
10
7
|
only:
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
- master
|
9
|
+
before_install:
|
10
|
+
- "./spec/support/before_install.sh"
|
11
|
+
notifications:
|
12
|
+
irc:
|
13
|
+
channels:
|
14
|
+
- "irc.freenode.net#jovelabs"
|
15
|
+
use_notice: true
|
16
|
+
skip_join: true
|
data/.yardopts
ADDED
data/README.md
CHANGED
@@ -1,10 +1,19 @@
|
|
1
|
+
[](http://badge.fury.io/rb/sockit)
|
1
2
|
[](http://travis-ci.org/zpatten/sockit)
|
3
|
+
[](https://coveralls.io/r/zpatten/sockit)
|
2
4
|
[](https://gemnasium.com/zpatten/sockit)
|
3
5
|
[](https://codeclimate.com/github/zpatten/sockit)
|
4
6
|
|
5
7
|
# SOCKIT
|
6
8
|
|
7
|
-
Transparent SOCKS
|
9
|
+
Transparent SOCKS v4 and SOCKS v5 support for TCPSocket
|
10
|
+
|
11
|
+
Seamlessly route all TCP for you application through a SOCKS server with nearly zero effort. Once `require`'d and configured all traffic leveraging the `TCPSocket` class will route via your configured SOCKS server.
|
12
|
+
|
13
|
+
This is especially useful for many cases; here are a couple:
|
14
|
+
|
15
|
+
- Ensure all outbound traffic from your application appears from a single IP.
|
16
|
+
- Ensure development traffic does not give away private IP addresses.
|
8
17
|
|
9
18
|
## INSTALLATION
|
10
19
|
|
@@ -30,36 +39,36 @@ You can configure on the singleton class or an instance of the class. The SOCKS
|
|
30
39
|
|
31
40
|
The defaults are as follows:
|
32
41
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
42
|
+
Sockit.config do |config|
|
43
|
+
config.version = 5
|
44
|
+
config.ignore = ["127.0.0.1"]
|
45
|
+
config.debug = false
|
37
46
|
end
|
38
47
|
|
39
48
|
Specify your SOCKS server and port:
|
40
49
|
|
41
|
-
|
42
|
-
|
43
|
-
|
50
|
+
Sockit.config do |config|
|
51
|
+
config.host = "127.0.0.1"
|
52
|
+
config.port = "1080"
|
44
53
|
end
|
45
54
|
|
46
55
|
If you want to use username/password authentication:
|
47
56
|
|
48
|
-
|
49
|
-
|
50
|
-
|
57
|
+
Sockit.config do |config|
|
58
|
+
config.username = "username"
|
59
|
+
config.password = "password"
|
51
60
|
end
|
52
61
|
|
53
62
|
Turn on debug output:
|
54
63
|
|
55
|
-
|
56
|
-
|
64
|
+
Sockit.config do |config|
|
65
|
+
config.debug = true
|
57
66
|
end
|
58
67
|
|
59
68
|
Ignore some more hosts:
|
60
69
|
|
61
|
-
|
62
|
-
|
70
|
+
Sockit.config do |config|
|
71
|
+
config.ignore << "192.168.0.1"
|
63
72
|
end
|
64
73
|
|
65
74
|
|
@@ -85,7 +94,7 @@ Documentation:
|
|
85
94
|
|
86
95
|
SOCKIT - Transparent SOCKS 5 support for TCPSocket
|
87
96
|
|
88
|
-
* Author: Zachary Patten <zachary
|
97
|
+
* Author: Zachary Patten <zachary AT jovelabs DOT com> [](http://coderwall.com/zpatten)
|
89
98
|
* Copyright: Copyright (c) Zachary Patten
|
90
99
|
* License: Apache License, Version 2.0
|
91
100
|
|
data/bin/sockit
CHANGED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Sockit
|
2
|
+
module Connection
|
3
|
+
|
4
|
+
def direct_connect(socket, remote_host, remote_port, local_host=nil, local_port=nil)
|
5
|
+
log(:yellow, "Directly connecting to #{remote_host}:#{remote_port}")
|
6
|
+
socket.__send__(:initialize_tcp, remote_host, remote_port, local_host=nil, local_port=nil)
|
7
|
+
log(:green, "Connected to #{remote_host}:#{remote_port}")
|
8
|
+
end
|
9
|
+
|
10
|
+
def connect(socket, host, port)
|
11
|
+
log(:yellow, "Connecting to SOCKS v#{config.version} server #{config.host}:#{config.port}")
|
12
|
+
|
13
|
+
# when doing proxy mode on SS5; we seemingly need to resolve all names first.
|
14
|
+
if host !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/
|
15
|
+
host = Resolv::DNS.new.getaddress(host).to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
data = case config.version.to_i
|
19
|
+
when 4 then
|
20
|
+
build_v4_connection_request(host, port)
|
21
|
+
when 5 then
|
22
|
+
build_v5_connection_request(host, port)
|
23
|
+
end
|
24
|
+
data = data.flatten.join
|
25
|
+
|
26
|
+
log(:yellow, "Requesting SOCKS v#{config.version} connection to #{host}:#{port}")
|
27
|
+
dump(:write, data)
|
28
|
+
socket.write(data)
|
29
|
+
|
30
|
+
log(:yellow, "Waiting for SOCKS v#{config.version} connection reply")
|
31
|
+
host, port = case config.version.to_i
|
32
|
+
when 4 then
|
33
|
+
process_v4_connection_response(socket)
|
34
|
+
when 5 then
|
35
|
+
process_v5_connection_response(socket)
|
36
|
+
end
|
37
|
+
log(:green, [host, port].inspect)
|
38
|
+
|
39
|
+
log(:green, "Connected to #{host}:#{port} via SOCKS v#{config.version} server #{config.host}:#{config.port}")
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Sockit
|
2
|
+
module Support
|
3
|
+
|
4
|
+
def is_host_configured?
|
5
|
+
(!config.host.nil? && !config.host.empty?)
|
6
|
+
end
|
7
|
+
|
8
|
+
def is_port_configured?
|
9
|
+
(!config.port.nil? && !config.port.empty?)
|
10
|
+
end
|
11
|
+
|
12
|
+
def is_version_configured?
|
13
|
+
((config.version == 4) || (config.version == 5))
|
14
|
+
end
|
15
|
+
|
16
|
+
def is_configured?
|
17
|
+
(is_host_configured? && is_port_configured? && is_version_configured?)
|
18
|
+
end
|
19
|
+
|
20
|
+
def connect_via_socks?(host)
|
21
|
+
(is_configured? && !config.ignore.flatten.include?(host))
|
22
|
+
end
|
23
|
+
|
24
|
+
def is_socks_v5?
|
25
|
+
(is_configured? && config.version.to_i == 5)
|
26
|
+
end
|
27
|
+
|
28
|
+
def is_socks_v4?
|
29
|
+
(is_configured? && config.version.to_i == 4)
|
30
|
+
end
|
31
|
+
|
32
|
+
def log(color, message)
|
33
|
+
return if !config.debug
|
34
|
+
|
35
|
+
timestamp = Time.now.utc
|
36
|
+
puts("%s%s.%06d %s%s" % [COLORS[color], timestamp.strftime("%Y-%m-%d|%H:%M:%S"), timestamp.usec, message, COLORS[:reset]])
|
37
|
+
end
|
38
|
+
|
39
|
+
def dump(action, data)
|
40
|
+
return if !config.debug
|
41
|
+
|
42
|
+
bytes = Array.new
|
43
|
+
chars = Array.new
|
44
|
+
for x in 0..(data.length - 1) do
|
45
|
+
bytes << ("%03d" % data[x].ord)
|
46
|
+
chars << ("%03s" % (data[x] =~ /^\w+$/ ? data[x].chr : "..."))
|
47
|
+
end
|
48
|
+
log(:blue, "#{action.to_s.upcase}: #{bytes.join(" ")}#{COLORS[:reset]}")
|
49
|
+
log(:blue, "#{action.to_s.upcase}: #{chars.join(" ")}#{COLORS[:reset]}")
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Sockit
|
2
|
+
module V4
|
3
|
+
module Connection
|
4
|
+
|
5
|
+
# SOCKS v4 Client Connection Request
|
6
|
+
# field 1: SOCKS version number, 1 byte (must be 0x04 for this version)
|
7
|
+
# field 2: command code, 1 byte:
|
8
|
+
# 0x01 = establish a TCP/IP stream connection
|
9
|
+
# field 3: port number in a network byte order, 2 bytes
|
10
|
+
# field 4: destination address of
|
11
|
+
# 4 bytes for IPv4 address
|
12
|
+
# field 5: userid
|
13
|
+
# variables bytes for userid, null terminate (0x00)
|
14
|
+
def build_v4_connection_request(host, port)
|
15
|
+
data = Array.new
|
16
|
+
data << [config.version.to_i, 0x01].pack("C*")
|
17
|
+
|
18
|
+
data << [port.to_i].pack("n")
|
19
|
+
if host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/
|
20
|
+
data << [$1.to_i, $2.to_i, $3.to_i, $4.to_i].pack("C*")
|
21
|
+
end
|
22
|
+
data << config.username
|
23
|
+
data << [0x00].pack("C*")
|
24
|
+
|
25
|
+
data
|
26
|
+
end
|
27
|
+
|
28
|
+
# SOCKS v4 Server Connection Response
|
29
|
+
# field 1: version number, 1 byte (must be 0x00)
|
30
|
+
# field 2: result code, 1 byte:
|
31
|
+
# 90 = request granted
|
32
|
+
# 91 = request rejected or failed
|
33
|
+
# 92 = request rejected because SOCKS server can not connect to identd on the client
|
34
|
+
# 93 = request rejected because the client program and identd report different user-ids
|
35
|
+
# field 3: port number in a network byte order, 2 bytes
|
36
|
+
# field 4: destination address of
|
37
|
+
# 4 bytes for IPv4 address
|
38
|
+
def process_v4_connection_response(socket)
|
39
|
+
packet = socket.recv(2).unpack("C*")
|
40
|
+
dump(:read, packet)
|
41
|
+
version = packet[0]
|
42
|
+
result_code = packet[1]
|
43
|
+
|
44
|
+
case result_code
|
45
|
+
when 90 then
|
46
|
+
log(:green, build_v4_result_code_message(result_code))
|
47
|
+
else
|
48
|
+
raise SockitError, build_v4_result_code_message(result_code)
|
49
|
+
end
|
50
|
+
|
51
|
+
port = socket.recv(2).unpack("n")
|
52
|
+
dump(:read, port)
|
53
|
+
|
54
|
+
host = socket.recv(4).unpack("C*")
|
55
|
+
dump(:read, host)
|
56
|
+
|
57
|
+
[host.join('.'), port.join]
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Sockit
|
2
|
+
module V4
|
3
|
+
module Support
|
4
|
+
|
5
|
+
# 90 = request granted
|
6
|
+
# 91 = request rejected or failed
|
7
|
+
# 92 = request rejected because SOCKS server can not connect to identd on the client
|
8
|
+
# 93 = request rejected because the client program and identd report different user-ids
|
9
|
+
def build_v4_result_code_message(result_code)
|
10
|
+
message = case result_code
|
11
|
+
when 90 then
|
12
|
+
"Request granted"
|
13
|
+
when 91 then
|
14
|
+
"Request rejected or failed"
|
15
|
+
when 92 then
|
16
|
+
"Request rejected because SOCKS server can not connect to identd on the client"
|
17
|
+
when 93 then
|
18
|
+
"Request rejected because the client program and identd report different user-ids"
|
19
|
+
else
|
20
|
+
"Unknown"
|
21
|
+
end
|
22
|
+
|
23
|
+
"%s (Code: 0x%02X)" % [message, result_code]
|
24
|
+
|
25
|
+
rescue
|
26
|
+
"Result Code: #{result_code.inspect}"
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module Sockit
|
2
|
+
module V5
|
3
|
+
module Authentication
|
4
|
+
|
5
|
+
def perform_v5_authenticate(socket)
|
6
|
+
log(:yellow, "Authenticating with SOCKS server #{config.host}:#{config.port}")
|
7
|
+
|
8
|
+
# The authentication methods supported are numbered as follows:
|
9
|
+
# 0x00: No authentication
|
10
|
+
# 0x01: GSSAPI[10]
|
11
|
+
# 0x02: Username/Password[11]
|
12
|
+
# 0x03-0x7F: methods assigned by IANA[12]
|
13
|
+
# 0x80-0xFE: methods reserved for private use
|
14
|
+
|
15
|
+
# The initial greeting from the client is
|
16
|
+
# field 1: SOCKS version number (must be 0x05 for this version)
|
17
|
+
# field 2: number of authentication methods supported, 1 byte
|
18
|
+
# field 3: authentication methods, variable length, 1 byte per method supported
|
19
|
+
if (config.username || config.password)
|
20
|
+
data = Array.new
|
21
|
+
data << [config.version, 0x02, 0x02, 0x00].pack("C*")
|
22
|
+
data = data.flatten.join
|
23
|
+
|
24
|
+
log(:yellow, "Requesting username/password authentication")
|
25
|
+
dump(:write, data)
|
26
|
+
socket.write(data)
|
27
|
+
else
|
28
|
+
data = Array.new
|
29
|
+
data << [config.version, 0x01, 0x00].pack("C*")
|
30
|
+
data = data.flatten.join
|
31
|
+
|
32
|
+
log(:yellow, "Requesting no authentication")
|
33
|
+
dump(:write, data)
|
34
|
+
socket.write(data)
|
35
|
+
end
|
36
|
+
|
37
|
+
# The server's choice is communicated:
|
38
|
+
# field 1: SOCKS version, 1 byte (0x05 for this version)
|
39
|
+
# field 2: chosen authentication method, 1 byte, or 0xFF if no acceptable methods were offered
|
40
|
+
log(:yellow, "Waiting for SOCKS authentication reply")
|
41
|
+
auth_reply = socket.recv(2).unpack("C*")
|
42
|
+
dump(:read, auth_reply)
|
43
|
+
server_socks_version = auth_reply[0]
|
44
|
+
server_auth_method = auth_reply[1]
|
45
|
+
|
46
|
+
if server_socks_version != config.version
|
47
|
+
raise SockitError, "SOCKS server does not support version #{config.version}!"
|
48
|
+
end
|
49
|
+
|
50
|
+
if server_auth_method == 0xFF
|
51
|
+
raise SockitError, authentication_method(server_auth_method)
|
52
|
+
else
|
53
|
+
log(:green, authentication_method(server_auth_method))
|
54
|
+
end
|
55
|
+
|
56
|
+
# The subsequent authentication is method-dependent. Username and password authentication (method 0x02) is described in RFC 1929:
|
57
|
+
case server_auth_method
|
58
|
+
when 0x00 then
|
59
|
+
# No authentication
|
60
|
+
when 0x01 then
|
61
|
+
# GSSAPI
|
62
|
+
raise SockitError, "Authentication method GSSAPI not implemented"
|
63
|
+
when 0x02 then
|
64
|
+
# For username/password authentication the client's authentication request is
|
65
|
+
# field 1: version number, 1 byte (must be 0x01)
|
66
|
+
# field 2: username length, 1 byte
|
67
|
+
# field 3: username
|
68
|
+
# field 4: password length, 1 byte
|
69
|
+
# field 5: password
|
70
|
+
data = Array.new
|
71
|
+
data << [0x01].pack("C*")
|
72
|
+
data << [config.username.length.to_i].pack("C*")
|
73
|
+
data << config.username
|
74
|
+
data << [config.password.length.to_i].pack("C*")
|
75
|
+
data << config.password
|
76
|
+
data = data.flatten.join
|
77
|
+
|
78
|
+
log(:yellow, "Sending username and password")
|
79
|
+
dump(:write, data)
|
80
|
+
socket.write(data)
|
81
|
+
|
82
|
+
# Server response for username/password authentication:
|
83
|
+
# field 1: version, 1 byte
|
84
|
+
# field 2: status code, 1 byte.
|
85
|
+
# 0x00 = success
|
86
|
+
# any other value = failure, connection must be closed
|
87
|
+
log(:yellow, "Waiting for SOCKS authentication reply")
|
88
|
+
auth_reply = socket.recv(2).unpack("C*")
|
89
|
+
dump(:read, auth_reply)
|
90
|
+
version = auth_reply[0]
|
91
|
+
status_code = auth_reply[1]
|
92
|
+
|
93
|
+
if status_code == 0x00
|
94
|
+
log(:green, authentication_status(status_code))
|
95
|
+
else
|
96
|
+
raise SockitError, authentication_status(status_code)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
log(:green, "Authenticated to SOCKS server #{config.host}:#{config.port}")
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module Sockit
|
2
|
+
module V5
|
3
|
+
module Connection
|
4
|
+
|
5
|
+
# SOCKS v5 Client Connection Request
|
6
|
+
# field 1: SOCKS version number, 1 byte (must be 0x05 for this version)
|
7
|
+
# field 2: command code, 1 byte:
|
8
|
+
# 0x01 = establish a TCP/IP stream connection
|
9
|
+
# 0x02 = establish a TCP/IP port binding
|
10
|
+
# 0x03 = associate a UDP port
|
11
|
+
# field 3: reserved, must be 0x00
|
12
|
+
# field 4: address type, 1 byte:
|
13
|
+
# 0x01 = IPv4 address
|
14
|
+
# 0x03 = Domain name
|
15
|
+
# 0x04 = IPv6 address
|
16
|
+
# field 5: destination address of
|
17
|
+
# 4 bytes for IPv4 address
|
18
|
+
# 1 byte of name length followed by the name for Domain name
|
19
|
+
# 16 bytes for IPv6 address
|
20
|
+
# field 6: port number in a network byte order, 2 bytes
|
21
|
+
def build_v5_connection_request(host, port)
|
22
|
+
data = Array.new
|
23
|
+
data << [config.version.to_i, 0x01, 0x00].pack("C*")
|
24
|
+
|
25
|
+
if host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/
|
26
|
+
data << [0x01].pack("C*")
|
27
|
+
data << [$1.to_i, $2.to_i, $3.to_i, $4.to_i].pack("C*")
|
28
|
+
elsif host =~ /^[:0-9a-f]+$/
|
29
|
+
data << [0x04].pack("C*")
|
30
|
+
data << [$1].pack("C*")
|
31
|
+
else
|
32
|
+
data << [0x03].pack("C*")
|
33
|
+
data << [host.length.to_i].pack("C*")
|
34
|
+
data << host
|
35
|
+
end
|
36
|
+
data << [port.to_i].pack("n")
|
37
|
+
|
38
|
+
data
|
39
|
+
end
|
40
|
+
|
41
|
+
# SOCKS v5 Server Connection Response
|
42
|
+
# field 1: SOCKS protocol version, 1 byte (0x05 for this version)
|
43
|
+
# field 2: status, 1 byte:
|
44
|
+
# 0x00 = request granted
|
45
|
+
# 0x01 = general failure
|
46
|
+
# 0x02 = connection not allowed by ruleset
|
47
|
+
# 0x03 = network unreachable
|
48
|
+
# 0x04 = host unreachable
|
49
|
+
# 0x05 = connection refused by destination host
|
50
|
+
# 0x06 = TTL expired
|
51
|
+
# 0x07 = command not supported / protocol error
|
52
|
+
# 0x08 = address type not supported
|
53
|
+
# field 3: reserved, must be 0x00
|
54
|
+
# field 4: address type, 1 byte:
|
55
|
+
# 0x01 = IPv4 address
|
56
|
+
# 0x03 = Domain name
|
57
|
+
# 0x04 = IPv6 address
|
58
|
+
# field 5: destination address of
|
59
|
+
# 4 bytes for IPv4 address
|
60
|
+
# 1 byte of name length followed by the name for Domain name
|
61
|
+
# 16 bytes for IPv6 address
|
62
|
+
# field 6: network byte order port number, 2 bytes
|
63
|
+
def process_v5_connection_response(socket)
|
64
|
+
packet = socket.recv(4).unpack("C*")
|
65
|
+
dump(:read, packet)
|
66
|
+
socks_version = packet[0]
|
67
|
+
result_code = packet[1]
|
68
|
+
reserved = packet[2]
|
69
|
+
address_type = packet[3]
|
70
|
+
|
71
|
+
if result_code == 0x00
|
72
|
+
log(:green, build_v5_result_code_message(result_code))
|
73
|
+
else
|
74
|
+
raise SockitError, build_v5_result_code_message(result_code)
|
75
|
+
end
|
76
|
+
|
77
|
+
address_length = case address_type
|
78
|
+
when 0x01 then
|
79
|
+
4
|
80
|
+
when 0x03 then
|
81
|
+
data = socket.recv(1).unpack("C*")
|
82
|
+
dump(:read, data)
|
83
|
+
data[0]
|
84
|
+
when 0x04 then
|
85
|
+
16
|
86
|
+
end
|
87
|
+
host = socket.recv(address_length).unpack("C*")
|
88
|
+
dump(:read, host)
|
89
|
+
|
90
|
+
port = socket.recv(2).unpack("n")
|
91
|
+
dump(:read, port)
|
92
|
+
|
93
|
+
[host.join('.'), port.join]
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Sockit
|
2
|
+
module V5
|
3
|
+
module Support
|
4
|
+
|
5
|
+
# 0x00 = request granted
|
6
|
+
# 0x01 = general failure
|
7
|
+
# 0x02 = connection not allowed by ruleset
|
8
|
+
# 0x03 = network unreachable
|
9
|
+
# 0x04 = host unreachable
|
10
|
+
# 0x05 = connection refused by destination host
|
11
|
+
# 0x06 = TTL expired
|
12
|
+
# 0x07 = command not supported / protocol error
|
13
|
+
# 0x08 = address type not supported
|
14
|
+
def build_v5_result_code_message(result_code)
|
15
|
+
message = case result_code
|
16
|
+
when 0x00 then
|
17
|
+
"Request granted"
|
18
|
+
when 0x01 then
|
19
|
+
"General failure"
|
20
|
+
when 0x02 then
|
21
|
+
"Connection not allowed by ruleset"
|
22
|
+
when 0x03 then
|
23
|
+
"Network unreachable"
|
24
|
+
when 0x04 then
|
25
|
+
"Host unreachable"
|
26
|
+
when 0x05 then
|
27
|
+
"Connection refused by destination host"
|
28
|
+
when 0x06 then
|
29
|
+
"TTL expired"
|
30
|
+
when 0x07 then
|
31
|
+
"Command not supported / Protocol error"
|
32
|
+
when 0x08 then
|
33
|
+
"Address type not supported"
|
34
|
+
else
|
35
|
+
"Unknown"
|
36
|
+
end
|
37
|
+
|
38
|
+
"%s (Code: 0x%02X)" % [message, result_code]
|
39
|
+
|
40
|
+
rescue
|
41
|
+
"Result Code: #{result_code.inspect}"
|
42
|
+
end
|
43
|
+
|
44
|
+
# The authentication methods supported are numbered as follows:
|
45
|
+
# 0x00: No authentication
|
46
|
+
# 0x01: GSSAPI[10]
|
47
|
+
# 0x02: Username/Password[11]
|
48
|
+
# 0x03-0x7F: methods assigned by IANA[12]
|
49
|
+
# 0x80-0xFE: methods reserved for private use
|
50
|
+
def authentication_method(auth_method)
|
51
|
+
case auth_method
|
52
|
+
when 0x00 then
|
53
|
+
"No authentication (Code: 0x%02X)" % auth_method
|
54
|
+
when 0x01 then
|
55
|
+
"GSSAPI authentication (Code: 0x%02X)" % auth_method
|
56
|
+
when 0x02 then
|
57
|
+
"Username/Password authentication (Code: 0x%02X)" % auth_method
|
58
|
+
when 0x03..0x7F then
|
59
|
+
"Authentication method assigned by IANA (Code: 0x%02X)" % auth_method
|
60
|
+
when 0x80..0xFE then
|
61
|
+
"Authentication method reserved for private use (Code: 0x%02X)" % auth_method
|
62
|
+
when 0xFF then
|
63
|
+
"Unsupported authentication (Code: 0x%02X)" % auth_method
|
64
|
+
else
|
65
|
+
"Unknown authentication (Code: 0x%02X)" % auth_method
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# 0x00 = success
|
70
|
+
# any other value = failure, connection must be closed
|
71
|
+
def authentication_status(auth_status)
|
72
|
+
case auth_status
|
73
|
+
when 0x00 then
|
74
|
+
"Authentication success (Code: 0x%02X)" % auth_status
|
75
|
+
else
|
76
|
+
"Authentication failure (Code: 0x%02X)" % auth_status
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/sockit/version.rb
CHANGED