ssl_gate 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6249ae8b79002d80de3d5710270887c8894834db
4
+ data.tar.gz: f3c9e97ddc513d3ebc72306f8c1ab5cca7c32ec6
5
+ SHA512:
6
+ metadata.gz: 469ccb88950f8402c3d01576e19a02ab7ba720a47177e15c4337a97239c0d8001f407103bce7d8c6c4a819fd03237e2418219659dde972c2e1db514baab7ba8a
7
+ data.tar.gz: 9d6feea10dc30a8985f36293e314e7a44de9a147cc4c33774c17b1beace980bc36e65186d13c26efe5e68d196d3c2826067d972f62199560da49c1319859906f
data/bin/ssl_gate ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'ssl_gate'
3
+
4
+ SSLGate::Runner.start
@@ -0,0 +1,47 @@
1
+ require 'thin'
2
+ require 'em-http'
3
+
4
+ module SSLGate
5
+
6
+ class HTTPServer
7
+ class << self; attr_accessor :add_ons end
8
+ @add_ons = []
9
+
10
+ attr_reader :config
11
+ def initialize(config)
12
+ @config = { signals: false,
13
+ # target: 'http://localhost:9000'
14
+ }.merge config
15
+ end
16
+
17
+ def call(env)
18
+ r_method = env['REQUEST_METHOD'].downcase.to_sym
19
+ r_query = env['QUERY_STRING']
20
+ r_path = env['REQUEST_PATH']
21
+ # input = env['rack.input'] #StringIO
22
+ env[:target_request_options] ||= { connect_timeout: 20, inactivity_timeout: 20 }
23
+
24
+ puts "head: #{env[:target_get_options][:head] rescue ''}"
25
+ request = EM::HttpRequest.new @config[:target], env[:target_request_options]
26
+ http = request.send r_method, (env[:target_get_options] || {}).merge( path: r_path, query: r_query) # body: input
27
+ puts "#{r_method}: #{r_path} #{r_query}"
28
+
29
+ ready = lambda {
30
+ headers = http.response_header.map{ |key, val| [key.tr('_', '-'), val] }.to_h
31
+ headers.delete 'TRANSFER-ENCODING'
32
+ headers.delete 'CONTENT-ENCODING'
33
+ headers.delete 'CONTENT-LENGTH'
34
+ puts "OK: #{headers}"
35
+ env['async.callback'].call [http.response_header.status, headers, [http.response]]
36
+ }
37
+ http.callback { ready.call }
38
+ http.errback { ready.call }
39
+ throw :async
40
+ end
41
+
42
+ def self.start(config)
43
+ server = new(config)
44
+ Thin::Server.start (config[:bind_interface] || '0.0.0.0'), config[:bind_port], server.config, server
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/ruby
2
+ require 'thin'
3
+
4
+ OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options] |= OpenSSL::SSL::OP_NO_COMPRESSION
5
+ OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options] |= OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
6
+ OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ciphers] = 'TLSv1.2:!aNULL:!eNULL'
7
+ OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ssl_version] = 'TLSv1_2'
8
+
9
+ module SSLGate
10
+
11
+ class SSLBackend < ::Thin::Backends::TcpServer
12
+ def initialize(host, port, options)
13
+ super(host, port)
14
+ @ssl = true
15
+ @ssl_options = options
16
+ end
17
+ end
18
+
19
+ module SSLBackendAddOn
20
+ def initialize(config)
21
+ super config.merge backend: SSLBackend
22
+ # private_key_file: File.dirname(__FILE__) + "/server.key",
23
+ # cert_chain_file: File.dirname(__FILE__) + "/server.crt",
24
+ end
25
+ end
26
+
27
+ HTTPServer.add_ons << SSLBackendAddOn
28
+ end
@@ -0,0 +1,12 @@
1
+ module SSLGate
2
+
3
+ module ClientCertAddOn
4
+ def initialize(config)
5
+ super config.merge verify_peer: true, fail_if_no_peer_cert: true
6
+ # ca:'ca.crt'
7
+ # add_cn_header: 'SSL_CLIENT_CN'
8
+ end
9
+ end
10
+
11
+ HTTPServer.add_ons << ClientCertAddOn
12
+ end
@@ -0,0 +1,27 @@
1
+ module SSLGate
2
+
3
+ module HeadersModAddOn
4
+
5
+ def call(env)
6
+ prev = env['async.callback']
7
+ env['async.callback'] = lambda { |*args|
8
+ # puts 'I see you'
9
+ prev.call(*args)
10
+ }
11
+ headers = env.select { |k, _v| k.start_with? 'HTTP_' }
12
+ .collect { |key, val| [key.sub(/^HTTP_/, '').gsub('_', '-'), val] }
13
+ .to_h
14
+ headers.delete 'HOST'
15
+ headers.delete 'USER-AGENT'
16
+ headers['REFERER'].sub! %r{^https?://[^/]+(:\d+)?}, @config[:target] if headers['REFERER']
17
+ super env
18
+ end
19
+
20
+ def initialize(config)
21
+ super
22
+ # subst_host: 'name'
23
+ end
24
+ end
25
+
26
+ HTTPServer.add_ons << HeadersModAddOn
27
+ end
@@ -0,0 +1,56 @@
1
+ require 'eventmachine'
2
+
3
+ module SSLGate
4
+
5
+ class RawClient < EM::Connection
6
+ attr_reader :queue
7
+
8
+ def initialize(q, parent)
9
+ set_sock_opt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) # Nagle off
10
+
11
+ @parent = parent
12
+ @queue = q
13
+
14
+ cb = proc do |msg|
15
+ msg ? send_data(msg) : close_connection
16
+ q.pop(&cb)
17
+ end
18
+ q.pop(&cb)
19
+ end
20
+
21
+ def receive_data(data)
22
+ @parent.send_data data
23
+ end
24
+
25
+ def unbind
26
+ @parent.close_connection
27
+ end
28
+ end
29
+
30
+ class RawServer < EM::Connection
31
+ class << self; attr_accessor :add_ons end
32
+ @add_ons = []
33
+
34
+ def self.start(config)
35
+ EventMachine.start_server (config[:bind_interface] || '0.0.0.0'), config[:bind_port], self, config
36
+ end
37
+
38
+ def initialize(config)
39
+ @config = config
40
+ end
41
+
42
+ def post_init
43
+ @queue = EM::Queue.new
44
+ uri = URI.parse @config[:target]
45
+ EM.connect uri.host, uri.port, RawClient, @queue, self
46
+ end
47
+
48
+ def receive_data(data)
49
+ @queue.push data
50
+ end
51
+
52
+ def unbind
53
+ @queue.push nil
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,21 @@
1
+ module SSLGate
2
+ module SSLRawAddOn
3
+ def post_init
4
+ super
5
+ start_tls private_key_file: @config[:private_key_file],
6
+ cert_chain_file: @config[:cert_chain_file]
7
+ # verify_peer: true,
8
+ # fail_if_no_peer_cert: true
9
+ end
10
+
11
+ # def ssl_verify_peer(cert)
12
+ # true
13
+ # end
14
+
15
+ def ssl_handshake_completed
16
+ $server_handshake_completed = true
17
+ end
18
+ end
19
+
20
+ RawServer.add_ons << SSLRawAddOn
21
+ end
@@ -0,0 +1,29 @@
1
+ require 'yaml'
2
+
3
+ module SSLGate
4
+ # CLI runner.
5
+ class Runner
6
+
7
+ def self.symbolize_keys(hash)
8
+ hash.each_with_object({}) do |(key, value), result|
9
+ new_key = key.is_a?(String) ? key.to_sym : key
10
+ new_value = value.is_a?(Hash) ? symbolize_keys(value) : value
11
+ result[new_key] = new_value
12
+ result
13
+ end
14
+ end
15
+
16
+ def self.start
17
+ config = symbolize_keys YAML.load_file('SSLGate')
18
+
19
+ EventMachine.run do
20
+ Signal.trap('INT') { EM.stop if EM.reactor_running? }
21
+ Signal.trap('TERM') { EM.stop if EM.reactor_running? }
22
+
23
+ SSLGate.factory config
24
+ end
25
+ rescue => e
26
+ STDERR.puts e.message
27
+ end
28
+ end
29
+ end
data/lib/ssl_gate.rb ADDED
@@ -0,0 +1,35 @@
1
+ require_relative 'ssl_gate/raw_gate'
2
+ require_relative 'ssl_gate/raw_ssl'
3
+
4
+ require_relative 'ssl_gate/base_gate'
5
+ require_relative 'ssl_gate/base_ssl_gate'
6
+ require_relative 'ssl_gate/headers_mod'
7
+ #require_relative 'ssl_gate/client_cert'
8
+ require_relative 'ssl_gate/runner'
9
+
10
+ module SSLGate
11
+ class RawServerAll < RawServer
12
+ RawServer.add_ons.each { |add_on|
13
+ puts "Include server add-on: #{add_on}"
14
+ prepend add_on
15
+ }
16
+ end
17
+
18
+ class HTTPServerAll < HTTPServer
19
+ HTTPServer.add_ons.each { |add_on|
20
+ puts "Include server add-on: #{add_on}"
21
+ prepend add_on
22
+ }
23
+ end
24
+
25
+ def self.factory(config)
26
+ config.each do |key, conf|
27
+ case key.to_s
28
+ when 'http' then HTTPServerAll.start conf
29
+ when 'tcp' then RawServerAll.start conf
30
+ else STDERR.puts "Unknown gate type: #{key}"
31
+ end
32
+ end
33
+ end
34
+ end
35
+
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ssl_gate
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Artyom B
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-03-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: em-http-request
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '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'
27
+ - !ruby/object:Gem::Dependency
28
+ name: eventmachine
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thin
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: ''
70
+ email: author@email.address
71
+ executables:
72
+ - ssl_gate
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - bin/ssl_gate
77
+ - lib/ssl_gate.rb
78
+ - lib/ssl_gate/base_gate.rb
79
+ - lib/ssl_gate/base_ssl_gate.rb
80
+ - lib/ssl_gate/client_cert.rb
81
+ - lib/ssl_gate/headers_mod.rb
82
+ - lib/ssl_gate/raw_gate.rb
83
+ - lib/ssl_gate/raw_ssl.rb
84
+ - lib/ssl_gate/runner.rb
85
+ homepage: http://rubygems.org/gems/ssl_gate
86
+ licenses:
87
+ - Nonstandard
88
+ metadata: {}
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 2.6.14
106
+ signing_key:
107
+ specification_version: 4
108
+ summary: SSL Proxy
109
+ test_files: []