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

How to use 'Custom Nginx Configuration' function to modify headers for added security

Open infi8ite opened this issue 4 years ago • 21 comments

Checklist

What is troubling you?

In short, I am having some trouble using the Custom Nginx Configuration.

I just want to start by saying this is a great tool for noobs like me who are just getting into self-hosting and reverse proxy management. As a beginner, I am slightly paranoid about the security of my server and is chasing this elusive A+ header test (see https://securityheaders.com/) for the domain that I am hosting (I am currently getting an E grade with the default NPM with 'Block common exploits' enabled).

After some googling, I learnt that it will be useful to include the following NGINX configurations for added security

	add_header X-Xss-Protection "1; mode=block" always;
	add_header X-Content-Type-Options "nosniff" always;
	add_header Strict-Transport-Security "max-age=2592000; includeSubdomains" always;
	add_header X-Frame-Options "SAMEORIGIN" always;
	proxy_hide_header X-Powered-By;
	add_header 'Referrer-Policy' 'no-referrer';
	add_header Content-Security-Policy "frame-ancestors mydomain.com files.mydomain.com;";

The issue is when I dump them to Custom Nginx Configuration section of the GUI, nothing happens. If I try to add {} to the script, NPM will go offline.

	{add_header X-Xss-Protection "1; mode=block" always;
	add_header X-Content-Type-Options "nosniff" always;
	add_header Strict-Transport-Security "max-age=2592000; includeSubdomains" always;
	add_header X-Frame-Options "SAMEORIGIN" always;
	proxy_hide_header X-Powered-By;
	add_header 'Referrer-Policy' 'no-referrer';
	add_header Content-Security-Policy "frame-ancestors mydomain.com files.mydomain.com;";}

Can someone shed some light into how I could go about adding these headers?

Much appreciated.

Ed

infi8ite avatar Aug 26 '20 11:08 infi8ite

That's a very good question. Your first attempt should be working (no brackets), but it's not. I'm currently investigating this; I noticed for example that NPM adds a header "X-Served-By $host;" but it's not there either, so I suspect some aspect of nginx I don't know.

gregfr avatar Aug 27 '20 12:08 gregfr

I just tried using this from an old site of mine and it's working. It shows up on https://securityheaders.com/ as functioning.

add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;"; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options nosniff; add_header Referrer-Policy same-origin; add_header Content-Security-Policy "default-src 'self' https://.elementor.com https://.google.com; font-src 'self' data: https://.googleapis.com https://.gstatic.com; img-src 'self' data: https://i.imgur.com https://.gravatar.com https://.elementor.com; object-src 'none'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' data: https://.googleapis.com; script-src-elem 'self' 'unsafe-inline' https://.cloudflare.com; frame-src 'self' https://.youtube.com https://.google.com;";

dash74 avatar Aug 27 '20 17:08 dash74

I tried your code as well and it's working. The only way that I could get it too work though is pictured below. If I tried too list the domain name it would not register.

image

dash74 avatar Aug 27 '20 17:08 dash74

After some digging, I think it's because of an oddity in the way nginx handles headers configuration: https://www.peterbe.com/plog/be-very-careful-with-your-add_header-in-nginx

gregfr avatar Sep 23 '20 12:09 gregfr

Was this ever sorted out? I'm struggling to get the exact headers added to mine. I've even tried adding it to custom/server_proxy.conf with no luck. From my troubleshooting, I think something is overwriting it.

jmarque3 avatar Nov 04 '20 05:11 jmarque3

Any news about this? It's a quite important feature that should work

lordraiden avatar Jan 06 '21 12:01 lordraiden

I'm also curious if anyone has found a solution... I'm having the same problem. At one point I came across this thread and I got it working using the custom location as demonstrated above.

But today it stopped working (ie the headers are no longer working... I'm using it with CloudFlare if that's relevant) when I had to renew the certs.

mattjmeier avatar Mar 30 '21 01:03 mattjmeier

+1

R0GGER avatar Apr 08 '21 20:04 R0GGER

I am facing the exact same dilemma. Adding any header = "add_header" variables to "Edit Proxy Host" / Advanced Has no effect.

jacqueshenning avatar Apr 12 '21 13:04 jacqueshenning

As I noted in my post from Sep 23, 2020, the problem is from Nginx itself, not NPM.

gregfr avatar Apr 21 '21 12:04 gregfr

Well on my setup, those headers are in the main server block, not any location block. But they're still not being added. I copied these into the custom config section of the site definition in npm without any effect.

skorvek avatar Apr 21 '21 21:04 skorvek

As I noted in my post from Sep 23, 2020, the problem is from Nginx itself, not NPM.

No... I'm pretty sure it's a NGINX Proxy Manager bug. It's already in the code, but it's not working...

Code: https://github.com/jc21/nginx-proxy-manager/blob/1a64d44857b8db488f56567b743f787b61e1f7a4/backend/app.js#L34-L52

When add the headers manually to a proxy_host config ( below # HSTS) it works perfectly fine...

add_header Referrer-Policy "no-referrer" always;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";

R0GGER avatar Apr 21 '21 22:04 R0GGER

I created a workaround which works pretty well... More info: Workaround - Security Headers @ NGINX Proxy Manager

Result: eLo2Df

R0GGER avatar Apr 21 '21 23:04 R0GGER

As I noted in my post from Sep 23, 2020, the problem is from Nginx itself, not NPM.

Hi I am pretty sure its not NGINX, I setup NGINX SSL Proxies + WAF's often, if I manually add the headers to the server blocks, all works as expected, but this is not ideal as NPM is supposed to be the "easier" option vs custom / scratch setups.

Or if you could please give a more productive answer i.e. point me to where the NGINX issue is, I can then investigate or be more informed.

Kind Regards

jacqueshenning avatar Apr 26 '21 15:04 jacqueshenning

@jacqueshenning imo the person above you states what does work.

Is this still an issue by the way? (as I am yet to configure the settings stated above).

dutch2005 avatar Jun 30 '21 09:06 dutch2005

Hi,

I'm also using custom location and I'm getting A+ grade with these headers:

add_header X-Xss-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always; proxy_hide_header X-Powered-By; add_header 'Referrer-Policy' 'no-referrer'; add_header Permissions-Policy "accelerometer=();ambient-light-sensor=(); autoplay=();camera=();encrypted-media=();focus-without-user-activation=(); geolocation=();gyroscope=();magnetometer=();microphone=();midi=();payment=();picture-in-picture=(); speaker=();sync-xhr=();usb=();vr=()"; add_header Content-Security-Policy "default-src 'none'; style-src 'self' ; form-action 'self'; frame-ancestors 'self'; base-uri 'self'; img-src 'self' data:; font-src 'self'; frame-src 'self'";

and also

include conf.d/include/ssl-ciphers.conf; in the advanced tab otherwise it uses unsafe ciphers if I use a custom SSL cert instead of Let's Encrypt

Kopernikus1979 avatar Apr 08 '22 10:04 Kopernikus1979

@Kopernikus1979 thanks for this, works like a charm!

NiapApa avatar Apr 09 '22 12:04 NiapApa

@Kopernikus1979 thanks for this, works like a charm!

Your welcome :-)

It's possible that the add_header Content-Security-Policy "default-src 'none'; style-src 'self' ; form-action 'self'; frame-ancestors 'self'; base-uri 'self'; img-src 'self' data:; font-src 'self'; frame-src 'self'"; needs tweaking (define allowed) for some services/apps, otherwise youc an replace it with add_header Content-Security-Policy upgrade-insecure-requests;

Kopernikus1979 avatar Apr 11 '22 15:04 Kopernikus1979

The only way i got this working is by manually adjusting the .conf. Can anyone explain what the custom location even means? What exactly is the IP address supposed to be?

andrewwarz avatar Sep 23 '22 20:09 andrewwarz

Hi @andrewwarz - The custom location is located inside Nginx Proxy Manager where you create the proxy hosts.

image

I have added the following to my configuration.

add_header X-Xss-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always; proxy_hide_header X-Powered-By; add_header 'Referrer-Policy' 'no-referrer'; add_header Permissions-Policy "accelerometer=();ambient-light-sensor=(); autoplay=();camera=();encrypted-media=();focus-without-user-activation=(); geolocation=();gyroscope=();magnetometer=();microphone=();midi=();payment=();picture-in-picture=(); speaker=();sync-xhr=();usb=();vr=()"; add_header Content-Security-Policy upgrade-insecure-requests;

image

Hope it helps.

NiapApa avatar Sep 24 '22 06:09 NiapApa

Tested this myself and i cant get more than B rating.

I have tried the workaround that @R0GGER posted and what @NiapApa said, both failed me.

Is there any progress done on this?

I'm on npm version 2.9.19 and the problem is still there

sebtech33 avatar Dec 05 '22 02:12 sebtech33

Also on 2.9.19 and none of the workarounds specified above work.

JPDucky avatar Feb 27 '23 22:02 JPDucky

Installed v2.10.2 and followed @R0GGER workaround. Thx

Aplus

I found adding 'always' on the end of for nginx works :-

{% if certificate and certificate_id > 0 -%} {% if ssl_forced == 1 or ssl_forced == true %} {% if hsts_enabled == 1 or hsts_enabled == true %} add_header Strict-Transport-Security "max-age=63072000;{% if hsts_subdomains == 1 or hsts_subdomains == true -%} includeSubDomains;{% endif %} preload" always; add_header Referrer-Policy strict-origin-when-cross-origin always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header Content-Security-Policy upgrade-insecure-requests always; add_header Permissions-Policy interest-cohort=() always; add_header Expect-CT 'enforce; max-age=604800' always; more_set_headers 'Server: Proxy'; more_clear_headers 'X-Powered-By'; {% endif %} {% endif %} {% endif %}

I hope it helps....

adley20 avatar May 01 '23 22:05 adley20

Just use headers more.

more_set_headers "X-XSS-Protection: 1; mode=block"; more_set_headers "X-Content-Type-Options: nosniff"; more_set_headers "Referrer-Policy: no-referrer-when-downgrade"; more_set_headers "Content-Security-Policy: default-src 'self' http: https: ws: wss: data: blob: 'unsafe-inline'; frame-ancestors 'self';"; more_set_headers "Permissions-Policy: interest-cohort=()"; more_set_headers "Strict-Transport-Security: max-age=31536000; includeSubDomains";

kristoftorok avatar Jun 15 '23 21:06 kristoftorok

Having an issue with adding custom headers, whenever i add a custom location "/" and add the headers there i get this page when trying to visit the site.

image

sinnayuh avatar Feb 10 '24 14:02 sinnayuh

damn, is this still an issue 2024???

Nazgile94 avatar Apr 05 '24 17:04 Nazgile94

Yeah, still not fixed you can add them manually like I do

Kopernikus1979 avatar Apr 06 '24 10:04 Kopernikus1979

If someone is here for Nextcloud, as I am, here's the solution: Just paste this in the NPM Advanced tab for your hostname:

location /.well-known/carddav {    
    return 301 $scheme://$host/remote.php/dav;}

location /.well-known/caldav {    
    return 301 $scheme://$host/remote.php/dav;}

more_set_headers "X-XSS-Protection: 1; mode=block";
more_set_headers "X-Content-Type-Options: nosniff";
more_set_headers "X-Robots-Tag: noindex, nofollow";
more_set_headers "Referrer-Policy: no-referrer-when-downgrade";
more_set_headers "Content-Security-Policy: default-src 'self' http: https: ws: wss: data: blob: 'unsafe-inline'; frame-ancestors 'self';";
more_set_headers "Permissions-Policy: interest-cohort=()";
more_set_headers "Strict-Transport-Security: max-age=31536000; includeSubDomains";
more_set_headers "X-Frame-Options: SAMEORIGIN";
more_set_headers "X-Permitted-Cross-Domain-Policies: none";

ALERTua avatar Apr 07 '24 09:04 ALERTua