sfackler / rust-native-tls

Apache License 2.0
470 stars 195 forks source link

Accepting non-TLS WebSocket makes TspListener hang? #237

Open tkntkn opened 1 year ago

tkntkn commented 1 year ago

Description

While trying to write a secured WebSocket server using tungstenite-rs, I found this strange behavior of native-tls (it does not require tungstenite to reproduce). When a client incorrectly requests a non-TLS WebSocket handshake to the server, TlsAcceptor::accept(&self, stream) goes into an infinite loop and never returns unless the client explicitly closes the connection. Even worse, it makes the server (= TcpListener) stop handling other (TLS secured) WebSocket requests. I'm new to Rust so I couldn't determine why accepting one wrong request in the separated thread makes TcpListener in the main thread stop working.

Environment

How to reproduce

  1. Run the below program

    use std::sync::Arc;
    use std::thread;
    use std::{fs::File, net::TcpListener};
    use std::io::{Read};
    
    use native_tls::{TlsAcceptor, Identity};
    
    fn main() {
        let mut file = File::open("./cert/server.pfx").unwrap();
        let mut identity = vec![];
        file.read_to_end(&mut identity).unwrap();
        let identity = Identity::from_pkcs12(&identity, "").unwrap();
        let acceptor = TlsAcceptor::new(identity).unwrap();
        let acceptor = Arc::new(acceptor);
    
        let server = TcpListener::bind("127.0.0.1:8080").unwrap();
        let t = thread::spawn(move || {
            for stream in server.incoming() {
                println!("incoming!");
                let acceptor = acceptor.clone();
                thread::spawn(move || {
                    acceptor.accept(stream.unwrap()).unwrap();
                    println!("accepted!");
                });
            }
        });
    
        t.join().unwrap();
    }
  2. Send a non-TLS WebSocket request from a browser

    > var ws = new WebSocket('ws://127.0.0.1:8080');
  3. The server prints "incoming!" but not "accepted!"

  4. Send another (but this time using TLS) WebSocketSecure request from a browser

    > var ws = new WebSocket('wss://127.0.0.1:8080');
  5. The server prints neither "incoming!" nor "accepted!", which means TcpListener itself is hanging?

mybreeze2018 commented 4 months ago

yes . me to