[Rust Frontend] Add static HTTPS and mTLS support for HTTP and gRPC#45890
Conversation
Signed-off-by: Tahsin Tunan <tahsintunan@gmail.com>
Signed-off-by: Tahsin Tunan <tahsintunan@gmail.com>
|
Hey @BugenZhao, I got the context from #46052 and reworked this to use OpenSSL ( |
Signed-off-by: Tahsin Tunan <tahsintunan@gmail.com>
Signed-off-by: Tahsin Tunan <tahsintunan@gmail.com>
|
Thanks @tahsintunan! Could we have the grpc server use the same TLS config? Also can we have a handshake timeout? (but keeping the handshake async) |
…tend Signed-off-by: Tahsin Tunan <tahsintunan@gmail.com>
Signed-off-by: Tahsin Tunan <tahsintunan@gmail.com>
|
Thanks @njhill! Went through your notes. Done:
On gRPC over TLS: yes, we can reuse the same TLS config, but I'd like to run through one thing before implementing. gRPC has no auth today (same as Python's insecure gRPC server), so plain server TLS would just encrypt an otherwise-open endpoint. And when HTTP binds a TCP host, gRPC uses the same host (just a different port), so a public HTTP bind exposes gRPC there too. Right now the only thing that can actually check who's calling is mTLS (client certificates, So we have these options:
Wdyt? |
There was a problem hiding this comment.
Just realized there's no built-in support for using TLS in axum... Would you help to check it out whether this library can be used to simplify implementation on our side?
Also it would be better we're agnostic about OpenSSL but only target native-tls, which can be backed by security-framework on macOS.
There was a problem hiding this comment.
Thanks, good call. I've switched the TLS termination over to tls-listener so the server side is a lot smaller now. (I also looked at axum-server since it's more widely used, but it's HTTP-only and wouldn't cover gRPC, whereas tls-listener wraps any stream, so it handles both.)
On native-tls instead of OpenSSL: it doesn't work for the server, because no mTLS. native-tls's acceptor has no client-cert verification (just cert+key, version, ALPN), so --ssl-cert-reqs can't be expressed on any backend. (rustls could, but we're keeping that out.)
Also, the Python frontend is OpenSSL as well (CPython's ssl is an OpenSSL binding), so staying on OpenSSL won't be a regression.
There was a problem hiding this comment.
On
native-tlsinstead of OpenSSL: it doesn't work for the server, because no mTLS.native-tls's acceptor has no client-cert verification (just cert+key, version, ALPN), so--ssl-cert-reqscan't be expressed on any backend. (rustlscould, but we're keeping that out.)
Good observation. Add a link to the original issue for reference: rust-native-tls/rust-native-tls#161
|
Thanks @tahsintunan ... I think for now we should just apply the same TLS configuration to the gRPC endpoint as the http one. In the python case we should also do that. I don't think mTLS should be required. But if configured then it should be enabled on both endpoints. |
…a --args-json Signed-off-by: Tahsin Tunan <tahsintunan@gmail.com>
…rate Signed-off-by: Tahsin Tunan <tahsintunan@gmail.com>
Signed-off-by: Tahsin Tunan <tahsintunan@gmail.com>
|
Thanks @njhill. I've got gRPC using the same TLS config as HTTP now. mTLS isn't required, but if |
Signed-off-by: Tahsin Tunan <tahsintunan@gmail.com>
njhill
left a comment
There was a problem hiding this comment.
Thanks @tahsintunan! LGTM.
I will let @BugenZhao also give a final approval.
It would be great to support cert rotation as a follow-on, for parity with the python-side functionality.
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
There was a problem hiding this comment.
Generally LGTM. Thanks for the work!
I just felt we could simplify a bit on current impl, especially that we seem to mix orthogonal layers together (like socket type / TCP_NODELAY / TLS / socket type / HTTP vs gRPC) , making the code a bit hard to read.
I've pushed some commits to simplify it, and probably I'll open some follow-up PRs for further refactoring.
…llm-project#45890) Co-authored-by: Bugen Zhao <i@bugenzhao.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Signed-off-by: Tahsin Tunan <tahsintunan@gmail.com> Signed-off-by: Bugen Zhao <i@bugenzhao.com>
…llm-project#45890) Co-authored-by: Bugen Zhao <i@bugenzhao.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Signed-off-by: Tahsin Tunan <tahsintunan@gmail.com> Signed-off-by: Bugen Zhao <i@bugenzhao.com>
|
Follow-up cert rotation PR: #47362 |
…llm-project#45890) Co-authored-by: Bugen Zhao <i@bugenzhao.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Signed-off-by: Tahsin Tunan <tahsintunan@gmail.com> Signed-off-by: Bugen Zhao <i@bugenzhao.com> Signed-off-by: wang.yuqi <yuqi.wang@daocloud.io>
Summary
--ssl-certfile,--ssl-keyfile,--ssl-ca-certs,--ssl-cert-reqs(0/1/2), and--ssl-ciphers. A combined cert+key PEM works (the key falls back to the certfile), mirroring uvicorn.openssl/tokio-openssl), reusing the OpenSSL already in the tree via native-tls. Introduces no new rustls.--grpc-portserver reuses the same TLS config (plus ALPNh2for HTTP/2). It now binds127.0.0.1instead of0.0.0.0on the unix-socket / inherited-fd path, so the unauthenticated service isn't exposed on all interfaces.VLLM_HTTP_TIMEOUT_KEEP_ALIVE, default 5s,0disables). gRPC adds HTTP/2 keepalive (gRPC-core/Python defaults). Stops stalled or idle connections from piling up.Notes
--ssl-ciphersis applied with OpenSSL'sset_cipher_list(TLS 1.2 and below), the same as Python'sssl.set_ciphers; an invalid value errors at startup. Without it, the default is theopensslcrate'smozilla_intermediate_v5baseline (forward-secret AEAD, TLS 1.2 floor, server cipher preference), slightly stricter than uvicorn and overridable via--ssl-ciphers.--features vendoredproduces a self-contained binary (server + client OpenSSL bundled). No runtime flag.--ssl-ca-certs. A key-without-cert/ unreadable/malformed PEM errors clearly at startup, and the keep-alive timeout also bounds the request-header read from the first byte, dropping silent/slow clients (uvicorn only bounds the wait between requests).--ssl-cert-reqsis set. Applying TLS to Python's gRPC is a follow-up.--enable-ssl-refresh) stays unsupported. A follow-up will reload the cert files into theSslContextand add a file watcher. No listener API change needed.engine-core-client(an abort-burst test surfaced by the main merge).Divergence:
opensslcrate'smozilla_intermediate_v5baseline (forward-secret AEAD suites, TLS 1.2 floor, server cipher preference), which is slightly stricter than Uvicorn's default. I chose it because it is the crate's recommended, maintained policy and the stronger default.--ssl-ciphersstill overrides it for full control.