nginx-proxy-manager icon indicating copy to clipboard operation
nginx-proxy-manager copied to clipboard

X-forwared-for shows Cloudflare IP instead of real IP

Open bernikr opened this issue 4 years ago • 21 comments

Checklist

  • Have you pulled and found the error with jc21/nginx-proxy-manager:latest docker image?
    • Yes
  • Are you sure you're not using someone else's docker image?
    • Yes
  • Have you searched for similar issues (both open and closed)?
    • Yes

Describe the bug When using Cloudflare infront of NPM, NPM populates the X-forwarded-for header with the cloudflare IP instead of the real IP that cloudflare provices in its X-forwarded-for header. I would expect NPM to check if the source IP is one of cloudflare's and trust the X-forwarded-for header in that case. This seemd to be a feature in 2.6.0 but broken in all verisons afterwards.

Nginx Proxy Manager Version 2.9.8

To Reproduce Set up a cloudflare domain and let it point to NPM. If you now navigate to the site the server behind NPM will get one of cloudflare's IPs as the X-forwarded-for header instead of the client IP

Expected behavior Show the real client IP that cloudflare reports in the X-forwarded-for header.

Operating System Synology NAS

Additional context The closed issues #112 and #811 both suggest using the following settings as a workaround:

real_ip_header CF-Connecting-IP;
#real_ip_header X-Forwarded-For;

This is however a major security risk as it doesnt check if the request is actually coming from cloudflare. It allows anyone with knowledge of your IP to send requests pretending to be from cloudflare with an CF-Connecting-IP header set to any IP they want, (including lan ips such as 10.0.0.1) possibly circumventing any IP based security measures.

bernikr avatar Aug 28 '21 13:08 bernikr

Use v2.6.0 is what I found in my #811

schevenin avatar Sep 04 '21 03:09 schevenin

Found the following:

set_real_ip_from defines trusted addresses that are known to send correct replacement addresses. Source: https://nginx.org/en/docs/http/ngx_http_realip_module.html

nginx configuration file snippet (IPv4 only):

set_real_ip_from    03.21.244.0/22;
set_real_ip_from    103.22.200.0/22;
set_real_ip_from    103.31.4.0/22;
set_real_ip_from    104.16.0.0/13;
set_real_ip_from    104.24.0.0/14;
set_real_ip_from    108.162.192.0/18;
set_real_ip_from    131.0.72.0/22;
set_real_ip_from    141.101.64.0/18;
set_real_ip_from    162.158.0.0/15;
set_real_ip_from    172.64.0.0/13;
set_real_ip_from    173.245.48.0/20;
set_real_ip_from    188.114.96.0/20;
set_real_ip_from    190.93.240.0/20;
set_real_ip_from    197.234.240.0/22;
set_real_ip_from    198.41.128.0/17;

#use any of the following two

real_ip_header CF-Connecting-IP;
#real_ip_header X-Forwarded-For;

Cloudflare Documentation: https://support.cloudflare.com/hc/en-us/articles/200170786-Restoring-original-visitor-IPs

Cloudflare IPs: https://www.cloudflare.com/ips

TritonB7 avatar Jan 21 '22 15:01 TritonB7

Awesome @TritonB7, I've tried it and it seems to work!

gmcinalli avatar Jan 21 '22 17:01 gmcinalli

Is this still not automatic/internal to NPM v2.9.16?

I am migrating to NPM. Previously, I was using this on my own config:

#!/bin/bash echo "#Cloudflare" > /var/www/nginx/cloudflare.conf; for i in $(curl https://www.cloudflare.com/ips-v4); do echo "set_real_ip_from $i;" >> /var/www/nginx/cloudflare.conf; done echo "real_ip_header CF-Connecting-IP;" >> /var/www/nginx/cloudflare.conf;

Not ideal but hacky enough to get the job done.

I landed on this thread because am experiencing this issue with my upstream behind NPM, it's not logging the correct IP where it was pre-NPM.

ctrlbrk42 avatar Feb 24 '22 22:02 ctrlbrk42

Is this still not automatic/internal to NPM v2.9.16?

I am migrating to NPM. Previously, I was using this on my own config:

#!/bin/bash echo "#Cloudflare" > /var/www/nginx/cloudflare.conf; for i in $(curl https://www.cloudflare.com/ips-v4); do echo "set_real_ip_from $i;" >> /var/www/nginx/cloudflare.conf; done echo "real_ip_header CF-Connecting-IP;" >> /var/www/nginx/cloudflare.conf;

