diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2015-11-16 19:44:04 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2015-11-16 20:17:11 +0900 |
commit | a5aa53a9174f47450582b29cb93cbd162753bf47 (patch) | |
tree | 64c717946fb08b64ff289e1de2dbb78b41dbee6a | |
parent | de62f5962e9047e867eb39ef933738ea3b9722c1 (diff) | |
download | plum-a5aa53a9174f47450582b29cb93cbd162753bf47.tar.gz |
rack/tls_listener: sni
-rw-r--r-- | examples/rack-example-config.rb | 21 | ||||
-rw-r--r-- | lib/plum/rack/listener.rb | 24 |
2 files changed, 37 insertions, 8 deletions
diff --git a/examples/rack-example-config.rb b/examples/rack-example-config.rb new file mode 100644 index 0000000..d8d3dcb --- /dev/null +++ b/examples/rack-example-config.rb @@ -0,0 +1,21 @@ +log "logs/plum.log" +debug false +server_push true +threaded false # create a new thread per request +fallback_legacy "127.0.0.1:8080" # forward if client doesn't support HTTP/2 + +# listeners may be multiple +listener :unix, { path: "/tmp/plum.sock", mode: 600 } +listener :tcp, { hostname: "0.0.0.0", port: 80 } +listener :tls, { + hostname: "0.0.0.0", + port: 443, + certificate: "/path/to/cert", # chained certifcate is acceptable + certificate_key: "/path/to/key", + sni: { + "rhe.jp" => { # SNI, key must be String. If none matches, default certificate (above) is used + certificate: "/path/to/rhe.jp/cert", + certificate_key: "/path/to/rhe.jp/key" + }, + } +} diff --git a/lib/plum/rack/listener.rb b/lib/plum/rack/listener.rb index c650ff0..1645c57 100644 --- a/lib/plum/rack/listener.rb +++ b/lib/plum/rack/listener.rb @@ -41,21 +41,29 @@ module Plum ctx = OpenSSL::SSL::SSLContext.new ctx.ssl_version = :TLSv1_2 - ctx.alpn_select_cb = -> protocols { - if protocols.include?("h2") - "h2" + ctx.alpn_select_cb = -> (protocols) { protocols.include?("h2") ? "h2" : protocols.first } + ctx.tmp_ecdh_callback = -> (sock, ise, keyl) { OpenSSL::PKey::EC.new("prime256v1") } + *ctx.extra_chain_cert, ctx.cert = parse_chained_cert(cert) + ctx.key = OpenSSL::PKey::RSA.new(key) + ctx.servername_cb = -> (sock, hostname) { + if lc[:sni] && (host = lc[:sni][hostname]) + new_ctx = ctx.dup + *new_ctx.extra_chain_cert, new_ctx.cert = parse_chained_cert(File.read(host[:certificate])) + new_ctx.key = OpenSSL::PKey::RSA.new(File.read(host[:certificate_key])) + new_ctx else - protocols.first + ctx end } - ctx.tmp_ecdh_callback = -> (sock, ise, keyl) { OpenSSL::PKey::EC.new("prime256v1") } - ctx.cert = OpenSSL::X509::Certificate.new(cert) - ctx.key = OpenSSL::PKey::RSA.new(key) tcp_server = ::TCPServer.new(lc[:hostname], lc[:port]) @server = OpenSSL::SSL::SSLServer.new(tcp_server, ctx) @server.start_immediately = false end + def parse_chained_cert(str) + str.scan(/-----BEGIN CERTIFICATE.+?END CERTIFICATE-----/m).map { |s| OpenSSL::X509::Certificate.new(s) } + end + def to_io @server.to_io end @@ -90,7 +98,7 @@ module Plum cert.sign key, OpenSSL::Digest::SHA1.new - [cert, key] + [cert.to_s, key.to_s] end end |