83

I'm using Nginx as a proxy to filter requests to my application. With the help of the "http_geoip_module" I'm creating a country code http-header, and I want to pass it as a request header using "headers-more-nginx-module". This is the location block in the Nginx configuration:

location / {
    proxy_pass                      http://mysite.com;
    proxy_set_header                Host http://mysite.com;;
    proxy_pass_request_headers      on;
    more_set_headers 'HTTP_Country-Code: $geoip_country_code';
}

But this only sets the header in the response. I tried using "more_set_input_headers" instead of "more_set_headers" but then the header isn't even passed to the response.

What am I missing here?

Peleg
  • 1,025
  • 1
  • 7
  • 11
  • Also check if you are running nginx at a docker container inside a docker swarm cluster, if yes, then you will have to follow [this steps](https://stackoverflow.com/questions/49415595/docker-swarm-get-real-ip-client-host-in-nginx/50592485#50592485) – deFreitas Feb 16 '21 at 18:56

4 Answers4

138

If you want to pass the variable to your proxy backend, you have to set it with the proxy module.

location / {
    proxy_pass                      http://example.com;
    proxy_set_header                Host example.com;
    proxy_set_header                HTTP_Country-Code $geoip_country_code;
    proxy_pass_request_headers      on;
}

And now it's passed to the proxy backend.

sandstrom
  • 14,554
  • 7
  • 65
  • 62
Fleshgrinder
  • 15,703
  • 4
  • 47
  • 56
  • 5
    I was just about to write you back that it doesn't work because I tried it already, but apparently it does. I wasn't viewing the request properly, but after using [tcpdump](http://www.tcpdump.org) I see that the header was passed this whole time... Thanks! – Peleg Nov 03 '13 at 11:42
  • 2
    If it is set in the client. I just want that value passed down. I have no idea what the value is in my nginx set up so I cannot reset it. What I want is to have any custom headers created by the client pass through to the reverse-proxied server unchanged. Surely there is a way to do this. –  Apr 23 '14 at 18:47
  • 48
    also make sure than you use ```underscores_in_headers on;``` in your server block, else nginx is not forwarding those headers! ref: http://serverfault.com/a/586997/317502 – kishorer747 Oct 19 '15 at 16:04
  • Is that the correct way to pass the `Host` header? Host header is not supposed to include `http://`. Unless nginx is doing some magic to strip that out, I'd say the relevant `proxy_set_header` statement is wrong. – Ivan Vučica Oct 25 '17 at 17:23
  • @Fleshgrinder would that work with 301/302 redirect as well? – Oleg Belousov May 06 '20 at 15:53
  • proxy_pass_request_headers on; is a default value, so you don't need to add it – zhukovgreen Jul 30 '20 at 08:38
  • proxy_pass_request_headers on; solved my problem :) – Smilefounder Dec 24 '20 at 04:50
  • Any reason to hardcode the server name? `proxy_set_header Host $server_name;` feels more flexible. (Arguably unrelated to the original question.) – Caesar Sep 21 '22 at 08:00
  • @OlegBelousov did you find a way to make it work for 301 redirects? – intmarinoreturn0 May 17 '23 at 21:05
69

The problem is that '_' underscores are not valid in header attribute. If removing the underscore is not an option you can add to the server block:

underscores_in_headers on;

This is basically a copy and paste from @kishorer747 comment on @Fleshgrinder answer, and solution is from: https://serverfault.com/questions/586970/nginx-is-not-forwarding-a-header-value-when-using-proxy-pass/586997#586997

I added it here as in my case the application behind nginx was working perfectly fine, but as soon ngix was between my flask app and the client, my flask app would not see the headers any longer. It was kind of time consuming to debug.

Peter
  • 1,753
  • 18
  • 19
  • 7
    This is exactly the problem I was having with nginx and my search led me here as well. The accepted answer didn't make any difference. – Mark Apr 24 '18 at 15:55
  • 1
    in my case, the nginx was ignoring the header with an `underscore(_)`, this answer solves my problem! – Atul Arvind Nov 02 '21 at 15:18
  • 1
    Anybody using AWS Elastic Load Balancers (eg. routing traffic based on HTTP headers) beware at present AWS does not accept unserscores (_) in headers so you would not be able to set rules based on these on the ELB side – Arnaud Bouchot Jun 16 '23 at 11:15
1

You may pass ALL headers by adding this:

ignore_invalid_headers off;

But please consider security issues by doing this.

sekrett
  • 1,205
  • 1
  • 15
  • 17
  • Interesting... what does nginx consider "invalid headers" to be? Is there a list? Better: is there a list we can _add_ to? – Gwyneth Llewelyn Aug 04 '23 at 15:21
  • 1
    It is not a list, see the docs: "Valid names are composed of English letters, digits, hyphens, and possibly underscores (as controlled by the underscores_in_headers directive)" https://nginx.org/en/docs/http/ngx_http_core_module.html#ignore_invalid_headers – sekrett Aug 04 '23 at 16:36
  • Ah ok @sekrett — thanks for the reference! – Gwyneth Llewelyn Aug 06 '23 at 23:09
0

I am using Nginx Proxy Manager and was wondering why my request headers were not getting to my API. Adding ignore_invalid_headers off;

Adding proxy_pass_request_headers on; didn't work for me.

I was passing a header like this and it was not getting through Nginx

"User-Id": "17"

I updated the Advanced configuration for my Host with ignore_invalid_headers off; and everything worked as expected.

enter image description here

I have no idea why User-Id is an invalid header in the eyes of Nginx.

PrestonDocks
  • 4,851
  • 9
  • 47
  • 82