Args in remote_ip matcher?

1. Output of caddy version:

v2.6.0 h1:lHDynvM+sTOi9Aq4Y15b4FtkqzPB36WbUrZvVdwzTCA=

2. How I run Caddy:

docker

a. System environment:

docker

b. Command:

caddy docker-proxy --caddyfile-path /etc/caddy/Caddyfile

c. Service/unit/compose file:

d. My complete Caddy config:

(auth) {
        @check_auth_except {
                expression `"{args.0}" == "auth_except"`
                not remote_ip forwarded 10.1.1.1/32 10.2.2.2/32
                #not working
                # not remote_ip forwarded {args.1}
        }
        basicauth @check_auth_except {
                import /etc/caddy/htpasswd/passwords
        }
}
(tmpl_except) {
        import auth auth_except 10.1.1.1/32
        #import auth auth_except "10.1.1.1/32 10.2.2.2/32"
}
{$MY_HOSTNAME} {
    import tmpl_except
}

3. The problem I’m having:

It looks like I can’t use args in the remote_ip matcher
If it does work, how could I send multiple IPs in the same arg?

4. Error messages and/or full log output:

{"level":"error","ts":"2022-09-28T07:34:26.634Z","logger":"docker-proxy","msg":"Error response from server","server":"localhost","status code":400,"body":"{\"error\":\"loading config: loading new config: loading
 http app module: provision http: server srv0: setting up route handlers: route 0: loading handler modules: position 0: loading module 'subroute': provision http.handlers.subroute: setting up subroutes: route 3:
 loading matcher modules: module name 'not': provision http.matchers.not: loading matcher sets: module name 'remote_ip': provision http.matchers.remote_ip: invalid IP address: '{args.2}': ParseAddr(\\\"{args.2}\
\\"): unexpected character (at \\\"{args.2}\\\")\"}\n"}

5. What I already tried:

Tried {args.2}, “{args.2}”, `{args.2}`

6. Links to relevant resources:

This works just fine for me:

(auth) {
	@check_auth_except {
		expression `"{args.0}" == "auth_except"`
		not remote_ip forwarded {args.1}
	}
	respond @check_auth_except 403
}

(tmpl_except) {
	import auth auth_except 10.1.1.1/32
}

:8881 {
	import tmpl_except
}

The config you posted doesn’t match the error you showed. So I don’t understand the issue.

You can’t, because they need to be separate args. But, you can use the new functionality in v2.6.0 to use an expression matcher to do it instead, with pure text instead of Caddyfile tokens:

(auth) {
	@check_auth_except `"{args.0}" == "auth_except" && !remote_ip({args.1})`
	respond @check_auth_except 403
}

(tmpl_except) {
	import auth auth_except `"10.1.1.1/32", "10.2.2.2/32"`
}

:8881 {
	import tmpl_except
}

This uses the new shortcut expression matcher syntax, where you can omit expression if the token immediately following the named matcher is a quoted token.

Obviously this is a bit janky because you need to construct a string that can get inserted into the expression matcher in your import args, but it should work just fine.

That said, keep in mind that the forwarded mode of remote_ip is insecure, be very careful with it. Anyone can spoof this value by setting their X-Forwarded-For request header to whatever IP address they want.

2 Likes

Thank you, @francislavoie !

I hape no idea where and what I was doing wrong, just getting your example and applying to my setup made it work perfectly.

Moreover, I am also able to use the caddy docker proxy plugin to sent the excepted IP list with the docker labels and it works as well.

In the docker-compose for the container I need to be proxied:

services:
  web:
    ...
    labels:
      caddy: subdomain.example.com
      caddy.import: tmpl_except_these {{index .Names 0}} password_file `"2.2.2.2/32", "1.1.1.1/32"`

and in caddy config:

(rev_proxy) {
	reverse_proxy {
		to {args.0}
		header_down -Server
	}
}
(auth) {
	@check_auth expression `"{args.0}" == "auth_enabled"`
	@check_auth_except `"{args.0}" == "auth_except" && !remote_ip({args.2})`
	basicauth @check_auth {
		import /etc/caddy/htpasswd/{args.1}*
	}
	basicauth @check_auth_except {
		import /etc/caddy/htpasswd/{args.1}*
	}
}

(tmpl_except_these) {
	import rev_proxy {args.0}
	import auth auth_except {args.1} {args.2}
}
1 Like

Cool, glad it works :+1:

You can simplify this one to match, remove expression there too:

@check_auth `"{args.0}" == "auth_enabled"`
1 Like

Will do, thank you!

Re forwarded issue, I wonder if there is a way to define the trusted sources for X-Forwarded-For.
Nginx does it through set_real_ip_from.

Not for the remote_ip matcher, currently. It is possible for the reverse_proxy though:

1 Like

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