Not ideal but hacky enough to get the job done.

I landed on this thread because am experiencing this issue with my upstream behind NPM, it's not logging the correct IP where it was pre-NPM.

Not sure if you have fixed this but I saw something here 811 check the post by techc0de maybe you can try it.

punksinatra avatar Mar 15 '22 19:03 punksinatra

Is this still not automatic/internal to NPM v2.9.16?

I am migrating to NPM. Previously, I was using this on my own config:

#!/bin/bash echo "#Cloudflare" > /var/www/nginx/cloudflare.conf; for i in $(curl https://www.cloudflare.com/ips-v4); do echo "set_real_ip_from $i;" >> /var/www/nginx/cloudflare.conf; done echo "real_ip_header CF-Connecting-IP;" >> /var/www/nginx/cloudflare.conf;

Not ideal but hacky enough to get the job done.

I landed on this thread because am experiencing this issue with my upstream behind NPM, it's not logging the correct IP where it was pre-NPM.

Not sure if you have fixed this but I saw something here 811 check the post by techc0de maybe you can try it.

I switched to Caddy for this particular project.

ctrlbrk42 avatar Mar 15 '22 20:03 ctrlbrk42

Awesome @TritonB7, I've tried it and it seems to work!

Where did you update this? In the GUI or in the compose file?

bioszombie avatar Feb 03 '23 01:02 bioszombie

@bioszombie “Custom Nginx Configuration” field in the “Advanced” tab of the proxy host editing modal on the GUI.

gmcinalli avatar Feb 03 '23 05:02 gmcinalli

@bioszombie “Custom Nginx Configuration” field in the “Advanced” tab of the proxy host editing modal on the GUI.

Thank you. That worked!

bioszombie avatar Feb 03 '23 12:02 bioszombie

I am currently trying to get this working with Guacamole and can't seem to figure it out as that isn't working. I am trying with the below and it doesn't seem to be picking up the remote ip but the ip address of Cloudflare that it is routing through. Does this look correct? I also tried adding a copy of the real_ip_header line under the location section which made no difference. set_real_ip_from 103.21.244.0/22; set_real_ip_from 103.22.200.0/22; set_real_ip_from 103.31.4.0/22; set_real_ip_from 104.16.0.0/12; set_real_ip_from 108.162.192.0/18; set_real_ip_from 131.0.72.0/22; set_real_ip_from 141.101.64.0/18; set_real_ip_from 162.158.0.0/15; set_real_ip_from 172.64.0.0/13; set_real_ip_from 173.245.48.0/20; set_real_ip_from 188.114.96.0/20; set_real_ip_from 190.93.240.0/20; set_real_ip_from 197.234.240.0/22; set_real_ip_from 198.41.128.0/17; real_ip_header CF-Connecting-IP; location / { proxy_pass http://10.1.11.3:9998/guacamole/; proxy_cookie_path /guacamole/ /; }

wdolan avatar Mar 01 '23 04:03 wdolan

@wdolan I don't think you need the location block, that will be handled by the NPM UI.

gmcinalli avatar Mar 01 '23 11:03 gmcinalli

