19

I have an Nginx proxy setup where I add several security-related headers to the server so that they return on all proxy locations. On some locations I need to add additional headers (ex. Content-Security-Policy to /), while on other specific locations I need to remove one of the headers (ex. X-Frame-Options from /framepage.html) added at the server level.

nginx.conf

# ...

server {
  # ...

  include security-headers.conf;

  location / {
    proxy_pass http://web:5000/;
    include security-headers.conf;
    add_header Content-Security-Policy "my csp...";
  }

  location = /framepage.html {
    proxy_pass http://web:5000/framepage.html;
    # TODO: remove `X-Frame-Options` response header from this specific page
    # Tried add_header X-Frame-Options "";
    # Tried proxy_set_header X-Frame-Options "";
    # Tried proxy_hide_header X-Frame-Options;
  }

  location /api/ {
    proxy_pass http://api:5000/;
  }

  location /otherstuff/ {
    proxy_pass http://otherstuff:5000/;
  }

  # ...
}

security-headers.conf

add_header Referrer-Policy same-origin;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";

I have tried the following, but none of them seem to remove the X-Frame-Options header from the /framepage.html location response:

  • add_header X-Frame-Options "";
  • proxy_set_header X-Frame-Options "";
  • proxy_hide_header X-Frame-Options;

How can I remove the X-Frame-Options header from the /framepage.html location response?

2
  • Is your backend server sending this header, then? – Michael Hampton Sep 2 '18 at 20:47
  • @MichaelHampton no, it is only set by the parent server block include statement. – kspearrin Sep 2 '18 at 20:49
18

The header config attributes are a bit confusing, this is what they do:

proxy_set_header is to set a request header
add_header is to add header to response
proxy_hide_header is to hide a response header

If you want to replace a header that already exists in the response it is not enough with add_header because it will stack the values (from server and the one you added).

You have to do this in two steps:

1) remove header:
proxy_hide_header Access-Control-Allow-Origin;

2) add your custom header value:
add_header Access-Control-Allow-Origin "*" always;

4
  • 1
    help, proxy_hide_header works with proxy_pass, it doesn't work with 'return' – datdinhquoc Jan 24 '20 at 8:35
  • @datdinhquoc What do you mean with "it doesn't work with 'return'"? Could you elaborate or even better post a question and send me a link? – Wilt Jan 24 '20 at 10:31
  • i want to change a response header, but 'return' in server block will pass the url to browser and some http 302 happen in browser, i cant add the extra header to the final redirected url – datdinhquoc Jan 24 '20 at 18:20
  • This only works for response headers set by an upstream server but not for headers set by nginx self like "server" header for example. – Daniel W. Aug 3 '20 at 15:21
4

You can use the headers_more module. Example:

location / {
    proxy_pass http://upstream_server/;
    more_clear_headers 'Access-Control-Allow-Origin';
}

https://www.nginx.com/resources/wiki/modules/headers_more/

3

You could probably try to use the 3rd party "Headers More" module:

https://github.com/openresty/headers-more-nginx-module

And something along the lines of:

load_module modules/ngx_http_headers_more_filter_module.so;

http {
    ...
    more_clear_headers 'X-Frame-Options';
    ...
}
1

Don't include security-headers.conf at the server level. Only include it in each individual location where you want these headers to be sent.

The reason for this is that add_header directives are inherited from the previous level if and only if the current level has no add_header directives. Thus, your including them in the server block causes them to be included in every location as you aren't overriding them in any location.

2
  • 1
    Yes, I was actually doing this intentionally since I wanted them to apply to all locations without having to include it at every location. It sounds like what I am trying to do is not possible. – kspearrin Sep 2 '18 at 21:20
  • Sure it is, just follow my instructions and DO NOT put it in the server or in the location where you don't want the headers sent. – Michael Hampton Sep 2 '18 at 21:23
0

Using the Nginx Lua module.

You will need the nginx-extras package installed. For example in aptitude do a apt install nginx-extras.

In nginx.conf:

load_module /usr/lib/nginx/modules/ndk_http_module.so;
load_module /usr/lib/nginx/modules/ngx_http_lua_module.so;

http {
  ...

  header_filter_by_lua_block {
    ngx.header["server"] = nil
  }
}

To verify run a nginx -V and you will see http-lua. The ndk_http_module.so is needed to load the ngx_http_lua_module.so module.

Always best to run an nginx -t to verify your configuration, as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.