Nginx -> HTTP server -> Real IP Source

Started by oleg, December 09, 2023, 04:27:19 PM

Previous topic - Next topic
Cannot disable setting of special Forward headers for Nginx -> HTTP server ->  Real IP Source.
Even if to choose None, they are still present.

I'm talking about these ones:

proxy_set_header X-Real-IP $remote_addr;                                   
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;               
proxy_set_header X-Forwarded-Proto $scheme;                                 
proxy_set_header X-Forwarded-Port $server_port;                             
proxy_set_header X-Forwarded-Host $host;   


My goal is to set my own values, but i cannot override them, because any `proxy_set_header` direcitve which is set in `GUID_post/*.conf` just adds new header, not override it.
This inability brakes my proxy logic. Maybe I miss something, or it is just isn't possible, but (I repeat myself) parameter 'None' for 'Real IP Source' does'n disable 'X-Real-IP' and 'X-Forwarded-' headers.

Is there a possibility to set own headers (or values) for the ones mentioned before?

December 09, 2023, 09:02:33 PM #1 Last Edit: December 09, 2023, 09:05:12 PM by Fright
Quoteparameter 'None' for 'Real IP Source' does'n disable 'X-Real-IP' and 'X-Forwarded-' headers
Real IP Source field defines 'real_ip_header' directive value. not the 'proxy_set_header'
https://github.com/opnsense/plugins/blob/d714e8fc24b233c93556c16c33ac17f26b2cfde1/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/http.conf#L152-L159


at the moment, the mentioned headers are hardcoded and uses widely used values (it is not clear from the question whether it is worth making a request to change this)
https://github.com/opnsense/plugins/blob/d714e8fc24b233c93556c16c33ac17f26b2cfde1/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/location.conf#L163-L167

December 09, 2023, 09:54:15 PM #2 Last Edit: December 09, 2023, 10:00:20 PM by oleg
The use case is quite simple. Just try to make NAT forwarding to the nginx. And you receive wrong Port or/and IP.
This is just my case. My backend server use that headers for dynamic modifications of sources' URI's.
It would be nice to have a possibility (at least using a pre/post configs) to handle the situation when you need to change the hardcoded values.

became clearer but only partially  ;)
What values do you set for these headers in this case (and how do you get the real IP)?

December 11, 2023, 09:18:05 AM #4 Last Edit: December 11, 2023, 10:22:57 AM by oleg
e.g. nginx listens on 127.0.0.1:1443, but the real IP and PORT the request is come to is 10.x.x.x:433 (over the NAT).
And for such a case i set OUTER ip/port -- X-Forwarded-Port : 443, and for ip something like
X-Forwarded-For 10.x.x.x, $proxy_add_x_forwarded_for;

