dcase 0.2

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3d798b7687187ae48822a7697be6f6481ec5147d
4
+ data.tar.gz: a216c5043444fa4cd375af0f16a1724d76eade1e
5
+ SHA512:
6
+ metadata.gz: 75fb759cf33a02d4bf5a13b11a003d75b0462b4b212f4bab0bd757e3222002519dd9e5c3ded0a72f889f77577bac5d1b17c98dde02ee1ea0bc95cfc0d916cb16
7
+ data.tar.gz: e5950388fe64ac83e88a81d00168a42e64cc251b9541d6c5e6c07a416c3e1a777812e9bee040489fef37cd1fa92598144cfab2076abcd2044d1ce4ba15f369e6
@@ -0,0 +1,25 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+
20
+ *.so
21
+ *.bundle
22
+ *.o
23
+ .DS_Store
24
+ Gemfile.lock
25
+ run
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ group :development, :test do
4
+ gem "minitest", '~> 5.2.2'
5
+ end
6
+
7
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Sen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,54 @@
1
+ DCase
2
+ =====
3
+
4
+ Current version: 0.2
5
+
6
+ DCase is a lightweight dns proxy which can help you get through firewalls.
7
+
8
+ Usage
9
+ -----------
10
+
11
+ First, make sure you have Ruby 2.0.
12
+
13
+ $ ruby -v
14
+ ruby 2.0.0p353
15
+
16
+ Install Shadowsocks.
17
+
18
+ gem install dcase
19
+
20
+ Create a file named `config.yml`, with the following content.
21
+
22
+ side: 'local or server'
23
+ password: 'your password'
24
+ port: '8440'
25
+ # you don't need this line when it's on server side
26
+ server: 'remote server address'
27
+
28
+ Explanation of the fields:
29
+
30
+ side Local or Server side
31
+ server Remote server address
32
+ port Remote server port
33
+ password Password, should be same in client and server sides
34
+
35
+ `cd` into the directory of `config.yml`. Run `dcase` on your server. To run it in the background, run
36
+ `nohup dcase -c ./config.yml > log &`.
37
+
38
+ On your client machine, `cd` into the directory of `config.yml` also, run `sudo dcase -c config.yml`.
39
+
40
+ Command line args
41
+ ------------------
42
+
43
+ You can use args to override settings from `config.json`.
44
+
45
+ sudo dcase -s local -r remote_server_ip_address -p remote_server_port -k your_password
46
+ sudo dcase -s server -p remote_server_port -k your_password
47
+
48
+ License
49
+ -------
50
+ MIT
51
+
52
+ Bugs and Issues
53
+ ----------------
54
+ Please visit [issue tracker](https://github.com/Sen/DCase/issues?state=open)
@@ -0,0 +1,12 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+
5
+ # Load custom tasks
6
+ Dir['tasks/*.rake'].sort.each { |f| load f }
7
+
8
+ Rake::TestTask.new do |task|
9
+ task.libs << 'test'
10
+ end
11
+
12
+ task :default => :test
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
5
+
6
+ require 'dcase'
7
+ require 'dcase/cli'
8
+ require 'dcase/config'
9
+
10
+ begin
11
+ config = DCase::Config.new ARGV
12
+ cli = DCase::Cli.new({config: config})
13
+ cli.run
14
+ rescue => e
15
+ raise e if $DEBUG
16
+ STDERR.puts e.message
17
+ STDERR.puts e.backtrace.join("\n")
18
+ exit 1
19
+ end
20
+
@@ -0,0 +1,3 @@
1
+ password: 'your password'
2
+ port: '8440'
3
+ server: '127.0.0.1'
@@ -0,0 +1,25 @@
1
+ require File.expand_path('../lib/dcase/version', __FILE__)
2
+ require 'date'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'dcase'
6
+ s.version = DCase::VERSION
7
+ s.date = Date.today
8
+ s.summary = "a secure dns proxy"
9
+ s.description = "DCase is a lightweight dns proxy which can help you get through firewalls."
10
+ s.authors = ["Sen"]
11
+ s.email = 'sen9ob@gmail.com'
12
+ s.files = `git ls-files`.split("\n")
13
+ s.test_files = `git ls-files -- test/{functional,unit}/*`.split("\n")
14
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
15
+ s.homepage = 'https://github.com/Sen/DCase'
16
+ s.license = 'MIT'
17
+ s.extensions = %w[ext/encrypt/extconf.rb]
18
+
19
+ s.add_dependency "celluloid-io", "~> 0.15.0"
20
+ s.add_dependency "ffi", "~> 1.9.0"
21
+
22
+ s.add_development_dependency "rake-compiler", "~> 0.9.2"
23
+ s.add_development_dependency "mocha", "~> 1.0.0"
24
+ s.add_development_dependency "rake"
25
+ end
@@ -0,0 +1,11 @@
1
+ char* encrypt(int table[], char buf[], int len)
2
+ {
3
+ int j = 0;
4
+ char *end = buf + len;
5
+ while (buf < end) {
6
+ *buf = (char)table[(unsigned char)*buf];
7
+ buf++;
8
+ }
9
+
10
+ return buf - len;
11
+ }
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+
3
+ create_makefile('encrypt')
@@ -0,0 +1,9 @@
1
+ require 'celluloid/io'
2
+
3
+ module DCase
4
+ autoload :Crypto, 'dcase/crypto'
5
+ autoload :Table, 'dcase/table'
6
+ autoload :Server, 'dcase/server'
7
+ autoload :Local, 'dcase/local'
8
+ end
9
+
@@ -0,0 +1,25 @@
1
+ module DCase
2
+ class Cli
3
+ def initialize(options = {})
4
+ @config = options[:config]
5
+ @crypto = DCase::Crypto.new(@config.password)
6
+ end
7
+
8
+ def run
9
+ supervisor = \
10
+ case @config.side
11
+ when 'local'
12
+ puts "*** Local side is up, remote server port:#{@config.port}"
13
+ DCase::Local.supervise('0.0.0.0', 53, @crypto, @config)
14
+ when 'server'
15
+ puts "*** Server side is up, port:#{@config.port}"
16
+ DCase::Server.supervise('0.0.0.0', @config.port, @crypto)
17
+ end
18
+
19
+ puts "*** Hit Ctrl+c to stop"
20
+ trap("INT") { supervisor.terminate; exit }
21
+ trap("TERM") { supervisor.terminate; exit }
22
+ sleep
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,90 @@
1
+ require 'optparse'
2
+ require 'yaml'
3
+
4
+ require File.expand_path('../version', __FILE__)
5
+
6
+ module DCase
7
+ class Config
8
+ attr_accessor :args, :side, :server, :port, :password, :config_path
9
+
10
+ def initialize(args)
11
+ @args = args || []
12
+
13
+ parse_args
14
+ read_config
15
+
16
+ check_values
17
+ end
18
+
19
+ def check_values
20
+ if side.nil?
21
+ raise 'You need to define side of dcase in'
22
+ end
23
+
24
+ if side == 'local' && server.nil?
25
+ raise 'You need to define remote server address'
26
+ end
27
+
28
+ if port.nil?
29
+ raise 'You need to define remote server port'
30
+ end
31
+
32
+ if password.nil?
33
+ raise 'You need to define a password, should be same in server/local side'
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def read_config
40
+ @config_path = File.expand_path('../..', File.dirname(__FILE__)) + '/config.yml' unless @config_path
41
+ config = YAML.load_file @config_path
42
+
43
+ @side = config["side"] if @side.nil?
44
+ @server = config["server"] if @server.nil?
45
+ @port = config["port"].to_i if @port.nil?
46
+ @password = config["password"] if @password.nil?
47
+ end
48
+
49
+ def parse_args
50
+ opt_parser = OptionParser.new do |opts|
51
+ opts.banner = "Usage: dcase [options]"
52
+
53
+ opts.separator ""
54
+ opts.separator "Specific options:"
55
+
56
+ opts.on("-s", "--side SIDE", "Local or Server side") do |c|
57
+ @side = c
58
+ end
59
+
60
+ opts.on("-c", "--config PATH", "Config file path") do |c|
61
+ @config_path = c
62
+ end
63
+
64
+ opts.on("-r", "--remote ADDRESS", "Remote server address") do |c|
65
+ @server = c
66
+ end
67
+
68
+ opts.on("-p", "--port PORT", Integer, "Remote server port") do |c|
69
+ @port = c
70
+ end
71
+
72
+ opts.on("-k", "--password PASSWORD", "Password, should be same in client and server sides") do |c|
73
+ @password = c
74
+ end
75
+
76
+ opts.on_tail("-v", "--version", "Show shadowsocks gem version") do
77
+ puts DCase::VERSION
78
+ exit
79
+ end
80
+
81
+ opts.on_tail("-h", "--help", "Show this message") do
82
+ puts opts
83
+ exit
84
+ end
85
+ end
86
+
87
+ opt_parser.parse!(args)
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,17 @@
1
+ module DCase
2
+ class Crypto
3
+ include DCase::Table
4
+
5
+ def initialize(password)
6
+ @encrypt_table, @decrypt_table = get_table(password)
7
+ end
8
+
9
+ def encrypt(data)
10
+ translate(@encrypt_table, data)
11
+ end
12
+
13
+ def decrypt(data)
14
+ translate(@decrypt_table, data)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,38 @@
1
+ module DCase
2
+ class Local
3
+ MAX_PACKET_SIZE = 512
4
+
5
+ include Celluloid::IO
6
+
7
+ attr_accessor :socket, :crypto
8
+
9
+ def initialize(addr, port, crypto, config)
10
+ @socket = UDPSocket.new
11
+ @socket.bind(addr, port)
12
+ @crypto = crypto
13
+ @config = config
14
+
15
+ async.run
16
+ end
17
+
18
+ def run
19
+ loop do
20
+ data, (_, port, addr) = @socket.recvfrom(MAX_PACKET_SIZE)
21
+ handle_data(data, port, addr)
22
+ end
23
+ end
24
+
25
+ def handle_data(data, port, addr)
26
+ connector = UDPSocket.new
27
+ connector.send crypto.encrypt(data), 0, @config.server, @config.port
28
+
29
+ async.request(connector, port, addr)
30
+ end
31
+
32
+ def request(connector, port, addr)
33
+ data, (_, _port, _addr) = connector.recvfrom(16384)
34
+ @socket.send crypto.decrypt(data), 0, addr, port
35
+ connector.close unless connector.closed?
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,41 @@
1
+ module DCase
2
+ class Server
3
+ include Celluloid::IO
4
+ finalizer :finalize
5
+
6
+ attr_accessor :crypto
7
+
8
+ def initialize(host, port, crypto)
9
+ @server = UDPSocket.new
10
+ @server.bind(host, port)
11
+
12
+ @crypto = crypto
13
+
14
+ async.run
15
+ end
16
+
17
+ def finalize
18
+ @server.close unless @server.closed?
19
+ end
20
+
21
+ def run
22
+ loop do
23
+ data, (_, port, addr) = @server.recvfrom(16384)
24
+ handle_data(data, port, addr)
25
+ end
26
+ end
27
+
28
+ def handle_data(data, port, addr)
29
+ request = UDPSocket.new
30
+ request.send crypto.decrypt(data), 0, '8.8.8.8', 53
31
+
32
+ async.start_connect(request, port, addr)
33
+ end
34
+
35
+ def start_connect(request, port, addr)
36
+ data, (_, _port, _addr) = request.recvfrom(16384)
37
+ @server.send crypto.encrypt(data), 0, addr, port
38
+ request.close unless request.closed?
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,84 @@
1
+ require "digest"
2
+ require 'ffi'
3
+
4
+ module Ext
5
+ def self.binary_path
6
+ path = ''
7
+ %w( so bundle dll ).each do |ext|
8
+ path = File.expand_path('..', File.dirname(__FILE__)) + "/encrypt.#{ext}"
9
+ break if File.exists? path
10
+ end
11
+
12
+ path
13
+ end
14
+
15
+ extend FFI::Library
16
+ ffi_lib binary_path
17
+ attach_function "encrypt", [:pointer, :pointer, :int], :pointer
18
+ end
19
+
20
+ module DCase
21
+ module Table
22
+ include Ext
23
+
24
+ def get_table key
25
+ table = Array.new(256, 0)
26
+ decrypt_table = Array.new(256, 0)
27
+
28
+ a = Digest::MD5.digest(key).unpack('Q<')[0]
29
+ i = 0
30
+
31
+ while i < 256
32
+ table[i] = i
33
+ i += 1
34
+ end
35
+ i = 1
36
+
37
+ while i < 1024
38
+ table = merge_sort(table, lambda { |x, y|
39
+ a % (x + i) - a % (y + i)
40
+ })
41
+ i += 1
42
+ end
43
+ i = 0
44
+ while i < 256
45
+ decrypt_table[table[i]] = i
46
+ i += 1
47
+ end
48
+ [ table, decrypt_table ]
49
+ end
50
+
51
+ def translate(table, buf)
52
+ table_ptr = FFI::MemoryPointer.new(:int, table.length)
53
+ table_ptr.put_array_of_int32(0, table)
54
+
55
+ buf_ptr = FFI::MemoryPointer.new(:string, buf.length)
56
+ buf_ptr.put_bytes(0, buf)
57
+
58
+ r = Ext.encrypt(table_ptr, buf_ptr, buf.length).get_bytes(0, buf.length)
59
+ table_ptr.free
60
+ buf_ptr.free
61
+ r
62
+ end
63
+
64
+ def merge (left, right, comparison)
65
+ result = []
66
+ while (left.length > 0) and (right.length > 0)
67
+ if comparison.call(left[0], right[0]) <= 0
68
+ result.push left.shift()
69
+ else
70
+ result.push right.shift()
71
+ end
72
+ end
73
+ result.push left.shift() while left.length > 0
74
+ result.push right.shift() while right.length > 0
75
+ result
76
+ end
77
+
78
+ def merge_sort (array, comparison)
79
+ return array if array.size < 2
80
+ middle = (array.size / 2).ceil
81
+ merge(merge_sort(array.slice(0, middle), comparison), merge_sort(array.slice(middle .. array.size), comparison), comparison)
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,3 @@
1
+ module DCase
2
+ VERSION = '0.2'
3
+ end
@@ -0,0 +1,9 @@
1
+ require 'rake/extensiontask'
2
+
3
+ def gemspec
4
+ @clean_gemspec ||= eval(File.read(File.expand_path('../../dcase.gemspec', __FILE__)))
5
+ end
6
+
7
+ Rake::ExtensionTask.new('encrypt', gemspec) do |ext|
8
+ ext.ext_dir = 'ext/encrypt'
9
+ end
@@ -0,0 +1,7 @@
1
+ task :gem do
2
+ `gem build ./dcase.gemspec`
3
+ end
4
+
5
+ task :install do
6
+ `gem install ./dcase-#{DCase::VERSION}.gem`
7
+ end
@@ -0,0 +1,3 @@
1
+ require "bundler/setup"
2
+ require "minitest/autorun"
3
+ require "mocha/setup"
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dcase
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.2'
5
+ platform: ruby
6
+ authors:
7
+ - Sen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: celluloid-io
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.15.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.15.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: ffi
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 1.9.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 1.9.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake-compiler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 0.9.2
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.9.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: mocha
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.0.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 1.0.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: DCase is a lightweight dns proxy which can help you get through firewalls.
84
+ email: sen9ob@gmail.com
85
+ executables:
86
+ - dcase
87
+ extensions:
88
+ - ext/encrypt/extconf.rb
89
+ extra_rdoc_files: []
90
+ files:
91
+ - .gitignore
92
+ - Gemfile
93
+ - LICENSE
94
+ - README.md
95
+ - Rakefile
96
+ - bin/dcase
97
+ - config.yml
98
+ - dcase.gemspec
99
+ - ext/encrypt/encrypt.c
100
+ - ext/encrypt/extconf.rb
101
+ - lib/dcase.rb
102
+ - lib/dcase/cli.rb
103
+ - lib/dcase/config.rb
104
+ - lib/dcase/crypto.rb
105
+ - lib/dcase/local.rb
106
+ - lib/dcase/server.rb
107
+ - lib/dcase/table.rb
108
+ - lib/dcase/version.rb
109
+ - tasks/compile.rake
110
+ - tasks/dev.rake
111
+ - test/test_helper.rb
112
+ homepage: https://github.com/Sen/DCase
113
+ licenses:
114
+ - MIT
115
+ metadata: {}
116
+ post_install_message:
117
+ rdoc_options: []
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - '>='
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ requirements: []
131
+ rubyforge_project:
132
+ rubygems_version: 2.0.14
133
+ signing_key:
134
+ specification_version: 4
135
+ summary: a secure dns proxy
136
+ test_files: []