diff options
author | Marcus Ilgner <mail@marcusilgner.com> | 2016-09-09 16:54:43 +0200 |
---|---|---|
committer | Miklos Fazekas <mfazekas@szemafor.com> | 2016-10-15 16:54:27 +0200 |
commit | d355aff1a18ca920c781a51ec716e1301983236f (patch) | |
tree | dda89e68ed91c6fd4ac1b16a7623283d6e3ad863 /lib/net/ssh/proxy | |
parent | ed13802dc2059b479653f75c10bd15243f11c0df (diff) | |
download | net-ssh-d355aff1a18ca920c781a51ec716e1301983236f.tar.gz |
Support HTTP Proxy on SSL socket
Since the HTTP Proxy only supports BASIC authentication, this adds the
required infrastructure to net-ssh to connect to a SSL-enabled server.
Closes: #432
Diffstat (limited to 'lib/net/ssh/proxy')
-rw-r--r-- | lib/net/ssh/proxy/http.rb | 11 | ||||
-rw-r--r-- | lib/net/ssh/proxy/https.rb | 49 |
2 files changed, 56 insertions, 4 deletions
diff --git a/lib/net/ssh/proxy/http.rb b/lib/net/ssh/proxy/http.rb index 27c99d5..5d64173 100644 --- a/lib/net/ssh/proxy/http.rb +++ b/lib/net/ssh/proxy/http.rb @@ -49,8 +49,7 @@ module Net; module SSH; module Proxy # Return a new socket connected to the given host and port via the # proxy that was requested when the socket factory was instantiated. def open(host, port, connection_options) - socket = Socket.tcp(proxy_host, proxy_port, nil, nil, - connect_timeout: connection_options[:timeout]) + socket = establish_connection(connection_options[:timeout]) socket.write "CONNECT #{host}:#{port} HTTP/1.0\r\n" if options[:user] @@ -68,7 +67,12 @@ module Net; module SSH; module Proxy raise ConnectError, resp.inspect end - private + protected + + def establish_connection(connect_timeout) + Socket.tcp(proxy_host, proxy_port, nil, nil, + connect_timeout: connect_timeout) + end def parse_response(socket) version, code, reason = socket.gets.chomp.split(/ /, 3) @@ -89,7 +93,6 @@ module Net; module SSH; module Proxy :headers => headers, :body => body } end - end end; end; end diff --git a/lib/net/ssh/proxy/https.rb b/lib/net/ssh/proxy/https.rb new file mode 100644 index 0000000..e36ea0a --- /dev/null +++ b/lib/net/ssh/proxy/https.rb @@ -0,0 +1,49 @@ +require 'socket' +require 'openssl' +require 'net/ssh/proxy/errors' +require 'net/ssh/proxy/http' + +module Net; module SSH; module Proxy + + # A specialization of the HTTP proxy which encrypts the whole connection + # using OpenSSL. This has the advantage that proxy authentication + # information is not sent in plaintext. + class HTTPS < HTTP + + # Create a new socket factory that tunnels via the given host and + # port. The +options+ parameter is a hash of additional settings that + # can be used to tweak this proxy connection. In addition to the options + # taken by Net::SSH::Proxy::HTTP it supports: + # + # * :ssl_context => the SSL configuration to use for the connection + def initialize(proxy_host, proxy_port=80, options={}) + @ssl_context = options.delete(:ssl_context) || + OpenSSL::SSL::SSLContext.new + super(proxy_host, proxy_port, options) + end + + protected + + # Shim to make OpenSSL::SSL::SSLSocket behave like a regular TCPSocket + # for all intents and purposes of Net::SSH::BufferedIo + module SSLSocketCompatibility + def self.extended(object) #:nodoc: + object.define_singleton_method(:recv, object.method(:sysread)) + object.sync_close = true + end + + def send(data, _opts) + syswrite(data) + end + end + + def establish_connection(connect_timeout) + plain_socket = super(connect_timeout) + OpenSSL::SSL::SSLSocket.new(plain_socket, @ssl_context).tap do |socket| + socket.extend(SSLSocketCompatibility) + socket.connect + end + end + end + +end; end; end |