support Proxy to get ip from a http Header instead from source IP (127.0.0.1) #70

Closed
opened 2025-12-29 01:21:37 +01:00 by adam · 8 comments
Owner

Originally created by @JensKuehnel on GitHub (Nov 7, 2021).

Hi,
I'm running headscale on a server that is servicing https via a caddy server. It works perfectly (Thanks for that).
The only minor problem are the logfiles. Because I'm using a Reverse-proxy in front, the logfile look like this:

Nov 07 23:05:04 MYHOST headscale[3132606]: [GIN] 2021/11/07 - 23:05:04 | 200 |  1.003830109s |       127.0.0.1 | POST     "/machine/MYID/map"

Could a new parameter be added to take the log file from a http-header instead of the source IP?

Sorry, I can't write go, or I would add it myself.

Originally created by @JensKuehnel on GitHub (Nov 7, 2021). Hi, I'm running headscale on a server that is servicing https via a caddy server. It works perfectly (Thanks for that). The only minor problem are the logfiles. Because I'm using a Reverse-proxy in front, the logfile look like this: ``` Nov 07 23:05:04 MYHOST headscale[3132606]: [GIN] 2021/11/07 - 23:05:04 | 200 | 1.003830109s | 127.0.0.1 | POST "/machine/MYID/map" ``` Could a new parameter be added to take the log file from a http-header instead of the source IP? Sorry, I can't write go, or I would add it myself.
adam added the enhancementhelp wantedgood first issue labels 2025-12-29 01:21:37 +01:00
adam closed this issue 2025-12-29 01:21:38 +01:00
Author
Owner

@ItalyPaleAle commented on GitHub (Nov 9, 2021):

The most complicated part of solving this issue is that it requires creating a new config option.

Caddy is already setting X-Forwarded-For headers. However, for security reasons Gin does not look into that automatically. Instead, you need to set r.SetTrustedProxies([]string{"IP or CIDR"}) (docs). In headscale, it would be around here:

74f0d08f50/app.go (L407)

However because the proxy's IP or CIDR depends on your environment, it needs to be something that is set in a config file.

Also note that the config should allow setting Gin's TrustedPlatform flag if the app is running on platforms like Google App Engine, Cloudflare, etc.

@ItalyPaleAle commented on GitHub (Nov 9, 2021): The most complicated part of solving this issue is that it requires creating a new config option. Caddy is already setting X-Forwarded-For headers. However, for security reasons Gin does not look into that automatically. Instead, you need to set `r.SetTrustedProxies([]string{"IP or CIDR"})` ([docs](https://github.com/gin-gonic/gin#dont-trust-all-proxies)). In headscale, it would be around here: https://github.com/juanfont/headscale/blob/74f0d08f507ba6dd25ea69cf4faa38093e46be07/app.go#L407 However because the proxy's IP or CIDR depends on your environment, it needs to be something that is set in a config file. Also note that the config should allow setting Gin's `TrustedPlatform` flag if the app is running on platforms like Google App Engine, Cloudflare, etc.
Author
Owner

@mannp commented on GitHub (Nov 9, 2021):

I also have the same issue using traefik 2 as proxy, I only ever see the proxy address instead of the remote client address.

@ItalyPaleAle those options are used commonly in other projects, so doesn't it seem sensible to have to set them here too when using a proxy?

@mannp commented on GitHub (Nov 9, 2021): I also have the same issue using traefik 2 as proxy, I only ever see the proxy address instead of the remote client address. @ItalyPaleAle those options are used commonly in other projects, so doesn't it seem sensible to have to set them here too when using a proxy?
Author
Owner

@ItalyPaleAle commented on GitHub (Nov 9, 2021):

For security reasons (and for the fact that certain CDNs require looking at different headers) I would not recommend enabling trusted proxies with 0.0.0.0/0 by default. Should really be a config option IMHO. Otherwise if someone is NOT running the app behind a proxy, a malicious actor could send requests with the X-Forwarded-For header to fake the IP.

@ItalyPaleAle commented on GitHub (Nov 9, 2021): For security reasons (and for the fact that certain CDNs require looking at different headers) I would not recommend enabling trusted proxies with 0.0.0.0/0 by default. Should really be a config option IMHO. Otherwise if someone is NOT running the app behind a proxy, a malicious actor could send requests with the `X-Forwarded-For` header to fake the IP.
Author
Owner

@mannp commented on GitHub (Nov 9, 2021):

That was my point, we should have to set them and yes likely 0.0.0.0/0 shouldn't be default, as it would be expected the proxy would be set to one specific IP or a range in the case of Cloudflare.

@mannp commented on GitHub (Nov 9, 2021): That was my point, we should have to set them and yes likely 0.0.0.0/0 shouldn't be default, as it would be expected the proxy would be set to one specific IP or a range in the case of Cloudflare.
Author
Owner

@Akruidenberg commented on GitHub (Oct 31, 2022):

Is there a temporary workaround for this? Is the alpine docker image a fix?

@Akruidenberg commented on GitHub (Oct 31, 2022): Is there a temporary workaround for this? Is the alpine docker image a fix?
Author
Owner

@mhameed commented on GitHub (Nov 20, 2022):

Adding link for reference for the haproxy proxy protocol, which seems to be relatively widely adopted:
https://www.haproxy.org/download/2.7/doc/proxy-protocol.txt

@mhameed commented on GitHub (Nov 20, 2022): Adding link for reference for the haproxy proxy protocol, which seems to be relatively widely adopted: https://www.haproxy.org/download/2.7/doc/proxy-protocol.txt
Author
Owner

@juanfont commented on GitHub (May 10, 2023):

I reckon this is now

@juanfont commented on GitHub (May 10, 2023): I reckon this is now
Author
Owner

@vutsalsinghal commented on GitHub (Mar 12, 2025):

guys, how do I fix this for nginx? I have headscale clients connecting to jellyfin via nginx but in the nginx logs, the client IP is always 127.0.0.1.

@vutsalsinghal commented on GitHub (Mar 12, 2025): guys, how do I fix this for nginx? I have headscale clients connecting to jellyfin via nginx but in the nginx logs, the client IP is always 127.0.0.1.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/headscale#70