Search code examples
sslrusthypernickel

Nickel server using Let's Encrypt certificate has a handshake error when accessed with rustls


I'm trying to create a small REST-like API that should be secured with HTTPS. I want to use the nickel crate for the server and hyper_rustls and hyper for the client.

The server is running great as long as I use a browser, curl or a REST client to access it, but when I start to use hyper_rustls I always get a handshake error:

TLS error: AlertReceived(HandshakeFailure)
Connection closed

To localize the error, I set up a minimal server:

#[macro_use]
extern crate nickel;
extern crate hyper;
use hyper::net::Openssl;


use nickel::Nickel;

fn main() {
    let mut server = Nickel::new();

    server.utilize(router! {
        get "**" => |_req, _res| {
            "Hello world!"
        }
    });

    // FIXME: Add Match Error and OK instead of unwreap and add a propper error handling
    let ssl = Openssl::with_cert_and_key("/etc/letsencrypt/live/www.example.de/fullchain.\
                                          pem",
                                         "/etc/letsencrypt/live/www.example.de/privkey.pem")
        .unwrap();

    server.listen_https("0.0.0.0:6767", ssl).expect("Failed to launch server");
}

On the Rust Playground

To avoid errors in hyper_rustls, I used the rustls tlsclient example but the error still appears.

The Let's Encrypt certificate isn't the problem as I can connect to an Apache2 server with these certs using tlsclient.

Have I made a mistake with my thinking how this works?


Solution

  • It looks like hyper's Openssl::with_cert_and_key tells openssl to use the DEFAULT cipher suite list, which is pretty awful. rustls in this case is failing to handshake for the same reason that chrome says "obsolete key exchange (RSA)". If you run your server and point ssllabs.com at it, you should get more information.

    I think more recent hyper releases have removed this code in favour getting TLS support from other crates. Could you try that?