This post describes how to add specific security headers to your apache2 or nginx webservers. This eliminates some client side attack vectors in the client browsers using your site. Additionally this makes your site more trustworthy which may have an influence on your search engine score.
Page Contents
How to test your website
There are multiple sites available which can test your website regarding various security settings. The following table shows three of them.
URL | Description |
https://securityheaders.com | Scans mainly for the security headers described in this post. |
https://internet.nl | Scans for security headers, dnssec, https parameters and more |
https://observatory.mozilla.org | Scans mainly for headers, but with detailed analysis for some. |
The Security Headers
We are concentrating on the following seven security headers which are the most important ones at the moment.
Header type | Example Value | Explanation |
Strict-Transport-Security | max-age=31536000 | Enforces https connection to the website, see also https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security |
X-Frame-Options | SAMEORIGIN | Clickjacking protection header, which avoids frames from untrusted sources on your site. See also wikipedia. |
X-Content-Type-Options | nosniff | With this header the server tells the browser to strictly follow the MIME types in Content-Type headers and disable sniffing. See also wikipedia. |
Referrer-Policy | no-referrer | The Referrer-Policy header controls how much referrer info (sent with the Referer header) should be included with requests. |
Permissions-Policy | geolocation=(); midi=();.... | Permissions Policy tells the browser whether a feature can be used on a site or not. These are referred to as policy-controlled features. A list of features which can be controlled by this policz is available under https://github.com/w3c/webappsec-permissions-policy/blob/main/features.md. The Permissions API gates access to features based on user-granted permissions. |
X-XSS-Protection | 1; mode=block | This header enables cross site scripting protection feature in modern browsers. |
Content-Security-Policy | script-src domain.org | Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross-Site Scripting (XSS) and data injection attacks. The CSP can be configured very fine grained and thus closes a lot of attack vectors but this comes with additional management effort. See also https://en.wikipedia.org/wiki/Content_Security_Policy. |
I will use values which I have applied on one of my sites. Please be aware that wordpress or other CMS systems need some special treatments to get a working setup, see section Problems with Content-Security-Policy for more information.
How to configure Security Headers for Nginx
In Nginx headers can be configured in the central nginx config file. The following example is for debian based systems.
user1@host:/etc/nginx$ sudo nano nginx.conf
In the http section you can add the seven headers described before with add_header as seen below (for webpage domain.org).
http {
##
# Basic Settings
##
....
add_header Strict-Transport-Security "max-age=31536000";
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer";
add_header Permissions-Policy "geolocation=(); midi=();notifications=();push=();sync-xhr=();accelerometer=(); gyroscope=(); magnetometer=(); payment=(); camera=(); microphone=();usb=(); xr=();speaker=(self);vibrate=);fullscreen=(self);";
add_header X-XSS-Protection "1; mode=block";
add_header Content-Security-Policy "default-src domain.org";
}
After the changes are saved nginx need to be restarted, e.g. with
user1@host:/sudo systemctl restart nginx
How to configure Security Headers for Apache2
For apache2 webserver the headers can be added in the config for each site. It is important that the mod_headers module is activated. You can do that with
user1@host:/sudo a2enmod headers
user1@host:/sudo systemctl restart apache2
Again the site I will configure is domain.org.
user1@host:/etc/apache2/sites-available# nano domain.org-le-ssl.conf
In the mod_headers section add the following:
</IfModule>
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000;"
Header always append X-Frame-Options SAMEORIGIN
Header always append X-Content-Type-Options "nosniff"
Header always set Permissions-Policy "geolocation=(); midi=();notifications=()push=();sync-xhr=();accelerometer=(); gyroscope=(); magnetometer=(); payment=(); camera=(); microphone=();usb=(); xr=();speaker=(self);vibrate=);fullscreen=(self);";
Header always set Referrer-Policy "no-referrer"
Header always set X-XSS-Protection "1; mode=block"
Header always set Content-Security-Policy "default-src 'self' "
</IfModule>
After the changes are saved apache2 need to be restarted, e.g. with
user1@host:/sudo systemctl restart apache2
Problems with Content-Security-Policy
Especially the Content-Security-Policy header can cause problems and can make your site not working because it prevents the browser from loading needed resources. The general strategy here is that you check blocked resources with the Developer tools in your browser (usually F12) and add this as trusted source (e.g. script-src) to your header definition. Additionally some CMS like wordpress need, depending on the used plugins, script-src unsafe-inline and unsafe-eval which are in general unsecure options. There are tons of articles in the internet how to prevent even that securely, but this means alot of effort. The following example is for a wordpress site with google analytics and google adsense.
Content-Security-Policy "script-src 'self' 'unsafe-inline' 'unsafe-eval' *.googleapis.com *.googlesyndication.com *.googletagmanager.com *.googleadservices.com *.google.com"
Please note that only script-src is secured here, not style etc. (e.g again lots of effort for a wordpress site). Additionally unsafe-inline and unsafe-eval are not considered secure.
Hi! I noticed you visited my site, so I’m returning the favor. I’m looking for ideas to improve my own site, and I appreciate the inspiration. Hope it’s okay if I take some cues from here.