December 11, 2023, 07:01:36 PM #5 Last Edit: December 12, 2023, 08:30:09 AM by Fright
Ah! I think this is an incorrect use of the XFF header (intended to convey the client address)
but you can try to use the headers-more module directives (https://github.com/openresty/headers-more-nginx-module#more_set_input_headers) in _post-hooks to replace 'standard' headers.
Headers More module should be enabled at Global HTTP Settings for this

January 09, 2024, 12:47:24 PM #6 Last Edit: January 09, 2024, 01:19:34 PM by oleg
> I think this is an incorrect use of the XFF header (intended to convey the client address)

I try to transfer not the client address, but the correct server address to the underlying backend.
I also tried headers-more module.
I is enabled in Nginx -> General Settings -> Global HTTP settings.
Then i found UUID in /usr/local/etc/nginx/nginx.conf for my server.

Part of config

server {                                                                       
  listen 127.0.0.1:1080;                                                     
  server_name  my.server.address;
 
  include feecb877-0831-4efa-8005-e26b0dde555f_pre/*.conf;

location  / {                                                                   
     BasicRule wl:19;                                                           
     DeniedUrl "/waf_denied.html";                                               
     autoindex off;                                                             
     http2_push_preload on;                                                     
     proxy_set_header Host $host;                                               
     proxy_http_version 1.1;                                                     
     proxy_set_header Upgrade $http_upgrade;                                     
     proxy_set_header Connection $connection_upgrade;                           
     proxy_buffer_size 8k;                                                       
     proxy_buffers 8 8k;                                                         
     proxy_busy_buffers_size 32k;                                               
     proxy_set_header X-TLS-Cipher $ssl_cipher;                                 
     proxy_set_header X-TLS-Protocol $ssl_protocol;                             
     proxy_set_header X-TLS-SNI-Host $ssl_server_name;                           
     # proxy headers for backend server                                         
     proxy_set_header X-Real-IP $remote_addr;                                   
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;               
     proxy_set_header X-Forwarded-Proto $scheme;                                 
     proxy_set_header X-Forwarded-Port $server_port;                             
     proxy_set_header X-Forwarded-Host $host;                                   
     proxy_set_header X-TLS-Client-Intercepted $tls_intercepted;                 
     proxy_read_timeout 10s;                                                     
     proxy_send_timeout 10s;                                                     
     proxy_ignore_client_abort on;                                               
     proxy_request_buffering on;                                                 
     proxy_max_temp_file_size 1024m;                                             
     proxy_buffering on;                                                         
     proxy_pass http://upstream5fa240aef8aa4a9f895a4959a40bbbbb;                 
     proxy_hide_header X-Powered-By;                                             
     include 9370ea92-2ab9-45b4-b244-ceb86baa2887_post/*.conf;                   
   }     
  include feecb877-0831-4efa-8005-e26b0dde555f_post/*.conf;
}


I created files:

/usr/local/etc/nginx/feecb877-0831-4efa-8005-e26b0dde555f_pre/myheaders.conf
/usr/local/etc/nginx/9370ea92-2ab9-45b4-b244-ceb86baa2887_post/myheaders.conf
/usr/local/etc/nginx/feecb877-0831-4efa-8005-e26b0dde555f_post/myheaders.conf


The content is quite simple -- one line:

more_set_input_headers 'X-Forwarded-Port: 80';


Then I restarted nginx and tried simple request via curl. Aaaand it doesn't work. I still continue to receive X-Forwarded-Port: 1080.

I think it would be better to allow to set/override the values for X-Forwarded- header over GUI at least in config.
For now it doesn't work.

January 26, 2024, 07:05:28 PM #8 Last Edit: January 26, 2024, 07:19:57 PM by Fright
ah, sorry. my bad.
'more_set_input_headers' will not work in this case, since XFF not arrived from upstream proxy. but set by nginx instance itself.. oops
in this case, I see the only way out is to use a truly custom X- header (say, X-Requested-IP) and set it via hooks or configure the whole location via server _post-hook?

February 02, 2024, 02:38:26 PM #9 Last Edit: February 02, 2024, 02:40:22 PM by oleg
It will work only if you have the full control over the server code in order to change it behavior so that it starts working with the new header.
But all ready products use the standard headers.

I don't know the actual architecture of opnsense, but I don't understand what is the core problem to add the possibility for configuration X-Forwarded headers. Let it be some checkbox -- use default behavior / use custom behavior (over pre/post files)

It would be nice to have some  working approach that can survive system reboots and configuration updates via GUI.
Maybe some of OPNsense developers have an idea?

I'll answer again in this thread so as not to interfere in a new one (https://forum.opnsense.org/index.php?topic=39391.0).
-in my opinion, this is an incorrect use of de-facto standard headers (and imho there are other ways to achieve the desired result without violating the standards)
-you could use your own headers for this setup
-a request for such changes has little chance of being merged imho
-you always have the option to use a completely hand-written Location (with the desired headers) and use it withe GUI-configured server via server _post-hook

to Fright
I didn't agree with some parts of your conclusions:

- this is an incorrect use of de-facto standard headers
These headers are intended to show the client where the original server/proxy resides in a heterogeneous systems. I don't have anything super special. Just a NUT with port forwarding.

-you could use your own headers for this setup
No, I can't. You are talking about some abstract suggestion, that 3rd party product somehow should handle non-standard headers. While we already have the de-facto standard headers for this purpose.

-you always have the option to use a completely hand-written Location (with the desired headers) and use it withe GUI-configured server via server _post-hook
Does it survive the update/upgrade of OPNsense? I mean -- is this a standard way for OPNsense?

-a request for such changes has little chance of being merged imho
What are the changes your are talking? Maybe we look at this problem from different points?
My suggestion is just give a possibility to the user switch on/off the logic of OPNsense, where it adds these headers. Just on/off -- no more.



Hi.
-These headers are intended to show the client where the original server/proxy resides in a heterogeneous systems
I still don't understand why you think using an XFF header in the '<arbitrary_external_server_address>, $proxy_add_x_forwarded_for' format satisfies the standard way if it assumes the '<client>, <proxy1>, <proxy2>' format.
if there was no NAT in front of the nginx, the external address of the plugin would also not be included in this header

-No, I can't. You are talking about some abstract suggestion..
It would be more accurate to say not a non-standard header, but non-standard requirements?

-Does it survive the update/upgrade of OPNsense? I mean -- is this a standard way for OPNsense?
This is certainly not the preferred method (preferably all settings are available in the UI) but it is included in the plugin templates. and yes, it will survive the reboot\update\upgrade.

I'm not a plugin maintainer, so feel free to ignore my assumptions  :) I just believe that changes requests should be motivated and I understand that I would not come up with enough justification for the maintainer to accept my arguments in this case

Maybe the os-caddy plugin fits your needs. You can manipulate the up and downstream headers in any way you wish from the GUI.

https://github.com/opnsense/plugins/blob/master/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogHeader.xml

Any amount of these custom header manipulations can be set per location.
Hardware:
DEC740