Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add example for usage with TLS #127

Open
brunogauthier1 opened this issue Jun 4, 2020 · 13 comments
Open

Add example for usage with TLS #127

brunogauthier1 opened this issue Jun 4, 2020 · 13 comments

Comments

@brunogauthier1
Copy link

Hi,

Anyone have a working example of a secure WebSocket on localhost for example, client and server?
I'm a bit confuse about how to instantiate the client and the server over TLS.

I simply did #[cfg(feature = "tls")] in both the .../example/client.rs and server.rs and use a wss prefix instead of ws in the client URL.
But it crash.

Thanks for helping

Bruno

@agalakhov
Copy link
Member

This works for the client but not for the server. In general, for the server you have to accept TLS connection yourself and then pass it to Tungstenite after accepting. This is done so because you must configure certificates and TLS options on the server side.

There are examples how to accept TLS connection in both native_tls and rustls, i.e.
https://docs.rs/native-tls/0.2.4/native_tls/

What you do is just add Tungstenite to their example:

fn handle_client(stream: TlsStream<TcpStream>) {
    let mut websocket = tungstenite::accept(stream)
        .add_your_error_handling_here();
    // ...
}

Both native_tls and rustls can be used with Tungstenite.

@captainmannering
Copy link

I don't really understand what is being said above. I have 2 cases:
1 - to connect using wss to a server and ignore any certificate problems
or
2 - to connect using wss and to use a certificate file (.pem or .cert) that I have been given to verify the server's cert.

How do I do these 2 cases with a tungstenite client app?

@daniel-abramov
Copy link
Member

I think what Alexey meant is that tungstenite-rs does not add any additional layer of abstractions at this point. If you're writing a server that accepts wss, you have to create the corresponding TlsAcceptor (see example from native-tls). After the stream is accepted, you can pass the TlsStream to tungstenite::accept().

@captainmannering
Copy link

Thanks, got that much working now.

@ProgrammingLife
Copy link

@captainmannering, How did you get it?

@daniel-abramov
Copy link
Member

@ProgrammingLife just try to use the example from native-tls (the link is in a comment above) and pass it to tungstenite::accept(), this should do the job.

@daniel-abramov daniel-abramov changed the title Question: WSS example Add example for usage with TLS Jun 24, 2020
@aidanhs
Copy link

aidanhs commented Feb 13, 2021

For the record, here's how I did it with rustls

  static KEY: &[u8] = include_bytes!("../keys/key.pem");    
  static CERT: &[u8] = include_bytes!("../keys/cert.pem");

[...]

      let mut tls_config: rustls::ServerConfig = rustls::ServerConfig::new(rustls::NoClientAuth::new());    
      tls_config.set_single_cert(    
          rustls::internal::pemfile::certs(&mut &*CERT).unwrap(),    
          rustls::internal::pemfile::pkcs8_private_keys(&mut &*KEY).unwrap()    
              .pop().unwrap()    
      ).unwrap();    
      let tls_config = Arc::new(tls_config);

      for stream in server.incoming() { 
          let tls_session = rustls::ServerSession::new(&tls_config);    
          let stream = rustls::StreamOwned::new(tls_session, stream.unwrap());
[...]
          let mut websocket = accept_hdr(stream, handshake_callback).unwrap();

I generated the certs with https://github.com/ctz/rustls/blob/0507dd0/bogo/regen-certs

@SauceChord
Copy link

@aidanhs I am having issues getting a simple example working with rustls. Could you (or anyone else who knows these kinds of things) take a look? I have an example repo with information about how I created keys. It should be something simple, but I have been bashing my head against this all for quite some time and I am getting a bit disheartened to my own lack of skill with certs and tls.

// thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: 
// HandshakeError::Failure(Io(Custom { kind: InvalidData, error: AlertReceived(CertificateUnknown) }))'
let mut websocket = tungstenite::accept(tls_stream).unwrap(); // <- panicks

I am connecting to "wss://localhost:8443" through a web page (code included).

All I want is to be able to have a web page connect to a server that will host a game (in the end).

@daniel-abramov
Copy link
Member

I have not checked it in the detail, but it looks like you're using the self-signed certificates while relying on the default root certificate (i.e. your certificates are not "signed" by a CA and being rejected by the client that connects to your server), so the validation fails.

@hp-goldfinger
Copy link

I'd like to recommend another approach, using nginx to proxy TLS stream. So you could keep your websocket code nice and clean and leave TLS auth to nginx. Here's an nginx config example to do that: http://disq.us/p/20a6j7c in case anyone is intereted in.

@daniel-abramov
Copy link
Member

Yes, that's actually what we would generally suggest ;) I think most of the typical services nowadays do it like this, i.e. having a reverse-proxy that does the TLS.

@hairui19
Copy link

see example

Can you give some details in terms of how you did it? I want my client to connect to my server via wss without server having to care about TLS certificate details.

@agalakhov
Copy link
Member

You need to use some extra software such as nginx in front of our server and configure certificates in this software. Please refer to its documentation for further examples. In many companies it isn't even your job since there is a separate department that configures networks and certificates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants