Closed kflansburg closed 10 months ago
TLS connections can't be opened in the normal way to Postgres servers - there's a small pre-TLS handshake: https://www.postgresql.org/docs/16/protocol-flow.html#PROTOCOL-FLOW-SSL
We do have support for Start TLS and know that this works with Node pg
, however, I'm not sure where I should hook in to call the method to switch from plaintext to TLS, could that be done in the TlsConnect::connect
method?
Unfortunately there is not yet a standard API for what I'm describing, however we have a Winter CG proposal for our JavaScript API which is exposed to Rust guests via wasm-bindgen
.
Ah gotcha. Once you have a stream that's finished the TLS handshake you should be able to hand it to https://docs.rs/tokio-postgres/latest/tokio_postgres/config/struct.Config.html#method.connect_raw with NoTls
. I don't think the client needs to know the TLS bits have already completed, but I could be misremembering?
Ah gotcha. Once you have a stream that's finished the TLS handshake you should be able to hand it to https://docs.rs/tokio-postgres/latest/tokio_postgres/config/struct.Config.html#method.connect_raw with
NoTls
.
Unfortunately doing this appears to cause an error. There must be some information sent in the Postgres protocol that indicates that the connection is plaintext (even though it's not) and the server rejects that. Perhaps that rings a bell?
I've pushed another commit that calls our start_tls
method and this indeed works! But I understand if you want to go a different direction with this.
Edit: Alternatively, is there some preamble I must pass before upgrading the connection?
Interesting - I'll go poke around a bit and see what's going on there.
Interesting - I'll go poke around a bit and see what's going on there.
Thanks, for reference the error I see on the server is invalid length of startup packet
, and the exception on the client (probably from our implementation) indicates that the TLS handshake fails.
If the current PR is working, then I don't think we need to actually make any changes to tokio-postgres - you can just define the TlsConnect
implementation in a separate cloudflare-specific crate like we have for e.g. https://docs.rs/postgres-openssl/latest/postgres_openssl/
Ah yes, that makes sense. Thanks!
@sfackler, apologies, I remember why I felt that I needed to contributed upstream. Implementing TlsConnect
requires access to the type private::ForcePrivateApi
which I think is intended to prevent other crates from implementing it. Is there a way around this?
You don't need to override that method: https://github.com/sfackler/rust-postgres/blob/master/postgres-openssl/src/lib.rs#L142-L167
While it may be possible to include a TLS library in Wasm, some environments such as Cloudflare Workers handle TLS origination for you. Today, this appears to not work because once the connection is established,
tokio-postgres
connects to the server in a way that suggests the connection is not encrypted and the server appears to reject the request.This is a proposal solution here, where a library can mark a
Stream
as encrypted with TLS by implementing theTlsStream
trait, and then use aPassthroughTls
struct to indicate totokio-postgres
that it can you the stream as-is, but treat the connection as a TLS connection.Note that I have not actually gotten this to work and don't want to merge yet, because my test server appears to be rejecting the TLS version being used by Workers.
I'm looking for a sanity check on this proposal, or would appreciate any other suggestions for how this could be achieved.