sockit 0.0.4 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/sockit.png)](http://badge.fury.io/rb/sockit)
|
1
2
|
[![Build Status](https://secure.travis-ci.org/zpatten/sockit.png)](http://travis-ci.org/zpatten/sockit)
|
3
|
+
[![Coverage Status](https://coveralls.io/repos/zpatten/sockit/badge.png?branch=master)](https://coveralls.io/r/zpatten/sockit)
|
2
4
|
[![Dependency Status](https://gemnasium.com/zpatten/sockit.png)](https://gemnasium.com/zpatten/sockit)
|
3
5
|
[![Code Climate](https://codeclimate.com/github/zpatten/sockit.png)](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> [![endorse](http://api.coderwall.com/zpatten/endorsecount.png)](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