class H2::Server::HTTPS
'h2' server - for TLS 1.2 ALPN HTTP/2 connection
Constants
- ALPN_PROTOCOL
- ALPN_SELECT_CALLBACK
- ECDH_CURVES
- ECDH_OPENSSL_MIN_VERSION
- TMP_ECDH_CALLBACK
Public Class Methods
create a new h2 server that uses SNI to determine TLS cert/key to use
@see en.wikipedia.org/wiki/Server_Name_Indication
@param [String] host the IP address for this server to listen on @param [Integer] port the TCP port for this server to listen on @param [Hash] sni the SNI option hash with certs/keys for domains @param [Hash] options
@option [String] :cert TLS certificate @option [String] :extra_chain_cert TLS certificate @option [String] :key TLS key
SNI options with default callback¶ ↑
- :sni
-
Hash with domain name
String
keys andHash
values: - :cert
-
String
TLS certificate - :extra_chain_cert
-
String
TLS certificate - :key
-
String
TLS key
SNI options with custom callback¶ ↑
- :sni
-
Hash:
- :callback
-
Proc
createsOpenSSL::SSL::SSLContext
for eachconnection
H2::Server::new
# File lib/h2/server/https.rb, line 43 def initialize host:, port:, sni: {}, **options, &on_connection @sni = sni @sni_callback = @sni[:callback] || method(:sni_callback) @tcpserver = Celluloid::IO::TCPServer.new host, port @sslserver = Celluloid::IO::SSLServer.new @tcpserver, create_ssl_context(options) options.merge! host: host, port: port, sni: sni super @sslserver, options, &on_connection end
Public Instance Methods
accept a socket connection, possibly attach spy, hand off to #handle_connection
asyncronously, repeat
# File lib/h2/server/https.rb, line 55 def run loop do begin socket = @server.accept rescue OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::EPIPE, Errno::ETIMEDOUT, Errno::EHOSTUNREACH => ex Logger.warn "Error accepting SSLSocket: #{ex.class}: #{ex.to_s}" retry end async.handle_connection socket end end
Private Instance Methods
# File lib/h2/server/https.rb, line 124 def context_cert cert case cert when String cert = File.read cert if File.exist? cert OpenSSL::X509::Certificate.new cert when OpenSSL::X509::Certificate cert end end
# File lib/h2/server/https.rb, line 110 def context_ecdh ctx ctx.ecdh_curves = ECDH_CURVES end
# File lib/h2/server/https.rb, line 144 def context_extra_chain_cert chain case chain when String chain = File.read chain if File.exist? chain [OpenSSL::X509::Certificate.new(chain)] when OpenSSL::X509::Certificate [chain] when Array chain end end
# File lib/h2/server/https.rb, line 134 def context_key key case key when String key = File.read key if File.exist? key OpenSSL::PKey::RSA.new key when OpenSSL::PKey::RSA key end end
# File lib/h2/server/https.rb, line 157 def context_set_protocols ctx ctx.alpn_protocols = [ALPN_PROTOCOL] ctx.alpn_select_cb = ALPN_SELECT_CALLBACK end
builds a new SSLContext suitable for use in 'h2' connections
# File lib/h2/server/https.rb, line 88 def create_ssl_context **opts ctx = OpenSSL::SSL::SSLContext.new ctx.ca_file = opts[:ca_file] if opts[:ca_file] ctx.ca_path = opts[:ca_path] if opts[:ca_path] ctx.cert = context_cert opts[:cert] ctx.ciphers = opts[:ciphers] || OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ciphers] ctx.extra_chain_cert = context_extra_chain_cert opts[:extra_chain_cert] ctx.key = context_key opts[:key] ctx.options = opts[:options] || OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options] ctx.servername_cb = @sni_callback ctx.ssl_version = :TLSv1_2 context_ecdh ctx # https://github.com/jruby/jruby-openssl/issues/99 context_set_protocols ctx unless H2.jruby? ctx end
default SNI callback - builds SSLContext from cert/key by domain name in +@sni+ or returns existing one if name is not found
# File lib/h2/server/https.rb, line 74 def sni_callback args socket, name = args @contexts ||= {} if @contexts[name] @contexts[name] elsif sni_opts = @sni[name] and Hash === sni_opts @contexts[name] = create_ssl_context sni_opts else socket.context end end