shadowsocks 0.3 → 0.4
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 +4 -4
- data/README.md +4 -2
- data/config.json +2 -1
- data/lib/shadowsocks.rb +1 -0
- data/lib/shadowsocks/cli.rb +15 -3
- data/lib/shadowsocks/config.rb +4 -2
- data/lib/shadowsocks/connection.rb +10 -0
- data/lib/shadowsocks/crypto.rb +133 -0
- data/lib/shadowsocks/listener.rb +1 -3
- data/lib/shadowsocks/local.rb +5 -5
- data/lib/shadowsocks/server.rb +3 -3
- data/lib/shadowsocks/table.rb +2 -2
- data/lib/shadowsocks/tunnel.rb +3 -7
- data/lib/shadowsocks/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e13759da84263a5a81769afcb8e2d99b511766b
|
4
|
+
data.tar.gz: 9f0049ec6920bc351fc0c04017f22dbfd2cf8104
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44a5fb86332bcbdadc27978a6dcebc2f8f215b8cb7daed472d4b84763d63dfdf1b2740136490bda9fa2c5be6385cf1f1c3c736c187d820eb620869b139e44606
|
7
|
+
data.tar.gz: 9d8ae8792552c49c434b2ee6abf4ca323e81e09c4d6bae01464a0afcb28dd254f5be834915d4695cba575350d6d3d0cb961bb4e3cd3cb6eec699ee5bddd1b0f8
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@ shadowsocks-ruby
|
|
3
3
|
|
4
4
|
[](https://codeclimate.com/repos/524baea6c7f3a37df208dd4c/feed)
|
5
5
|
|
6
|
-
Current version: 0.
|
6
|
+
Current version: 0.4
|
7
7
|
|
8
8
|
shadowsocks-ruby is a lightweight tunnel proxy which can help you get through firewalls. It is a port of [shadowsocks](https://github.com/clowwindy/shadowsocks).
|
9
9
|
|
@@ -26,7 +26,8 @@ Create a file named `config.json`, with the following content.
|
|
26
26
|
"server_port":8388,
|
27
27
|
"local_port":1080,
|
28
28
|
"password":"barfoo!",
|
29
|
-
"timeout":
|
29
|
+
"timeout":60,
|
30
|
+
"method":"aes-256-cfb"
|
30
31
|
}
|
31
32
|
|
32
33
|
Explanation of the fields:
|
@@ -36,6 +37,7 @@ Explanation of the fields:
|
|
36
37
|
local_port local port
|
37
38
|
password a password used to encrypt transfer
|
38
39
|
timeout in seconds
|
40
|
+
method encryption method, "bf-cfb", "aes-256-cfb", "des-cfb", "rc4", etc. Default is aes-256-cfb
|
39
41
|
|
40
42
|
`cd` into the directory of `config.json`. Run `ss-server` on your server. To run it in the background, run
|
41
43
|
`nohup ss-server -c ./config.json > log &`.
|
data/config.json
CHANGED
data/lib/shadowsocks.rb
CHANGED
data/lib/shadowsocks/cli.rb
CHANGED
@@ -7,12 +7,24 @@ module Shadowsocks
|
|
7
7
|
class Cli
|
8
8
|
include ::Shadowsocks::Table
|
9
9
|
|
10
|
-
attr_accessor :side, :args, :config
|
10
|
+
attr_accessor :side, :args, :config
|
11
11
|
|
12
12
|
def initialize(options)
|
13
13
|
@side = options[:side]
|
14
14
|
@config = options[:config]
|
15
|
-
|
15
|
+
|
16
|
+
@method_options = {
|
17
|
+
method: config.method,
|
18
|
+
password: config.password
|
19
|
+
}
|
20
|
+
|
21
|
+
if @config.method == 'table'
|
22
|
+
table = get_table(config.password)
|
23
|
+
@method_options.merge!(
|
24
|
+
encrypt_table: table[:encrypt],
|
25
|
+
decrypt_table: table[:decrypt]
|
26
|
+
)
|
27
|
+
end
|
16
28
|
end
|
17
29
|
|
18
30
|
def run
|
@@ -43,7 +55,7 @@ module Shadowsocks
|
|
43
55
|
|
44
56
|
def initialize_connection connection
|
45
57
|
connection.config = @config
|
46
|
-
connection.
|
58
|
+
connection.crypto = Shadowsocks::Crypto.new @method_options
|
47
59
|
connection.pending_connect_timeout = @config.timeout
|
48
60
|
end
|
49
61
|
|
data/lib/shadowsocks/config.rb
CHANGED
@@ -2,7 +2,7 @@ require 'json'
|
|
2
2
|
|
3
3
|
module Shadowsocks
|
4
4
|
class Config
|
5
|
-
attr_reader :args, :server, :server_port, :local_port, :password, :timeout, :config_path
|
5
|
+
attr_reader :args, :server, :server_port, :local_port, :password, :timeout, :method, :config_path
|
6
6
|
|
7
7
|
def initialize(_args)
|
8
8
|
@args = _args || []
|
@@ -22,6 +22,7 @@ module Shadowsocks
|
|
22
22
|
@server_port = json["server_port"].to_i if @server_port.nil?
|
23
23
|
@local_port = json["local_port"].to_i if @local_port.nil?
|
24
24
|
@timeout = json["timeout"].to_i if @timeout.nil?
|
25
|
+
@method = json["method"] if @method.nil?
|
25
26
|
end
|
26
27
|
|
27
28
|
private
|
@@ -37,7 +38,8 @@ module Shadowsocks
|
|
37
38
|
opts.on("-k", "--password PASSWORD", "Password, should be same in client and server sides") { |c| @password = c }
|
38
39
|
opts.on("-c", "--config PATH", "config.json path") { |c| @config_path = c }
|
39
40
|
opts.on("-p", "--port PORT", Integer, "Remote server port") { |c| @server_port = c }
|
40
|
-
opts.on("-l", "--local_port PORT", Integer,"Local client port")
|
41
|
+
opts.on("-l", "--local_port PORT", Integer, "Local client port") { |c| @local_port = c }
|
42
|
+
opts.on("-m", "--method METHOD", Integer, "Encryption method") { |c| @method = c }
|
41
43
|
opts.on("-t", "--timeout NUMBER", Integer, "connection timeout") { |c| @timeout = c }
|
42
44
|
|
43
45
|
opts.on_tail("-v", "--version", "Show shadowsocks gem version") { puts Shadowsocks::VERSION; exit }
|
@@ -2,8 +2,18 @@ module Shadowsocks
|
|
2
2
|
class Connection < EventMachine::Connection
|
3
3
|
BackpressureLevel = 2097152 # 2m
|
4
4
|
|
5
|
+
attr_accessor :crypto
|
6
|
+
|
5
7
|
private
|
6
8
|
|
9
|
+
def encrypt(buf)
|
10
|
+
crypto.encrypt(buf)
|
11
|
+
end
|
12
|
+
|
13
|
+
def decrypt(buf)
|
14
|
+
crypto.decrypt(buf)
|
15
|
+
end
|
16
|
+
|
7
17
|
def over_pressure?
|
8
18
|
remote.get_outbound_data_size > BackpressureLevel
|
9
19
|
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'openssl'
|
3
|
+
require 'digest/md5'
|
4
|
+
|
5
|
+
module Shadowsocks
|
6
|
+
class Crypto
|
7
|
+
include ::Shadowsocks::Table
|
8
|
+
|
9
|
+
attr_accessor :encrypt_table, :decrypt_table, :password, :method,
|
10
|
+
:cipher, :bytes_to_key_results, :iv_sent
|
11
|
+
|
12
|
+
def method_supported
|
13
|
+
case method
|
14
|
+
when 'aes-128-cfb' then [16, 16]
|
15
|
+
when 'aes-192-cfb' then [24, 16]
|
16
|
+
when 'aes-256-cfb' then [32, 16]
|
17
|
+
when 'bf-cfb' then [16, 8 ]
|
18
|
+
when 'camellia-128-cfb' then [16, 16]
|
19
|
+
when 'camellia-192-cfb' then [24, 16]
|
20
|
+
when 'camellia-256-cfb' then [32, 16]
|
21
|
+
when 'cast5-cfb' then [16, 8 ]
|
22
|
+
when 'des-cfb' then [8, 8 ]
|
23
|
+
when 'idea-cfb' then [16, 8 ]
|
24
|
+
when 'rc2-cfb' then [16, 8 ]
|
25
|
+
when 'rc4' then [16, 0 ]
|
26
|
+
when 'seed-cfb' then [16, 16]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
alias_method :get_cipher_len, :method_supported
|
30
|
+
|
31
|
+
def initialize(options = {})
|
32
|
+
@password = options[:password]
|
33
|
+
@method = options[:method].downcase
|
34
|
+
@iv_sent = false
|
35
|
+
if method == 'table'
|
36
|
+
@encrypt_table = options[:encrypt_table]
|
37
|
+
@decrypt_table = options[:decrypt_table]
|
38
|
+
else
|
39
|
+
if method_supported.nil?
|
40
|
+
raise "Encrypt method not support"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
if method != 'table'
|
45
|
+
@cipher = get_cipher(1, SecureRandom.hex(32))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def encrypt buf
|
50
|
+
return buf if buf.length == 0
|
51
|
+
if method == 'table'
|
52
|
+
translate @encrypt_table, buf
|
53
|
+
else
|
54
|
+
if iv_sent
|
55
|
+
@cipher.update(buf)
|
56
|
+
else
|
57
|
+
@iv_sent = true
|
58
|
+
@cipher_iv + @cipher.update(buf)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def decrypt buf
|
64
|
+
return buf if buf.length == 0
|
65
|
+
if method == 'table'
|
66
|
+
translate @decrypt_table, buf
|
67
|
+
else
|
68
|
+
if @decipher.nil?
|
69
|
+
decipher_iv_len = get_cipher_len[1]
|
70
|
+
decipher_iv = buf[0..decipher_iv_len ]
|
71
|
+
@iv = decipher_iv
|
72
|
+
@decipher = get_cipher(0, @iv)
|
73
|
+
buf = buf[decipher_iv_len..-1]
|
74
|
+
return buf if buf.length == 0
|
75
|
+
end
|
76
|
+
@decipher.update(buf)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def iv_len
|
83
|
+
@cipher_iv.length
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_cipher(op, iv)
|
87
|
+
m = get_cipher_len
|
88
|
+
unless m.nil?
|
89
|
+
key, _iv = EVP_BytesToKey(m[0], m[1])
|
90
|
+
|
91
|
+
iv = _iv[0..m[1] - 1]
|
92
|
+
@iv = iv unless @iv
|
93
|
+
@cipher_iv = iv if op == 1
|
94
|
+
|
95
|
+
cipher = OpenSSL::Cipher.new method
|
96
|
+
|
97
|
+
op == 1 ? cipher.encrypt : cipher.decrypt
|
98
|
+
|
99
|
+
cipher.key = key
|
100
|
+
cipher.iv = @iv
|
101
|
+
cipher
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def EVP_BytesToKey key_len, iv_len
|
106
|
+
if bytes_to_key_results
|
107
|
+
return bytes_to_key_results
|
108
|
+
end
|
109
|
+
|
110
|
+
m = []
|
111
|
+
i = 0
|
112
|
+
|
113
|
+
len = key_len + iv_len
|
114
|
+
|
115
|
+
code = password.unpack('H*').first
|
116
|
+
|
117
|
+
while m.join.length < len do
|
118
|
+
data = if i > 0
|
119
|
+
m[i - 1] + password
|
120
|
+
else
|
121
|
+
password
|
122
|
+
end
|
123
|
+
m.push Digest::MD5.digest data
|
124
|
+
i += 1
|
125
|
+
end
|
126
|
+
ms = m.join
|
127
|
+
key = ms[0, key_len]
|
128
|
+
iv = ms[key_len, key_len + iv_len]
|
129
|
+
bytes_to_key_results = [key, iv]
|
130
|
+
bytes_to_key_results
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
data/lib/shadowsocks/listener.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
module Shadowsocks
|
2
2
|
class Listener < ::Shadowsocks::Connection
|
3
|
-
include ::Shadowsocks::Table
|
4
|
-
|
5
3
|
attr_accessor :stage, :remote_addr, :remote_port, :addr_to_send, :cached_pieces,
|
6
|
-
:header_length, :connector, :config
|
4
|
+
:header_length, :connector, :config
|
7
5
|
|
8
6
|
def receive_data data
|
9
7
|
data_handler data
|
data/lib/shadowsocks/local.rb
CHANGED
@@ -5,15 +5,15 @@ module Shadowsocks
|
|
5
5
|
p "connecting #{server.remote_addr[3..-1]} via #{server.config.server}"
|
6
6
|
addr_to_send = server.addr_to_send.clone
|
7
7
|
|
8
|
-
send_data encrypt(
|
9
|
-
server.cached_pieces.each { |piece| send_data encrypt(
|
8
|
+
send_data encrypt(addr_to_send)
|
9
|
+
server.cached_pieces.each { |piece| send_data encrypt(piece) }
|
10
10
|
server.cached_pieces = []
|
11
11
|
|
12
12
|
server.stage = 5
|
13
13
|
end
|
14
14
|
|
15
15
|
def receive_data data
|
16
|
-
server.send_data
|
16
|
+
server.send_data decrypt(data)
|
17
17
|
outbound_checker
|
18
18
|
end
|
19
19
|
end
|
@@ -31,7 +31,7 @@ module Shadowsocks
|
|
31
31
|
when 4
|
32
32
|
cached_pieces.push data
|
33
33
|
when 5
|
34
|
-
connector.send_data(encrypt(
|
34
|
+
connector.send_data(encrypt(data)) and return
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -49,7 +49,7 @@ module Shadowsocks
|
|
49
49
|
send_data "\x05\x00\x00\x01\x00\x00\x00\x00" + [config.server_port].pack('s>')
|
50
50
|
|
51
51
|
@stage = 4
|
52
|
-
@connector = EventMachine.connect config.server, config.server_port, ServerConnector, self,
|
52
|
+
@connector = EventMachine.connect config.server, config.server_port, ServerConnector, self, crypto
|
53
53
|
|
54
54
|
if data.size > header_length
|
55
55
|
cached_pieces.push data[header_length, data.size]
|
data/lib/shadowsocks/server.rb
CHANGED
@@ -11,7 +11,7 @@ module Shadowsocks
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def receive_data data
|
14
|
-
server.send_data encrypt(
|
14
|
+
server.send_data encrypt(data)
|
15
15
|
outbound_checker
|
16
16
|
end
|
17
17
|
end
|
@@ -20,7 +20,7 @@ module Shadowsocks
|
|
20
20
|
private
|
21
21
|
|
22
22
|
def data_handler data
|
23
|
-
data =
|
23
|
+
data = decrypt data
|
24
24
|
case stage
|
25
25
|
when 0
|
26
26
|
fireup_tunnel data
|
@@ -41,7 +41,7 @@ module Shadowsocks
|
|
41
41
|
cached_pieces.push data[header_length, data.size]
|
42
42
|
end
|
43
43
|
|
44
|
-
@connector = EventMachine.connect @remote_addr, @remote_port, RequestConnector, self,
|
44
|
+
@connector = EventMachine.connect @remote_addr, @remote_port, RequestConnector, self, crypto
|
45
45
|
rescue Exception => e
|
46
46
|
warn e
|
47
47
|
connection_cleanup
|
data/lib/shadowsocks/table.rb
CHANGED
@@ -45,10 +45,10 @@ module Shadowsocks
|
|
45
45
|
decrypt_table[table[i]] = i
|
46
46
|
i += 1
|
47
47
|
end
|
48
|
-
{
|
48
|
+
{ encrypt: table, decrypt: decrypt_table }
|
49
49
|
end
|
50
50
|
|
51
|
-
def
|
51
|
+
def translate(table, buf)
|
52
52
|
table_ptr = FFI::MemoryPointer.new(:int, table.length)
|
53
53
|
table_ptr.put_array_of_int32(0, table)
|
54
54
|
|
data/lib/shadowsocks/tunnel.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
module Shadowsocks
|
2
2
|
class Tunnel < ::Shadowsocks::Connection
|
3
|
-
attr_accessor :server
|
3
|
+
attr_accessor :server
|
4
4
|
|
5
|
-
def initialize server,
|
5
|
+
def initialize server, crypto
|
6
6
|
@server = server
|
7
|
-
@
|
7
|
+
@crypto = crypto
|
8
8
|
super
|
9
9
|
end
|
10
10
|
|
@@ -15,9 +15,5 @@ module Shadowsocks
|
|
15
15
|
def remote
|
16
16
|
server
|
17
17
|
end
|
18
|
-
|
19
|
-
def encrypt table, data
|
20
|
-
server.encrypt table, data
|
21
|
-
end
|
22
18
|
end
|
23
19
|
end
|
data/lib/shadowsocks/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shadowsocks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.4'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sen
|
@@ -118,6 +118,7 @@ files:
|
|
118
118
|
- lib/shadowsocks/cli.rb
|
119
119
|
- lib/shadowsocks/config.rb
|
120
120
|
- lib/shadowsocks/connection.rb
|
121
|
+
- lib/shadowsocks/crypto.rb
|
121
122
|
- lib/shadowsocks/listener.rb
|
122
123
|
- lib/shadowsocks/local.rb
|
123
124
|
- lib/shadowsocks/server.rb
|