cloudflare/pingora

Be able to get the SNI from the HTTP filter context

Open

#547 opened on 2025年3月2日

GitHub で見る
 (2 comments) (0 reactions) (0 assignees)Rust (26,634 stars) (1,642 forks)batch import
enhancementgood first issue

説明

What is the problem your feature solves, or the need it fulfills?

I would like to be able to get the SNI when in the req_filter() callback, so that I can do some business logic on it with the HTTP HOST header.

Describe the solution you'd like

In the self or more likely the session, store the SNI (e.g. in the downstream session) so it can be retrieved. The SSL Digest is available in the req_filter and that would be a suitable place to put it. (session.digest();)

Describe alternatives you've considered

I tried to dive into the stream and get to the get_ssl() function, but was unable to figure out how (or if it is possible) to downcast stream to the SslStream.

if let Some(stream) = session.stream() {
    println!("session stream: {:?}", stream);
    println!("Actual type of stream: {}", std::any::type_name_of_val(&stream));
    // downcast it somehow
    // then
        if let Some(ssl) = ssl_stream.get_ssl() {
            if let Some(sni) = ssl.servername(pingora::tls::ssl::NameType::HOST_NAME) {

but the 5-6 methods I tried for downcasting didn't work. It would also be a lot of insider baseball even if it did work and likely fragile.

Additional context

From looking at the code, the SNI is not extracted anywhere. It is available in the TLS callback via a call to the underlying ssl instance but since there's no HTTP context there's no place to put it.

#[async_trait]
impl pingora::listeners::TlsAccept for DynamicCert {
    async fn certificate_callback(&self, ssl: &mut pingora::tls::ssl::SslRef) {
        // Inspect the SNI
        if let Some(sni) = ssl.servername(pingora::tls::ssl::NameType::HOST_NAME) {
            println!("SNI: {}", sni);
        }
        ext::ssl_use_certificate(ssl, &self.cert).unwrap();
        ext::ssl_use_private_key(ssl, &self.key).unwrap();
    }
}

It's possible I missed an ext field somewhere where the SNI could be stuffed.

コントリビューターガイド