mlalic / solicit

An HTTP/2 implementation in Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Is it possible to connect to an insecure connection?

AKST opened this issue · comments

commented

I've managed to test my http2 server with a dodgy certificate in chrome by explicitly acknowledging the connection is insecure, however I am having a hard time connecting to this server via this library, when I do I get an IOError, and I'm convinced it's the dodgy certificate I have for my server as I can connect to https://http2bin.org just fine.

My code using solicit is identical to the demo code here, and the server is written using node-http2 [1]. The line that is returning the Err(IOError) is this.

// I've removed the unwrap due to the error
let mut client = SimpleClient::with_connection(conn, "http2bin.org".into());

Whether you consider this a bug is more to do with the design philosophy of this library, but considering it's described as a low level library it might be worth considering this as an opt-in thing. It would be particularly useful for beginners who don't have a signed cert for their servers running on localhost [2], or maybe a different client called InsecureSimpleClient or UnsafeSimpleClient identical to SimpleClient except it accepts unsafe requests. This way you explicitly acknowledge you're doing something insecure, even if you have to wrap each of it's method calls in an unsafe block [3].

Another thing if connecting to an insecure connection does result in a Err(IOError) it might be worthwhile adding a different error value for insecure connections.

_[1]_ I say this as it might make assessing this issue easier
_[2]_ I know the bare minimum about ssl, so maybe this is a solved problem, but I ended up buying my own certificate
_[3]_ It's not an unsafe memory operation, so maybe that's non-idiomatic rust, also it would likely make it impossible to share a trait due to different signatures (i think)

If you're using the exact code from the example that you linked, then the problem is clear.

The example establishes a pure cleartext TCP connection and passes this to the HttpConnection instance as the underlying stream that it should use. This socket is then directly and immediately used by the client.

However, since in your case, your server expects all clients to negotiate a TLS session, once the client sends its first bytes (the client preface for an HTTP/2 connection) over the unprotected socket, the server will (most probably) see this as an invalid TLS handshake and close the connection. This then leads to the client reporting an IO error as the underlying socket gets unexpectedly closed right under it.

(Note: again, if you're using the same code for trying to talk to http2bin, it's not actually https://, but pure http://, as that's what port 80 defaults to.)

Of course, there is a solution to this. :)

The first is to check out the SimpleClient::with_connector method, which automatically establishes an HTTP/2 connection (and the HttpConnection instance) by using a given instance of a type that implements HttpConnect to provide it with the network stream it should use. This trait is already implemented for cleartext and TLS connections (CleartextConnector and TlsConnector, respectively). The connectors take care to properly initialize the stream (including the client preface). The "tls" crate feature is required for using the TlsConnector, though. [0]

Then, all you need to do is include the cert of your own server in the CA file that you pass when constructing the TlsConnecor and the client should then automatically work everything out on its own and be fully usable. There's an example of this here.

This should probably be enough for the use case that you describe.

(You could also construct the TlsConnector with a custom SslContext that does no real validation, but I think it's faster to just "trust" your cert for the kind of experiments that you appear to be running.)

The second option is to "manually" establish a correct TLS/SSL-backed socket (i.e. the SslStream from the rust-openssl crate) and give that to the HttpConnection, instead of the TcpStream. This would require the "tls" feature too, since otherwise the TransportStream trait wouldn't be implemented for SslStream.

In terms of philosophy, the library deliberately does not make any requirements on the type of the underlying network connection that the SimpleClient should rely on, so long as it implements the TransportStream trait. For HttpConnection, things are even more general -- it doesn't even know anything about a network, only sending/receiving HTTP/2 frames (in the form of SendFrame and ReceiveFrame traits). The connectors that I mentioned are provided for convenience, though, as those are the most common ways you'd want to establish a "real" connection, but the door's still completely open for any sort of customization, either by implementing a custom connector (HttpConnect) or dropping down to the HttpConnection level, instead of the SimpleClient level of abstraction.

Hope that helps.

Let me know if it resolves your issue.

[0] This reveals a bug in the docs generation, since the TlsConnector is not included, given that it's behind the tls feature.

commented

Thanks for the detailed response, I'll investigate this more on my end in the next few days, I'll be sure to get back about this once I do.

As my post above answers the original question -- indeed, it is possible to establish a connection to a host with a self-signed cert -- I'll close this issue now.

That said, if there's any improvements in the API that you'd like, @AKST, feel free to open a new issue for that.

commented

Yeah apologies for not following up yet, I've just been deal with exams, but I'll follow up once I get around to testing it this again. Thanks again for your reply earlier

Sent from my phone

On 25 Jun 2015, at 9:45 pm, Marko Lalic notifications@github.com wrote:

As my post above answers the original question -- indeed, it is possible to establish a connection to a host with a self-signed cert -- I'll close this issue now.

That said, if there's any improvements in the API that you'd like, @AKST, feel free to open a new issue for that.


Reply to this email directly or view it on GitHub.