dcase 0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []