Skip to content

Instantly share code, notes, and snippets.

@R0GGER
Last active May 7, 2024 08:09
Show Gist options
  • Star 27 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save R0GGER/916183fca41f02df1471a6f455e5869f to your computer and use it in GitHub Desktop.
Save R0GGER/916183fca41f02df1471a6f455e5869f to your computer and use it in GitHub Desktop.
Workaround - Security Headers @ NGINX Proxy Manager
{% if certificate and certificate_id > 0 -%}
{% if ssl_forced == 1 or ssl_forced == true %}
{% if hsts_enabled == 1 or hsts_enabled == true %}
# HSTS (ngx_http_headers_module is required) (63072000 seconds = 2 years)
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;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options SAMEORIGIN;
add_header Content-Security-Policy upgrade-insecure-requests;
add_header Permissions-Policy interest-cohort=();
add_header Expect-CT 'enforce; max-age=604800';
more_set_headers 'Server: Proxy';
more_clear_headers 'X-Powered-By';
{% endif %}
{% endif %}
{% endif %}
@maximushugus
Copy link

Thanks for sharing your config !
As said on a comment the problem is that if an application already has on of those header, the same header (maybe with a different value) is added by NPM, wich could cause issue and is not following the standards.

So I made so changes :

First here is my _hsts.conf file :

{% 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 $hdr_strict_transport_security;
add_header Referrer-Policy $hdr_referrer_policy;
add_header X-Content-Type-Options $hdr_x_content_type_options;
add_header X-XSS-Protection $hdr_x_xss_protection;
add_header X-Frame-Options $hdr_x_frame_options;
add_header Content-Security-Policy $hdr_content_security_policy;
add_header Permissions-Policy $hdr_permissions_policy;
add_header Expect-CT $hdr_expect_ct;
more_set_headers 'Server: Proxy';
more_clear_headers 'X-Powered-By';
{% endif %}
{% endif %}
{% endif %}

Then I created (or modified) in /data/nginx/custom a http_top.conf file :

map $upstream_http_strict_transport_security $hdr_strict_transport_security {
'' "max-age=63072000; includeSubDomains; preload";
}

map $upstream_http_referrer_policy $hdr_referrer_policy {
'' "strict-origin-when-cross-origin";
}

map $upstream_http_x_content_type_options $hdr_x_content_type_options {
'' "nosniff";
}

map $upstream_http_x_xss_protection $hdr_x_xss_protection {
'' "1; mode=block";
}

map $upstream_http_x_frame_options $hdr_x_frame_options {
'' "SAMEORIGIN";
}

map $upstream_http_content_security_policy $hdr_content_security_policy {
'' "upgrade-insecure-requests";
}

map $upstream_http_permissions_policy $hdr_permissions_policy {
'' "interest-cohort=()";
}

map $upstream_http_expect_ct $hdr_expect_ct {
'' "enforce, max-age=604800";
}

Than restarting nginx and disabling SSL and saving in NPM, and enabling it again.
With this configuration nginx only adds those header if they are not already send by the underling application.

The only thing is if you want to disable on of those header (X-frame for me) on a specified application, you have to put the entire configuration for this application in the advanced tap with "location/{ ....}

@jce-zz
Copy link

jce-zz commented May 7, 2024

@maximushugus Thanks for sharing your config and updates! Works like a charm! :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment