RemoteAddr and Caddy v2 - help needed

According to @Mohammed90 I think you can do {request>headers>X-Forwarded-For>[0]} to grab the first element in the array, but you’ll need to try it out and see.

Regarding the realip module, someone just needs to implement it. It’s quite simple, so you might be able to do it yourself if you need:

This is the v1 plugin, it would just need to be ported to v2’s plugin system:

Thanks for the reply. Unfortunately I think I will have to go the route of porting the realip module since IP tables only has the ability to look at RemoteAddr.

I will give it a shot this evening.

Is there any reason the v1 realip plugin can’t be done in v2 simply by using the remote_ip matcher? Is it just setting RemoteAddr?

Yeah, nothing in vanilla Caddy allows for overwriting the r.RemoteAddr right now. We’d need a handler to do it. The rest of the realip plugin is just setting up a whitelist for trusted IPs, which can just be done with the remote_ip matcher anyways.

1 Like

Ah right. Why does that matter, again? RemoteAddr is an internal construct, not something that external apps can access. They only read headers and stuff, so why is overwriting RemoteAddr specifically so crucial?

It makes other pieces of the Caddy pipeline (logs, other plugins) not need to also support handling X-Forwarded-For (which requires parsing the array of headers plus the comma separated IP values, non-trivial to add support for that everywhere).

Matt, I’m a total noob to this stuff so I apologize if I’m wrong or mis-speaking but my understanding is that IP tables can ONLY read RemoteAddr with packets that have end to end SSL, such as my case.

@francislavoie @matt

View my work on porting @captncraig original “realip” plugin over to v2:

It compiles just fine, moving over to testing now!

Cool! I think you’ll need to update your go.mod to point to Caddy v2, it’s still pointing to Caddy v1 currently.

Also please don’t forget to add a LICENSE file to your repo.

Once it’s working, you can sign up for an account here and register your plugin so it shows up in the download page for others to use it :smile:

Just as an aside, I noticed you made, did you consider making a PR against the upstream repo with your change instead of just forking it? That way others could benefit from your changes. I didn’t look at what exactly you changed though, just a thought.

1 Like

Thank you for the heads up, its been a long night.

Also, regarding my changes to format-encoder, I just added one line to format the time to something other than the plugin default of UNIX-micoseconds. I am just now learning how to use github and what repos are etc, so honeslty I didn’t even know that was an option.

Once I get realip functioning I will try to add proper license files and tie them back to the parent repo so others can see what I’ve been working on.

1 Like


Its working!!! Very happy and excited about it. I wouldnt have even attempted were it not for your suggestion so thank you. I will register the plugin so hopefully others can see it to benefit from.

Since so much code changed, I cant really add this as a ‘fork’ of the original plugin correct? What is the best way to get this out there? Ive seen quite a few posts asking about this so just want to make sure anyone who could use it or even make it better is aware.

1 Like

The repo you have is fine. The attribution to the original implementation is enough. Forking is really just a button in github that makes a linked clone of a repo, it’s not something you have to do.

Adding it to the page is probably enough for visibility.

Understood. However, I am unable to register the module with the following error code:


Any ideas? @matt


Hey, sorry to bother about this again. Hoping you may be able to help with an issue. So, it seems to be working OK and i’m not sure if this issue is just me having wrong expectations or if there is a fix. See log output below:

"X-Forwarded-For":["<MY ACTUAL IP>"],
"If-Modified-Since":["Sat, 17 Oct 2020 04:21:41 GMT"],
"Cf-Connecting-Ip":["<MY ACTUAL IP>"],
"common_log":"<MY ACTUAL IP> - - [01/Nov/2020:18:14:31 +0000] \"GET / HTTP/1.1\" 304 0","duration":0.000420325,"size":0,"status":304,"resp_headers":{"Referrer-Policy":["no-referrer-when-downgrade"],"Strict-Transport-Security":["max-age=31536000;"],"X-Frame-Options":["DENY"],"Etag":["XXXX"],"Server":["Caddy"],"X-Content-Type-Options":["nosniff"],"X-Xss-Protection":["1"]}}

So, initially “request>remote_addr” is incorrect because is a cloudflare IP. However the common_log output shows the correct output with ? Is this because I am loading in the realip directive too late, if not how can I get the “request>remote_addr” value to be corrected like what common_log is giving me?

Ah, that’s because the LoggableHTTPRequest is created before the request is passed through the handlers, so any changes to the request aren’t reflected in the logs.

The common_log field is created after the handlers though, because it needs the response size and status. So it does get the right value.

This isn’t a problem if all you care about is subsequent handlers having the right value, because they will; it’s just not updated in the logs.

I’m not sure there’s anything you can do in your plugin to fix the log output without a change to Caddy.

@matt what do you think?

I see. That makes sense.

Honestly, at this point I dont think what I want to do is even possible. Keeping in mind I’m learning as I go, but my intention has been to correct “request>remote_addr” so that IP tables can see the correct IP and block accordingly, but my entire approach is flawed because caddy is what I’m relying on to do the IP correction which only happens after the packet is passed through IP tables. So, I think I need to find another solution.

@francislavoie @matt

This will be my last post on this thread but thought I would keep you two in the loop incase this comes up in the future. I figured it out. Just needed to configure fail2ban to use cloudflare API to ban the actual client IP instead of using IP tables at all.

All is working just as I wanted at this point. Turns out, I didn’t even need to port “realip” since I was successfully using “format-encoder” to get my access logs corrected before starting. But regardless, it may be useful to others so I will keep up with it.

Thank you both for your help!

1 Like


Since you seem to have figured out how to use fail2ban, do you think you’d be interested in writing a wiki article explaining how to use it alongside Caddy?

There have been quite a few people asking how, but I don’t use it so I haven’t been able to point them in the right direction.

Most definitely! May take me a couple days to find the time to get it written out but I would love to do that. The more guidance out there the better.


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