caddy: http.request.tls.client.* placeholder broken for Caddy 2.6.3+

Let me first say thanks for this awesome product ! The bug I am about to “complain” is rather a first world problem^^

I am using following matcher to decide whenever I am on a “safe” client (with installed client certificate) or some “public” machine (fallback to Authelia):

        @missing_mTLS_cert {
                expression {tls_client_subject} == null
        }
        
        forward_auth @missing_mTLS_cert ... {
                ....
        }        

Everything was working fine until 2.6.3 … Starting from this version it become unstable… Now even with a valid certificate it randomly fails (placeholder not set (?)). forcing me to login with Authelia …

Thanks!

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Reactions: 1
  • Comments: 28 (15 by maintainers)

Most upvoted comments

Dear all:

Thank you all for this thread. For me, the issue is that I was using {http.request.tls.client.certificate} instead of {http.request.tls.client.certificate_der_base64}.

So thank you for your time, @mholt

Greetings and best wishes!

Notice that I’ve changed the placeholder to {http.request.tls.client.certificate_der_base64} to get a value valid for headers.

Yeah long story, I used a mod by someone in a different issue to get around this since Caddy doesn’t wrap certs in escape characters–it was unrelated to the issue so I didn’t want to bog down my already-wordy paragraphs with extraneous details.

The extra Client cert: {http.request.tls.client.certificate_der_base64} at the end is normal because of the --next https://localhost request which makes a second request without client auth.

This is a lack of an understanding of how curl processes the --next request on my side then.

Let’s put a pin in this for now. I will do more testing on my side and see if I can recreate the issue I am having in the web browsers I tested with curl, instead. The workaround for now is to disable HTTP3, which allows users to successfully use require_and_verify. I will also see if this behavior occurs with other web servers (Nginx, Apache, etc.) to see if it’s an issue that is only related to web browsers.

I think the issue should be left as open with needs info. I will update as soon as I can, likely after Hacker Summer Camp. Sorry for the delays on my end.

ALCON,

I am having the same issue where Caddy v2.6.4 only sometimes passes the client certificate to the backend server (in my case, Keycloak, but it shouldn’t matter whether it’s Keycloak, Authelia, or Authentik). Note that this issue only occurs if H3 is enabled and verify_if_given is used. If require_and_verify is used, this issue doesn’t occur. Below is my Caddyfile

{
    log {
        level debug
    }
    servers {
        protocols h1 h2 h3
    }
}

(client_auth) {
    tls {
        client_auth {
            mode verify_if_given
            trusted_ca_cert_file /certs/ca/root_ca.crt
            trusted_ca_cert_file /certs/ca/intermediate_ca.crt
        }
    }
}

keycloak.secure.local {
    import client_auth
    reverse_proxy 127.0.0.1:8080 {
        header_up SSL_CLIENT_CERT {http.request.tls.client.certificate_pem}
    }
}

Attached here is my debug log. Note that I removed the following from the logs, do let me know if it is an issue:

  1. The client certificate itself has been removed. All instances that contain certificate data have been replaced with “[CERT_DATA]”
  2. Any references to the server certificate. I can’t release this at this time, but if it’s required I’ll stand up a separate environment with releasable server certificate data.

Another difference is I cannot recreate the issue with curl. It seems to only occur with browsers (Firefox, Chrome) and only sometimes. I know this is unhelpful. I will also try the latest alpha version, as well, and comment here.

@francislavoie You are right! I don’t see any http3 requests when testing with 2.6.2.

2 6 2

The behavior changed with 2.6.3+

2 7 0 b (302 is the Authelia redirection)

but afterwards with http3 requests i only see placeholder strings “{http.request.tls.client…}” returned.

Hmm. So you’re saying it seems broken for H3 requests but it works fine for H1/H2? Okay. Are you sure it worked with H3 with prior versions? I’m trying to understand what you’re actually describing as broken and when.

Please try v2.7.0-beta.1, we’ve made a lot of changes since 2.6.4, some of which may have already fixed it.