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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 210530027df71869738df356d97c6d3155592ab9
4
- data.tar.gz: 8a45ea79d7cfe255af4f1926dd26eb9b7c4f3328
3
+ metadata.gz: 1e13759da84263a5a81769afcb8e2d99b511766b
4
+ data.tar.gz: 9f0049ec6920bc351fc0c04017f22dbfd2cf8104
5
5
  SHA512:
6
- metadata.gz: 78fe95f2a08447581d78d6b2f6e31cf5ef9ca60fd5d27e722949b0f3a50070166cf6ac316a092e4c21f655168a2168e091c5b9ba365e807afa19b12ee99a8ce7
7
- data.tar.gz: 73b565053f9dbee59d094485e68797e0e740475e4ccd56739f8df62f15b12f7c096e484b6b33aa11ae11e0709762f31f03a73980d6b15240c2172b732e80800c
6
+ metadata.gz: 44a5fb86332bcbdadc27978a6dcebc2f8f215b8cb7daed472d4b84763d63dfdf1b2740136490bda9fa2c5be6385cf1f1c3c736c187d820eb620869b139e44606
7
+ data.tar.gz: 9d8ae8792552c49c434b2ee6abf4ca323e81e09c4d6bae01464a0afcb28dd254f5be834915d4695cba575350d6d3d0cb961bb4e3cd3cb6eec699ee5bddd1b0f8
data/README.md CHANGED
@@ -3,7 +3,7 @@ shadowsocks-ruby
3
3
 
4
4
  [![Code Climate](https://codeclimate.com/repos/524baea6c7f3a37df208dd4c/badges/9dd6c11b6a17c3a55631/gpa.png)](https://codeclimate.com/repos/524baea6c7f3a37df208dd4c/feed)
5
5
 
6
- Current version: 0.2
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":600
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
@@ -3,5 +3,6 @@
3
3
  "server_port":8388,
4
4
  "local_port":1080,
5
5
  "password":"barfoo!",
6
- "timeout":60
6
+ "timeout":60,
7
+ "method":"aes-256-cfb"
7
8
  }
data/lib/shadowsocks.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'eventmachine'
2
2
 
3
3
  module Shadowsocks
4
+ autoload :Crypto, 'shadowsocks/crypto'
4
5
  autoload :Connection, 'shadowsocks/connection'
5
6
  autoload :Server, 'shadowsocks/server'
6
7
  autoload :Local, 'shadowsocks/local'
@@ -7,12 +7,24 @@ module Shadowsocks
7
7
  class Cli
8
8
  include ::Shadowsocks::Table
9
9
 
10
- attr_accessor :side, :args, :config, :table
10
+ attr_accessor :side, :args, :config
11
11
 
12
12
  def initialize(options)
13
13
  @side = options[:side]
14
14
  @config = options[:config]
15
- @table = get_table(config.password)
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.table = @table
58
+ connection.crypto = Shadowsocks::Crypto.new @method_options
47
59
  connection.pending_connect_timeout = @config.timeout
48
60
  end
49
61
 
@@ -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") { |c| @local_port = c }
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
@@ -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, :table
4
+ :header_length, :connector, :config
7
5
 
8
6
  def receive_data data
9
7
  data_handler data
@@ -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(table[:encrypt_table], addr_to_send)
9
- server.cached_pieces.each { |piece| send_data encrypt(table[:encrypt_table], piece) }
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 encrypt(table[:decrypt_table], 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(table[:encrypt_table], data)) and return
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, @table
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]
@@ -11,7 +11,7 @@ module Shadowsocks
11
11
  end
12
12
 
13
13
  def receive_data data
14
- server.send_data encrypt(table[:encrypt_table], data)
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 = encrypt table[:decrypt_table], 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, table
44
+ @connector = EventMachine.connect @remote_addr, @remote_port, RequestConnector, self, crypto
45
45
  rescue Exception => e
46
46
  warn e
47
47
  connection_cleanup
@@ -45,10 +45,10 @@ module Shadowsocks
45
45
  decrypt_table[table[i]] = i
46
46
  i += 1
47
47
  end
48
- { encrypt_table: table, decrypt_table: decrypt_table }
48
+ { encrypt: table, decrypt: decrypt_table }
49
49
  end
50
50
 
51
- def encrypt (table, buf)
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
 
@@ -1,10 +1,10 @@
1
1
  module Shadowsocks
2
2
  class Tunnel < ::Shadowsocks::Connection
3
- attr_accessor :server, :table
3
+ attr_accessor :server
4
4
 
5
- def initialize server, table
5
+ def initialize server, crypto
6
6
  @server = server
7
- @table = table
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
@@ -1,3 +1,3 @@
1
1
  module Shadowsocks
2
- VERSION = '0.3'
2
+ VERSION = '0.4'
3
3
  end
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.3'
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