Cloudflare Tunnel with Caddy - problem with config

I’ve tried two:

1

  - hostname: '*.mydomain.net'
    service: https://<caddy_lxc_ip>:443
    originRequest:
      noTLSverify: true
      originServerName: '*.mydomain.net'
      httpHostHeader: '*.mydomain.net'

2

  - hostname: 'serviceX.mydomain.net'
    service: https://<caddy_lxc_ip>:443
    originRequest:
      noTLSverify: true
      originServerName: '*.mydomain.net'
      httpHostHeader: '*.mydomain.net'

Both of them result on the white page without errors and the last block of the debug I’ve mentioned here

At this point, and given the logs and the config, I think the request is processed by this config block

because the Host passed from cloudflared is literally *.mydomain.net, which falls within the wildcard of *.mydomain.net in Caddy.

I don’t use cloudflared and not faamiliar with its config much, so you’ll have to figure out how to have it pass the same Host name received.

1 Like

@danluckner did you try omitting the httpHostHeader setting?

2 Likes

Yes, I have.

This is the log when that condition is applied. And the cloudflare tunnel throws in a Host error.

What’s in your cloudflared config now?

I am using service: https://localhost here and it’s passing all hosts through with correct SNI ok. I’m not using Caddy in this config but the desired result is the same.

This:

ingress:
    - hostname: '*.mydomain.net'
      service: https://<caddy_lxc_ip>:443
    - servce: http_status:404

Guys, I appreciate all of your inputs, but it seems that Caddy does not work for what I want to do.

I’m simply moving on and keep using NPM for now and keep monitoring if a Caddy update comes around that fits my setup.

Otherwise, I think we tried everything possible and it just won’t work, unless I use an insecure setting.

You still need the matchSNItoHost: true directive.

To not leave any doubt, this what I have configured:

Caddyfile:

{
    debug
    auto_https prefer_wildcard
}

*.mydomain.net {
	tls {
		dns cloudflare {env.CLOUDFLARE_API_KEY}
	}
}

serviceX.mydomain.net {
    reverse_proxy <serviceX_ip>:<serviceX_port>
}

serviceY.mydomain.net {
    reverse_proxy <serviceY_ip>:<serviceY_port>
}

Cloudflared:

tunnel: UUID
credentials-file: /etc/cloudflared/UUID.json

ingress:
  - hostname: '*.mydomain.net'
    service: https://<caddy_lxc_ip>:443
    originRequest:
      matchSNItoHost: true
  - service: http_status:404

I’m able to access serviceX once, but when I try to access serviceY, my browser throws an HTTP ERROR 421, and this is what Caddy shows in the debug:

2025/02/27 19:47:07.785 DEBUG   http.log.error  strict host matching: TLS ServerName (serviceX.mydomain.net) and HTTP Host (serviceY.mydomain.net) values differ       {"request": {"remote_ip": "<cloudflared_lxc_ip>", "remote_port": "41664", "client_ip": "<cloudflared_lxc_ip>", "proto": "HTTP/1.1", "method": "GET", "host": "serviceY.mydomain.net", "uri": "/", "headers": {"Accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"], "Cache-Control": ["max-age=0"], "Cf-Visitor": ["{\"scheme\":\"https\"}"], "Accept-Encoding": ["gzip, br"], "Cf-Warp-Tag-Id": ["<cf-ward-tag-id>"], "Priority": ["u=0, i"], "Connection": ["keep-alive"], "Sec-Fetch-User": ["?1"], "Cdn-Loop": ["cloudflare; loops=1"], "Cf-Connecting-Ip": ["<cf-conneting-ip>"], "Sec-Fetch-Dest": ["document"], "User-Agent": ["Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Mobile Safari/537.36"], "Sec-Fetch-Site": ["none"], "Upgrade-Insecure-Requests": ["1"], "X-Forwarded-Proto": ["https"], "Sec-Ch-Ua": ["\"Not(A:Brand\";v=\"99\", \"Google Chrome\";v=\"133\", \"Chromium\";v=\"133\""], "Cf-Ray": ["<cf-ray>"], "Sec-Ch-Ua-Platform": ["\"Android\""], "Accept-Language": ["en-US,en;q=0.9"], "X-Forwarded-For": ["<x-forwarded-for-ip>"], "Sec-Fetch-Mode": ["navigate"], "Cf-Ipcountry": ["US"], "Sec-Ch-Ua-Mobile": ["?1"]}, "tls": {"resumed": false, "version": 772, "cipher_suite": 4865, "proto": "", "server_name": "serviceX.mydomain.net"}}, "duration": 0.000038972, "status": 421, "err_id": "jx0m9jf0t", "err_trace": "caddyhttp.(*Server).enforcementHandler (server.go:479)"}

Hmm, it sounds like a cloudflared bug possibly. There’s one comment here which sounds similar: Pass SNI to origin + Istio ingress gateway · Issue #541 · cloudflare/cloudflared · GitHub

In that case, switching to nginx won’t help. But I can’t reproduce the problem with Apache HTTPD.

1 Like

Also, you could consider just using HTTP rather than HTTPS between cloudflared and Caddy, unless you particularly need this to be encrypted.

Honestly, I don’t need it to be encrypted since the containers are running on the same Proxmox instance. But when I change the cloudflared config to service: http://<caddy_lxc_ip>, it doesn’t even reach the Caddy instance. I see no entries in the Caddy debug and when I try to reach serviceX.mydomain.net or serviceY.mydomain.net through Cloudflare tunnel, my browser throws this error: ERR_TOO_MANY_REDIRECTS.

There is no changes in my configs, except for the http instead of https.

And about this:

That is part that surprises me, because when I change cloudflared to point to NGINX Proxy Manager, it works. Also, when accessing the services locally, through my AdGuard Home DNS server pointing to Caddy, it also works. It is just the cloudflared and caddy pairing that won’t work, as I mentioned here:

You could debug that with curl -v.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.