Beta v2.7.0-beta.1 warns > remote_ip's forwarded mode is deprecated

So was just curious to test latest version before the final will release to see if my setup will run flawless when the next big stable release.

I was hit by a deprecated note spamming in console

2023/06/15 13:07:11.168 ←[33mWARN←[0m http.matchers.remote_ip remote_ip’s forwarded mode is deprecated; use the ‘client_ip’ matcher instead

I assume its from running remote_ip forwarded X.X.X.X where we should run remote_ip client_ip X.X.X.X instead?

I did not see any release notes about this, so I was wondering if it was accidentally left out or coming in release notes later on?

1 Like

Close; you use the client_ip matcher instead of remote_ip. Make sure you set trusted_proxies in your global servers options.


We’ll make sure to clarify this in future release notes. Thanks!

1 Like

Ok latest announcement added some info about it being deprecated now, but I’m still on lost ground, no clear instructions for me how it should be added. I failed for hours and lost track, tried all various ways, but never managed to set it up proper.

Here’s an example for caddyfile, could you help sort it out?

(theheaders) {
	header X-Content-Type-Options "nosniff"
	header X-XSS-Protection "1; mode=block"
	header Strict-Transport-Security "max-age=63072000"
	header Cache-Control "no-store, no-cache, must-revalidate, max-age=0"
	header Pragma "no-cache"
	header X-Frame-Options "SAMEORIGIN"
	header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), autoplay=(self), camera=(), encrypted-media=(), fullscreen=(self), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(*), speaker=(), sync-xhr=(), usb=(), vr=()"
	# Prevent search engines from indexing (optional)
	header X-Robots-Tag "none"
	header Access-Control-Max-Age "86400"

	header /* {
} {
	import theheaders

	log {
		format transform "[{ts}] - User={user_id} - X-Forwarded-For={request>headers>X-Forwarded-For} - remote_ip={request>remote_ip} Country={request>headers>Cf-Ipcountry} {request>method} {request>headers>X-Forwarded-Proto} {request>host} {request>uri} {request>headers>Referer>[0]} {request>headers>User-Agent>[0]} - {request>proto} {status} {size} -" {
			time_format "02-01-2006 15:04:05.000"

		output file C:\caddy\logs\ {
			roll true # Rotate logs, enabled by default
			roll_size_mb 5 # Set max size 5 MB
			roll_gzip true # Whether to compress rolled files
			#roll_local_time true # Use localhost time
			roll_keep 2 # Keep at most 2 log files
			roll_keep_days 7 # Keep log files for 7 days

	header X-Real-IP {http.request.header.CF-Connecting-IP}
	header X-Forwarded-For {http.request.header.CF-Connecting-IP}
	header X-Forwarded-Host {http.request.hostport}
	encode gzip

	@blocked {
		not header_regexp User-Agent (?i:Test*|ABC*)
		not remote_ip private_ranges
		not remote_ip forwarded WAN_IP
	handle @blocked {

	@anotherpublic {
		not remote_ip forwarded wan_ip
		not remote_ip private_ranges
		header_regexp User-Agent (?i:Test*|ABC*)

	@anotherlan {
		remote_ip forwarded wan_ip
		remote_ip private_ranges
		header_regexp User-Agent (?i:Test*|ABC*)

	handle {
		@public {
			not remote_ip private_ranges
			not remote_ip forwarded WAN_IP
		basicauth @public {
			user pass

		handle @anotherpublic {
			# reads from @anotherpublic
			handle_path /anotherout
			root * C:\caddy\@file_server\root\anotherout.file
			file_server browse
			rewrite * /anotherout

		handle @anotherlan {
			# reads from @anotherlan
			handle_path /anotherin
			root * C:\caddy\@file_server\root\anotherin.file
			file_server browse
			rewrite * /anotherin
	#SSL Settings
	tls mail {
		dns cloudflare key

You literally just replace remote_ip forwarded with client_ip. And make sure you have trusted_proxies configured in your global options. That’s it. See Global options (Caddyfile) — Caddy Documentation

Ok I’ll try again with a fresh read on this tomorrow, I must have made obvious mistake somewhere…

Thanks gnite :slight_smile:

Yeah sorry I don’t follow it.

I tried adding it under various handles, and on top of all configs, and in beginning of each domainexample

trusted_proxies cloudflare

Getting errors right and left.


caddy run
Error: adapting config using caddyfile: parsing caddyfile tokens for 'servers': Caddyfile:3 - Error during parsing: getting module named 'http.ip_sources.cloudflare': module not registered: http.ip_sources.cloudflare

Error: adapting config using caddyfile: Caddyfile:34: unrecognized directive: trusted_proxies


←[34mINFO←[0m   using adjacent Caddyfile
Error: adapting config using caddyfile: parsing caddyfile tokens for 'handle': getting matcher module 'trusted_proxies': module not registered: http.matchers.trusted_proxies

Then I tested without adding the trusted_proxies cloudflare , but with only changing all cases of remote_ip forwarded to clientip caddy started up, but I was no longer allowed to access from inside my own without giving username password…

If you want to use the cloudflare IP source module, you need to build Caddy with that plugin added. It doesn’t ship with the standard distribution of Caddy.

It’s a separate plugin from the DNS one, even though they are both named cloudflare in your config. They’re different modules used in different places of the config.

1 Like

So I’m kinda confused then… If and when I need to migrate to the newer version I would need to have that cloudflare IP source module ?

I was in the “thought” of that you mentioned trusted_proxies that I needed cloudflare in that?

Why would I need to use trusted_proxies then if I just use not clientip my_wan_ip_here and just use GitHub - caddy-dns/cloudflare: Caddy module: dns.providers.cloudflare

As you can read, you are not going to rid of me that easy because I will 90% fail after the next conversation from you “haha” :smiley:

Yes, if you want to use trusted_proxies cloudflare you need that module. If you use trusted_proxies static <cidrs...> then you don’t need any additional modules.

Because there needs to be a mechanism that verifies that the request actually came from a trusted proxy, otherwise the X-Forwarded-For header could be spoofed by the original client to bypass your matchers.

That’s why remote_ip forwarded is deprecated, there was no mechanism for preventing spoofing, therefore anyone could just craft an HTTP request with their own X-Forwarded-For value which would pass your remote_ip forwarded matcher.

The new client_ip matcher does not have this problem because it specifically relies on trusted_proxies. If the request is trusted, it’ll use the IP parsed from headers, otherwise it will use the remote address (i.e. the IP address attached to the TCP packets).

Since you’re using Cloudflare, you should also set client_ip_headers CF-Connecting-IP (just below trusted_proxies in global options) because Cloudflare doesn’t prevent X-Forwarded-For spoofing. Only their CF-Connecting-IP is safe from spoofing.

1 Like

Ok so I added trusted_proxies under reverse_proxy

trusted_proxies private_ranges and_my_wan_ip_here ← is this correct? for having both the private_ranges where caddy and my wan_ip is ran from being allowed to run internally and bypass.

So it would look like this

trusted_proxies private_ranges wan_ip_x.x.x.x

I then replaced all places found remote_ip forwarded with client_ip

When I try to enter from my home location it still ask for username and password ?

So I was wondering if the other places where I still use remote_ip but without forwarded attached to it should also be changed to client_ip ?

I tried but without any luck.

1 Like

No, you need to use the trusted_proxies global option.

The client_ip matcher doesn’t know about your proxy handler and its config. You need to configure trusted_proxies in global options for it to affect the automatic client IP parsing behaviour.

I wrote about this above already, and linked to the documentation.

1 Like

Ok yes my bad, I was reading various different docs and got it all mixed up.

Now I have done that and added it to the top + i renamed all remote_ip forwarded to client_ip and the rest of fields I could find with just remote_ip leftovers also where renamed to client_ip

	servers {
	trusted_proxies static private_ranges my_wan_ip

It seems to be running but my access without entering credentials on the lan is still not working, where if I simply revert the rename of forwarded change it works.

I then replaced trusted_proxies static private_ranges my_wan_ip with trusted_proxies cloudflare to the servers, after compiling new version with GitHub - WeidiDeng/caddy-cloudflare-ip included

	servers {
	trusted_proxies cloudflare

I can now succesfull connect from via lan without authentication.

But I’m not sure if this is the correct way(in my head when I think of adding cloudflare as trusted_proxies I think of it as all clients connected through cloudflare now, does not have to enter any authentication details?, and how if I want to add private_range and my wan_ip into the trusted_proxies at the same time as cloudflare is included into it, how would that look like?

trusted_proxies static private_ranges cloudflare

Just give errors.

1 Like

trusted_proxies configures which proxies are trusted to have correctly handled X-Forwarded-For (or whatever header you configure with client_ip_headers) such that those headers are trusted sources of the real client IP. You’re not trusting your actual client IP, you’re trusting the proxy.

This doesn’t make sense, because your proxy is Cloudflare, not something running locally (i.e. private ranges) and the proxy is not your client.

This is better because it trusts cloudflare’s IP ranges, i.e. what they list at

As I explained in my first paragraph, that doesn’t make sense.

Also, quoting myself from earlier, you should also do this:


I’m one of those who needs to be slapped in the head and feeded a bit more before I understand it, even tho sometimes its all in front of you.

Thanks for the patience and time, its working now and thanks I added the client_ip_headers CF-Connecting-IP below trused_proxies


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