Hello, Maybe I have something wrong then. Even then trying to make a few variants on it, I am seeing connections as being from 127.0.0.1 despite having the below setup. When I connect through the host from the same network using the machine name instead of the external FQDN it reports correctly. Did I miss something? server { server_name remote.redacted.net; location / { set_real_ip_from 03.21.244.0/22; set_real_ip_from 103.22.200.0/22; set_real_ip_from 103.31.4.0/22; set_real_ip_from 104.16.0.0/13; set_real_ip_from 104.24.0.0/14; set_real_ip_from 108.162.192.0/18; set_real_ip_from 131.0.72.0/22; set_real_ip_from 141.101.64.0/18; set_real_ip_from 162.158.0.0/15; set_real_ip_from 172.64.0.0/13; set_real_ip_from 173.245.48.0/20; set_real_ip_from 188.114.96.0/20; set_real_ip_from 190.93.240.0/20; set_real_ip_from 197.234.240.0/22; set_real_ip_from 198.41.128.0/17; real_ip_header CF-Connecting-IP; proxy_pass http://localhost:8080/guacamole/;

proxy_pass http://localhost:8081;

proxy_read_timeout  90;
proxy_http_version  1.1;
proxy_cache_bypass  $http_upgrade;

proxy_buffering off;
proxy_set_header Upgrade           $http_upgrade;
proxy_set_header Connection        $http_connection;
proxy_set_header Host              $host;
proxy_set_header X-Real-IP         CF-Connecting-IP;
proxy_set_header X-Forwarded-For   CF-Connecting-IP;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host  $host;
proxy_set_header X-Forwarded-Port  $server_port;
proxy_intercept_errors on;

}

listen 443 http2 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/remote.redacted.net/fullchain.pem;

managed by Certbot

ssl_certificate_key /etc/letsencrypt/live/

remote.redacted.net/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot error_page 404 500 502 503 504 https://letmegooglethat.com/?q=why+does+my+server+have+an+error; }

Any help would be greatly appreciated.

On Thu, May 18, 2023 at 12:39 PM glassman81 @.***> wrote:

Found the following:

set_real_ip_from defines trusted addresses that are known to send correct replacement addresses. Source: https://nginx.org/en/docs/http/ngx_http_realip_module.html

nginx configuration file snippet (IPv4 only):

set_real_ip_from 03.21.244.0/22; set_real_ip_from 103.22.200.0/22; set_real_ip_from 103.31.4.0/22; set_real_ip_from 104.16.0.0/13; set_real_ip_from 104.24.0.0/14; set_real_ip_from 108.162.192.0/18; set_real_ip_from 131.0.72.0/22; set_real_ip_from 141.101.64.0/18; set_real_ip_from 162.158.0.0/15; set_real_ip_from 172.64.0.0/13; set_real_ip_from 173.245.48.0/20; set_real_ip_from 188.114.96.0/20; set_real_ip_from 190.93.240.0/20; set_real_ip_from 197.234.240.0/22; set_real_ip_from 198.41.128.0/17;

#use any of the following two

real_ip_header CF-Connecting-IP; #real_ip_header X-Forwarded-For;

Cloudflare Documentation: https://support.cloudflare.com/hc/en-us/articles/200170786-Restoring-original-visitor-IPs

Cloudflare IPs: https://www.cloudflare.com/ips

Sorry, I know this post is a little older, but what would happen if you included the “real_ip_header X-Forwarded-For;” line but didn’t add any actual cloudflare addresses using “set_real_ip_from”?

— Reply to this email directly, view it on GitHub https://github.com/NginxProxyManager/nginx-proxy-manager/issues/1358#issuecomment-1553324231, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABA3PV6GNDF3NWHJFS5ZXP3XGZGE3ANCNFSM5C7EPWOQ . You are receiving this because you were mentioned.Message ID: @.***>

wdolan avatar May 18 '23 19:05 wdolan

Found the following:

set_real_ip_from defines trusted addresses that are known to send correct replacement addresses. Source: https://nginx.org/en/docs/http/ngx_http_realip_module.html

nginx configuration file snippet (IPv4 only):

set_real_ip_from    03.21.244.0/22;
set_real_ip_from    103.22.200.0/22;
set_real_ip_from    103.31.4.0/22;
set_real_ip_from    104.16.0.0/13;
set_real_ip_from    104.24.0.0/14;
set_real_ip_from    108.162.192.0/18;
set_real_ip_from    131.0.72.0/22;
set_real_ip_from    141.101.64.0/18;
set_real_ip_from    162.158.0.0/15;
set_real_ip_from    172.64.0.0/13;
set_real_ip_from    173.245.48.0/20;
set_real_ip_from    188.114.96.0/20;
set_real_ip_from    190.93.240.0/20;
set_real_ip_from    197.234.240.0/22;
set_real_ip_from    198.41.128.0/17;

#use any of the following two

real_ip_header CF-Connecting-IP;
#real_ip_header X-Forwarded-For;

Cloudflare Documentation: https://support.cloudflare.com/hc/en-us/articles/200170786-Restoring-original-visitor-IPs

Cloudflare IPs: https://www.cloudflare.com/ips

You just saved my day!

LuXc-NL avatar Feb 29 '24 10:02 LuXc-NL

@bioszombie “Custom Nginx Configuration” field in the “Advanced” tab of the proxy host editing modal on the GUI.

If you want to take effect to all your websites, you could add the content to a file /data/nginx/custom/server_proxy.conf which is included at the end of every proxy server block. You could find more information from official document

reply2future avatar Mar 09 '24 08:03 reply2future

this is a godsend :pray:

here's the latest ips

/portainer/Files/AppData/Config/nginx-proxy-manager $ cat data/nginx/custom/server_proxy.conf

set_real_ip_from    103.21.244.0/22;
set_real_ip_from    103.22.200.0/22;
set_real_ip_from    103.31.4.0/22;
set_real_ip_from    104.16.0.0/13;
set_real_ip_from    104.24.0.0/14;
set_real_ip_from    108.162.192.0/18;
set_real_ip_from    131.0.72.0/22;
set_real_ip_from    141.101.64.0/18;
set_real_ip_from    162.158.0.0/15;
set_real_ip_from    172.64.0.0/13;
set_real_ip_from    173.245.48.0/20;
set_real_ip_from    188.114.96.0/20;
set_real_ip_from    190.93.240.0/20;
set_real_ip_from    197.234.240.0/22;
set_real_ip_from    198.41.128.0/17;
set_real_ip_from    2400:cb00::/32;
set_real_ip_from    2405:8100::/32;
set_real_ip_from    2405:b500::/32;
set_real_ip_from    2606:4700::/32;
set_real_ip_from    2803:f800::/32;
set_real_ip_from    2a06:98c0::/29;
set_real_ip_from    2c0f:f248::/32;

#use any of the following two

real_ip_header CF-Connecting-IP;
#real_ip_header X-Forwarded-For;

EDIT: Seems like npm is already fetching these ips, isn't this a reason to implement a simple checkbox to enable cloudflare visitor ips? @jc21

2024-04-07T15:07:13.850501792Z [4/7/2024] [3:07:13 PM] [IP Ranges] › ℹ  info      Fetching https://www.cloudflare.com/ips-v4
2024-04-07T15:07:13.977207458Z [4/7/2024] [3:07:13 PM] [IP Ranges] › ℹ  info      Fetching https://www.cloudflare.com/ips-v6

Bluscream avatar Apr 07 '24 15:04 Bluscream

Found the following:

set_real_ip_from defines trusted addresses that are known to send correct replacement addresses. Source: https://nginx.org/en/docs/http/ngx_http_realip_module.html

nginx configuration file snippet (IPv4 only):

set_real_ip_from    03.21.244.0/22;
set_real_ip_from    103.22.200.0/22;
set_real_ip_from    103.31.4.0/22;
set_real_ip_from    104.16.0.0/13;
set_real_ip_from    104.24.0.0/14;
set_real_ip_from    108.162.192.0/18;
set_real_ip_from    131.0.72.0/22;
set_real_ip_from    141.101.64.0/18;
set_real_ip_from    162.158.0.0/15;
set_real_ip_from    172.64.0.0/13;
set_real_ip_from    173.245.48.0/20;
set_real_ip_from    188.114.96.0/20;
set_real_ip_from    190.93.240.0/20;
set_real_ip_from    197.234.240.0/22;
set_real_ip_from    198.41.128.0/17;

#use any of the following two

real_ip_header CF-Connecting-IP;
#real_ip_header X-Forwarded-For;

Cloudflare Documentation: https://support.cloudflare.com/hc/en-us/articles/200170786-Restoring-original-visitor-IPs

Cloudflare IPs: https://www.cloudflare.com/ips

man this worked for me using CasaOS with home assistant and Nginx Proxy Manager and Cloudflare with proxy enabled and now i can access it thanks to this information thanks so much, spend so many hours trying to get it to work

MrrZed0 avatar Apr 10 '24 05:04 MrrZed0

For anyone in the same situation as me: if you're using a Cloudflare zero trust tunnel, I only needed a single set_real_ip_from specifying the local Cloudflare network IP. This is the IP your server will report when visiting through the tunnel

aerickt avatar Nov 26 '24 16:11 aerickt

There is no need to manually specify set_real_ip_from for Cloudflare IP addresses, because Nginx Proxy Manager already includes a built-in ip_ranges.conf file that’s automatically generated and refreshed.

It’s based on Cloudflare and CloudFront IP addresses. You can check it out here: https://github.com/NginxProxyManager/nginx-proxy-manager/blob/master/backend/internal/ip_ranges.js

Simply add the following snippet to your /data/nginx/custom/server_proxy.conf configuration:

include conf.d/include/ip_ranges.conf;
real_ip_header X-Forwarded-For;

mrwogu avatar Mar 05 '25 14:03 mrwogu

Nothing works for me, tried everything on this page, still getting the container ip

anver avatar Apr 04 '25 15:04 anver

Issue is now considered stale. If you want to keep it open, please comment :+1:

github-actions[bot] avatar Oct 15 '25 02:10 github-actions[bot]

No need to add include conf.d/include/ip_ranges.conf;. Those configs are included by default. Just add real_ip_header X-Forwarded-For; in your proxy host custom config.

enoot avatar Dec 09 '25 17:12 enoot