How to change request headers for an authentication handler? Getting Flyio, Caddy, and caddy-tailscale plugin to play nice

1. The problem I’m having:

I’m hoping to be able to change the request headers before reaching the authentication handler.

I’m using the caddy-tailscale plugin as the authentication handler. The caddy-tailscale plugin is expecting a Remote-Addr header. I’m also using Flyio which passes the client ip in a Fly-Client-Ip header. I need to modify the Remote-Addr header to have the value of the Fly-Client-Ip.

When I add the headers handler portion I start getting Could not proxy HTTP request. Retrying in 24 ms (attempt 1) which I think means Caddy isn’t getting any response. Without the headers handler Caddy accepts requests but is using the wrong Remote-Addr value with caddy-tailscale plugin.

Is there something I’m doing wrong in Caddy or is this on the caddy-tailscale plugin side of things? If I can just make sure I’m doing things correctly in Caddy it will help me know where I should be debugging :slight_smile:

2. Error messages and/or full log output:

Could not proxy HTTP request. Retrying in 24 ms (attempt 1)

3. Caddy version:

2.6.4

4. How I installed and ran Caddy:

a. System environment:

Dockerfile → Flyio VM

b. Command:

caddy run --config /config/caddy/caddy.json

c. Service/unit/compose file:

d. My complete Caddy config:

{
  "apps": {
    "http": {
      "servers": {
        "srv0": {
          "listen": [
            ":8080"
          ],
          "routes": [
            {
              "handle": [
                {
                  "handler": "subroute",
                  "routes": [
                    {
                      "handle": [
                        {
                          "handler": "authentication",
                          "providers": {
                            "tailscale": {}
                          }
                        },
                        {
                          "handler": "headers",
                          "request": {
                            "set": {
                              "Remote-Addr": [
                                "{http.request.header.Fly-Client-Ip}"
                              ]
                            }
                          }
                        },
                        {
                          "handler": "headers",
                          "request": {
                            "set": {
                              "Remote-Port": [
                                "{http.request.header.Fly-Forwarded-Port}"
                              ]
                            }
                          }
                        }
                      ]
                    },
                    {
                      "handle": [
                        {
                          "handler": "static_response",
                          "status_code": 200
                        }
                      ],
                      "match": [
                        {
                          "host": [
                            "my-api.com"
                          ]
                        }
                      ]
                    }
                  ]
                }
              ],
              "terminal": true
            }
          ]
        }
      }
    }
  }
}

5. Links to relevant resources:

The headers handler sets response headers, not request headers. If you want to change the request, use request_header instead. It works the same way.

Also, you can merge your two header handlers, put both headers you want to apply in set.

Where are you seeing that? That’s not an error from Caddy.

I used this Caddyfile to generate but in the json it creates the headers handlers. What does it look like to use request_header in the json directly?

{
  order tailscale_auth after basicauth
}

:8080 {
	@my-api.com {
		host my-api.com
	}

	request_header Remote-Addr "{http.request.header.Fly-Client-Ip}"
	request_header Remote-Port "{http.request.header.Fly-Forwarded-Port}"
	
	tailscale_auth

	respond @my-api.com 200 {
		close
	}
}

Ah that error must be from the Flyio side of things then. It must have been on Fly that I read it gives that response if there’s no response from the server it proxies to, so I just know usually when I have a bad Caddy config I get that error and that it means Caddy is not giving a response. That’s been my understanding so far at least.

Oh my bad, I’m too used to Caddyfile, I forgot that in JSON there’s one handler for headers which does both request and response manipulation. See JSON Config Structure - Caddy Documentation

Well, your Caddyfile doesn’t really do anything right now. It just authenticates, then writes an empty 200 status response, closing the connection. Are you sure that’s what you wanted?

Also, seeing your Caddyfile, what order did you expect it to run in? See the JSON, the handlers run top-down in the order they appear in the JSON. The Caddyfile sorts directives according to the directive order Caddyfile Directives — Caddy Documentation

Take a look at Caddy’s logs, enable the debug global option.

I’ve found out that http.request.RemoteAddr does not come from headers. This is just how it worked in the Tailscale nginx-auth library. I’ll need a different approach here :slight_smile:

I am doing that just to test authentication as simply as possibly. So far I have not been able to get the 200 response.

Ah thank you for the tip about directives, I’ll go through that. I definitely did not realize.

Edit: Looks like maybe this could help? And then I could pass that client_ip value in the caddy-tailscale plugin if that’s how it works? fly-proxy being the trusted proxy here.

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