Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prefer Cloudflare IP header instead of X-Forwarded-For #905

Open
ChokunPlayZ opened this issue Oct 1, 2023 · 7 comments
Open

Prefer Cloudflare IP header instead of X-Forwarded-For #905

ChokunPlayZ opened this issue Oct 1, 2023 · 7 comments
Labels
enhancement New feature or request server Relates to the main binary (server or client)

Comments

@ChokunPlayZ
Copy link

💡 Idea
I think there's not many configs like mine where the setup involves multiple reverse proxy (in my case NGINX and Cloudflare)
the current "behind proxy" setting cause issue because
NGINX attach 2 IP in the forwarded for header, ntfy always prefer the wrong one (the last one)
instead there's the Cloudflare's Cf-Connecting-Ip which is more accurate than the X-Forwarded-For header
it would be great if this could be added

or an alternative fix, if there is multiple IP in the X-Forwarded-For header always prefer the public IP over private ones
because in my case here's how the header looks like: X-Forwarded-For: <mypublicip>, 172.17.0.1(docker)

💻 Target components
ntfy server

@ChokunPlayZ ChokunPlayZ added the enhancement New feature or request label Oct 1, 2023
@binwiederhier binwiederhier added the server Relates to the main binary (server or client) label Nov 18, 2023
@binwiederhier
Copy link
Owner

I understand that the X-Forwarded-For handling is rudimentary. ntfy picks the rightmost address, since that is the most secure way to pick a trustworthy address. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For for details.

To implement a proper X-Forwarded-For handling, we'd need to be able to configure a list of trustworthy proxies, e.g. proxies: 172.17.0.1. These proxies would be ignored in the selection of the IP address.

Adding a vendor-specific header like Cf-Connecting-Ip doesn't seem like a great idea, IMHO.

@hipur
Copy link

hipur commented Nov 8, 2024

Maybe X-Real-IP could be beneficial, since it's easier to overwrite without reverse proxies adding another IP to the right. e.g.: traefik

@ojio-san
Copy link

Hello there,

I'm sorry to revive such an old topic, but this issue is open, so I would like to add something to this, as I have multiple proxies there, so I have the same issue as @ChokunPlayZ

@binwiederhier

I understand that the X-Forwarded-For handling is rudimentary. ntfy picks the rightmost address, since that is the most secure way to pick a trustworthy address. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For for details.

I would like to know where did you find that the rightmost address is the most secure way and the trustworthy address ?

If I'm reading right here : https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For#client

This means that the rightmost IP address is the IP address of the most recent proxy and the leftmost IP address is the address of the originating client

So, if we get the rightmost address, we always get the proxy, not the client, because "the leftmost IP address is the address of the originating client", right ?

In that case, the visitor_ip is always the last proxy IP and not the client IP; I don't think that's the expected behaviour.

ntfy-857c5c874d-x5mvp 2024/12/29 09:57:50 DEBUG HTTP request finished (http_method=GET, http_path=/, tag=http, time_taken_ms=0, visitor_auth_limiter_limit=0.016666666666666666, visitor_auth_limiter_tokens=3 │
│ 0, visitor_id=ip:2a03:123:456:789::123, visitor_ip=2a03:123:456:789::123, visitor_messages=0, visitor_messages_limit=17280, visitor_messages_remaining=17280, visitor_request_limiter_limit=0.2, visitor_reque │
│ st_limiter_tokens=60, visitor_seen=2024-12-29T08:57:50.115+01:00) 

Thank you, have a nice day :)

@pixitha
Copy link

pixitha commented Jan 2, 2025

I just ran across this issue when I was deploying ntfy on Fly.io, which uses a customer header name like Cloudflare does. Right now with behind-proxy: true, I just get the Fly.io proxy IP, not the true client ip.

So I think that there are 2 issues here: picking the incorrect XFF client IP from the list and the lack of support for multiple/alternate header names.

It would be great if setting behind proxy to true, would also enable the option to set which header to look at for the client IP? (cloudflare/fly.io/aws/gcp all have customer header names to store client ip securely)
OR
if you could configured a trusted proxy subnet or IP so that looking at the XFF IP list, you could know to ignore the far right address if its "internal" (This is what Apache Tomcat does)

Example Image to help visualize the possible problem:
image
ref: https://www.stackhawk.com/blog/do-you-trust-your-x-forwarded-for-header/

In this diagram, picking the right most IP, would always be the first proxy, but really we should be picking n-1 if there are more than 1 IPs in the list?

@pixitha
Copy link

pixitha commented Jan 6, 2025

I'm working on a PR for this, here is an example running in fly.io:

2025-01-06T02:17:30.515 app[28669d] den [info] 2025/01/06 02:17:30 DEBUG Starting IP extraction (http_method=GET, http_path=/config.js, tag=http)

2025-01-06T02:17:30.515 app[28669d] den [info] 2025/01/06 02:17:30 DEBUG RemoteAddr: 172.16.13.122:52970 (http_method=GET, http_path=/config.js, tag=http)

2025-01-06T02:17:30.515 app[28669d] den [info] 2025/01/06 02:17:30 DEBUG Initial IP after RemoteAddr parsing: 172.16.13.122 (http_method=GET, http_path=/config.js, tag=http)

2025-01-06T02:17:30.515 app[28669d] den [info] 2025/01/06 02:17:30 DEBUG Using ProxyClientIPHeader: Fly-Client-IP (http_method=GET, http_path=/config.js, tag=http)

2025-01-06T02:17:30.515 app[28669d] den [info] 2025/01/06 02:17:30 DEBUG Custom header Fly-Client-IP value: 76.123.x.x(http_method=GET, http_path=/config.js, tag=http)

2025-01-06T02:17:30.515 app[28669d] den [info] 2025/01/06 02:17:30 DEBUG Successfully parsed IP from custom header: 76.123.x.x(http_method=GET, http_path=/config.js, tag=http)

2025-01-06T02:17:30.515 app[28669d] den [info] 2025/01/06 02:17:30 DEBUG Final resolved IP: 76.123.x.x(http_method=GET, http_path=/config.js, tag=http)

2025-01-06T02:17:30.515 app[28669d] den [info] 2025/01/06 02:17:30 DEBUG HTTP request started (http_method=GET, http_path=/config.js, tag=http, visitor_auth_limiter_limit=0.016666666666666666, visitor_auth_limiter_tokens=30, visitor_id=ip:76.123.x.x, visitor_ip=76.123.x.x, visitor_messages=0, visitor_messages_limit=17280, visitor_messages_remaining=17280, visitor_request_limiter_limit=0.2, visitor_request_limiter_tokens=60, visitor_seen=2025-01-06T02:17:30.514Z)

@sr7142x
Copy link

sr7142x commented Jan 21, 2025

@pixitha I have the exact problem and your changes looks promising.

@ojio-san
Copy link

I'm also looking forward @pixitha PR merged on master !
@binwiederhier : is it possible to check #1252 ?
Thank you :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request server Relates to the main binary (server or client)
Projects
None yet
Development

No branches or pull requests

6 participants