Remote_ip behaviour

I just wanted to drop a note to help anyone else. I’ve been confused for hours on end about how to make a remote_ip matcher work. I expected the functionality to act on the connected IP, but it seems to actually take effect on the “X-Forwarded-For” header, which could still be useful, but the docs should make this clearer.

Thanks!

1 Like

Good point! I’ll clarify that in the docs. Update: Done in https://github.com/caddyserver/caddy/commit/b8a799df9f58cf3ccc2577a37c2b561d2a3e72bd – note that the Caddyfile docs were already updated but the site has not been deployed since it is a recent addition.

Is the current behavior going to be a problem? (We find that most users want it to match X-Forwarded-For.) What is your use case?

Thanks Matt. I don’t see it as a problem, I think in most cases it’s really helpful and it’s the quickest way I’ve seen to achieve the goal.

It doesn’t suit my use case though as I specifically want to act on the connecting IP to ensure the request comes in via Cloudflare.

So how are you working around that? (You’re not using IP addresses as authentication right?)

No its not ‘authentication’, just access control. Typically I’d have no issues doing that job on a firewall, but the site I’m working on now is just a hobby and I’m trying to make is as compact as possible. I can do it on my router but its a bit of custom hack that wont persist.

I could see this potentially being useful to other people in microservice containers which typically wouldn’t have firewalls at such a granular level.

I mean, that is the same thing :upside_down_face: You have to trust that the remote IP is really that IP, which is a form of authentication. It’s using a username without a password to control access.

I’ll add an option to the matcher to do a direct match rather than using the forwarded IP as the reference. Would you be willing to try out a PR/commit?

Well actually

Authentication = verify who you are

Authorization = verify what you’re allowed to do

Okay, I’ll bite: “Access control” = control who is allowed to access.

Who = IP address

Control = Access

The matcher is kind of being used for both here.

Fair enough, I think of an IP address more of an attribute a user has rather than their identity itself. But the line is blurry. :man_shrugging:

@nialfrancis I’ve pushed a commit here that I want you to try: https://github.com/caddyserver/caddy/commit/deedf8abb036bdc096360bd6f06df17a6cff9799

It adds a forwarded option to the remote_ip matcher; if true, it will read the X-Forwarded-For header; otherwise it will use the immediate peer’s IP. I also decided this is a safer default (though obviously not foolproof) and that relying on the header value by default is not a good idea. Nor was it ever really documented, as you pointed out in this thread.

Anyway, the default is now to use the immediate peer’s IP and only optionally to read it from X-Forwarded-For.

I’m with @francislavoie on this, it is authorisation. If the definition of authentication included this then a port binding or a firewall policy would also be authentication.
Plus, used correctly there should also be an authorisation layer after the remote_ip match, caddy could even provide this auth itself.

Thanks for the change though Matt, very happy to test it later today. Are you sure you want to change the default though? This will be a breaking change for anyone using it currently with NAT or a proxy.

1 Like

Agreed, this is good for that: https://github.com/greenpau/caddy-auth-portal

Yes, because the behavior was never documented, thus not defined; and it is arguably a bug. It shouldn’t be the default. And it is not a secure default. So the change is warranted I think.

Hello @matt, I’ve done a few quick tests and this is working well. Thanks a lot!

2 Likes

Thanks for confirming!

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