Improving Nginx Config

← Back

The nginx configuration was already pretty secure, but being pretty won't cut it. So I kept digging deeper to make it as secure as possible.

Improving Nginx config

# STS prevents domain hijacking
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

# Prevents embedding
add_header X-Frame-Options "DENY" always;

# Preserves MIME types
add_header X-Content-Type-Options "nosniff" always;

# Sends the origin, path, and query string when performing a same-origin request.
# For cross-origin requests send the origin (only) when the protocol security level stays same (HTTPS→HTTPS).
# Don't send the Referer header to less secure destinations (HTTPS→HTTP).
add_header Referrer-Policy strict-origin-when-cross-origin always;

# Hides version info
server_tokens off;

# Prevents XSS attacks
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'sha256-5TmCSWsRHHKtNC4AgS23KS5Z9SBqma0xikI6H6iJ1/Y=' 'sha256-xYUerDScZY4B65XkoeXj33T52wAKgK+ssZ70qQZ4yNA=' 'sha256-8IkJ0p9CxsIPvZz2G+oZweeNsTtH60j+LXkVV4s1tAQ=' 'sha256-W0UTwJQZ4NjzaqQKhEPjHlR1UuGvkuYFOSbMRgzzNqgg=' 'sha256-1H2YnMkH9j5EEFikbgn35bkymUZxRysYd5B0q7EZzZQ='; connect-src 'self'; img-src 'self'; style-src 'self' 'sha256-5TmCSWsRHHKtNC4AgS23KS5Z9SBqma0xikI6H6iJ1/Y=' 'sha256-YFOIjkCvZnAH6R5z1ZjUI/Zgf7uslK5vN80+lsdvYss=' 'sha256-YustHjijiQEwObTHTWBhQNMhYZnfxLrv6pRx9xtazf4=' 'unsafe-hashes'";

# Prevents embedding
add_header Cross-Origin-Embedder-Policy "require-corp";
add_header Cross-Origin-Embedder-Policy-Report-Only "same-origin";

# Prevents Cross-Site Script Inclusion attacks
add_header Cross-Origin-Resource-Policy "same-origin";

# Cross-origin isolation for a BCG
add_header Cross-Origin-Opener-Policy "same-origin";

# Hides Resource Timings from external domains
add_header Timing-Allow-Origin "https://r1nge.com";

# Blocks unused permissions to reduce the attack surface
add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), attribution-reporting=(), autoplay=(), battery=(), bluetooth=(), camera=(), compute-pressure=(self), cross-origin-isolated=(self), direct-sockets=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-not-visible=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), hid=(), identity-credentials-get=(), idle-detection=(self), keyboard-map=(), magnetometer=(), mediasession=(), microphone=(), midi=(), navigation-override=(self), otp-credentials=(), payment=(), picture-in-picture=(self), publickey-credentials-get=(), screen-wake-lock=(), serial=(), sync-xhr=(), storage-access=(self), usb=(), web-share=(self), window-management=(), xr-spatial-tracking=()";

# Legacy Permissions policy
add_header Feature-Policy "accelerometer 'none'; ambient-light-sensor 'none'; attribution-reporting 'none'; autoplay 'none'; battery 'none'; bluetooth 'none'; camera 'none'; compute-pressure 'self'; cross-origin-isolated 'self'; direct-sockets 'none'; encrypted-media 'none'; execution-while-not-rendered 'none'; execution-while-not-visible 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; hid 'none'; identity-credentials-get 'none'; idle-detection 'none'; keyboard-map 'self'; magnetometer 'none'; mediasession 'none'; microphone 'none'; midi 'none'; navigation-override 'self'; otp-credentials 'none'; payment 'none'; picture-in-picture 'self'; publickey-credentials-get 'none'; screen-wake-lock 'none'; serial 'none'; sync-xhr 'none'; storage-access 'self'; usb 'none'; web-share 'self'; window-management 'none'; xr-spatial-tracking 'none';";

# Prevents resource access from other origins
# Prevents cookie hijacking
add_header Access-Control-Allow-Origin "https://r1nge.com";

# Some tech savvy companies use this or similar headers to recruit people
add_header X-Recruiting "Open to work! Contact me via r1ngegamedev@proton.me; I love Kasane Teto";

Setting CAA record

Generate a CAA record for your certificate provider. I use Let's Encrypt, so my record looks like this:

r1nge.com.    CAA    0 issue "letsencrypt.org"

Then set the CAA DNS record in your domain provider's web panel.

Patching Nginx executable

Since we're patching the executable binary, the string should have the same length as the original.

sed -i 's/Server: nginx/Server: Teto /' which nginx

Patching Flatpress

My fork:

# https://github.com/flatpressblog/flatpress/blob/master/fp-plugins/fpprotect/plugin.fpprotect.php
# remove
// This is set by nginx
// header('Permissions-Policy: interest-cohort=(), autoplay=(self), camera=(self), fullscreen=*, geolocation=(self), microphone=(self), payment=()');
// header('Referrer-Policy: strict-origin-when-cross-origin');
// header('Strict-Transport-Security: max-age=15552000; includeSubDomains');
// header('Cross-Origin-Embedder-Policy: unsafe-none');
// header('Cross-Origin-Opener-Policy: same-origin-allow-popups');
// header('Cross-Origin-Resource-Policy: same-site');

# change
header('Server: Kasane Teto');

Requesting preloading

If you have subdomains, set up HSTS on all of them before submitting and it's not worth the hassle in most cases.

Testing

Beware that it's not necessary to make everything green. Many features are now deprecated.

References

Deprecated