Implementing comprehensive security measures involves preventive access to entire domains. It prevents entry for users and bots from specific IP addresses and domains, and restricts access to particular areas within a domain. This page outlines the use cases and suggested code snippets for controlling access to your site using the .htaccess file.
Preventing access to a domain
You can prevent users from accessing a domain or prevent users from a certain domain from accessing your website.
The following are two example use cases of this type of preventative access:
Limiting access to a domain by allowing only a specific group of domains or IP addresses:
To protect the origin and only allow access from specific IP addresses, you can use the following configuration:<IfModule mod_setenvif.c> SetEnvIf Host ^origin\.domain\.com$ origin=1 SetEnvIf AH_CLIENT_IP ^127\.0\.0\.1$ allowlist=1 SetEnvIf AH_CLIENT_IP ^10\.171\. allowlist=1 SetEnvIf AH_CLIENT_IP ^10\.210\.122\.14$ allowlist=1 SetEnvIf AH_CLIENT_IP ^192\.168\.204\.109$ allowlist=1 SetEnvIf AH_CLIENT_IP ^192\.168\.236\.194$ allowlist=1 <RequireAll> Require not env origin <RequireAny> Require env allowlist Require all denied </RequireAny> </RequireAll> </IfModule>
These IP addresses are for demonstration only. The configuration ensures that access is denied if the
origin
environment variable is set, indicating a request using the origin host, and is allowed if theallowlist
environment variable is set for the listed IP addresses.Preventing access to the DNS name of your Elastic Load Balancer (ELB):
To prevent access to your site through the DNS name of your ELB for theGET
method, you can use the following configuration:<Limit GET> Require all granted Require not host [ELB DNS name] </Limit>
Replace
[ELB DNS name]
with the actual DNS name of your Elastic Load Balancer. If you have dedicated balancers, you can also achieve this by using your VCL (Varnish Configuration Language).
Preventing access to users originating from a domain
Requests to domains can be blocked by referring to the HTTP_REFERER
variable as shown in the following example code:
For single domains, add the following code to your
.htaccess
file:RewriteCond %{HTTP_REFERER} domain-name\.com [NC] RewriteRule .* - [F]
For multiple domains, add the following code to your
.htaccess
file:RewriteCond %{HTTP_REFERER} domain-one\.com [NC,OR] RewriteCond %{HTTP_REFERER} domain-two\.com [NC,OR] RewriteCond %{HTTP_REFERER} domain-three\.com RewriteRule .* - [F]
Preventing access to specific pages(Drupal 7 only)
Some customers may only want specific IPs to be able to log in to the Drupal website. The recommended code snippet to implement this is made with the following considerations:
If you are using Varnish, ensure your page caches do not serve restricted content.
Set max-age to 0. See the max-age headers for specific pages, files, or paths for help in setting max-age=0 in appropriate circumstances. Ensure that the user page is not cached after the accepted IP has accessed the page.
- Ensure only accepted IPs can access the page by using
AH_Client_IP
variable. This is needed on Cloud Platform if your website is behind an ELB. This is to ensure that the correct IP is checked in the code. Ensure that Drupal does not cache the user page by adding the following into the websites
settings.php
:// Drupal 7 only if (isset($_GET['q']) && strpos($_GET['q'], 'user') === 0) { $conf['cache'] = FALSE; }
The following is the recommended code snippet for the .htaccess
file:
Header always set Cache-Control max-age=0 env=userpage RewriteCond %{REQUEST_URI} ^/user(/login)*$ [OR] RewriteCond %{QUERY_STRING} ^q=user(/login)*$ RewriteCond %{ENV:AH_Client_IP} !^2.121.88.122$ RewriteCond %{ENV:AH_Client_IP} !^12.211.9.49$ RewriteCond %{ENV:AH_Client_IP} !^123.45. RewriteCond %{ENV:AH_SITE_ENVIRONMENT} ^(dev|test|prod)$ RewriteRule ^ http://%{HTTP_HOST} [R=302,L,E=userpage:1]
You can use a similar method to restrict access to a single page to one IP address.
The following code restricts access to /path/to/page
to the IP 192.168.2.3
:
// Drupal 7 only // Add this to the end of settings.php // Handle allowlisting for a /path/to/page URL if ($_SERVER['REQUEST_URI'] == '/path/to/page') { // Turn off page caching (internal and external) for this page // to avoid a valid IP getting this page into cache. drupal_page_is_cacheable(FALSE); // Only allow access to an IP. if ($_ENV['AH_Client_IP'] != '192.168.2.3') { // Deny access drupal_add_http_header('Status', '403 Forbidden'); echo "<h1>403 Forbidden</h1><p>Access is forbidden from " . $_ENV['AH_Client_IP'] .". Shoo!</p>\n\n"; exit; } }
After this change is implemented, you must clear the Varnish cache for that page.
Preventing access to some Drupal core files
Files such as CHANGELOG.txt
can be used to identify security vulnerabilities in your Drupal installation to a malicious script or user. While there are several ways to identify the version of Drupal, one addition to your .htaccess file
file can make it slightly less obvious by adding in the following alias rules:
#various alias rules Redirect 404 /CHANGELOG.txt Redirect 404 /COPYRIGHT.txt Redirect 404 /cron.php Redirect 404 /INSTALL.mysql.txt Redirect 404 /INSTALL.pgsql.txt Redirect 404 /INSTALL.sqlite.txt Redirect 404 /INSTALL.txt Redirect 404 /install.php Redirect 404 /LICENSE.txt Redirect 404 /MAINTAINERS.txt Redirect 404 /PATCHES.txt Redirect 404 /README.txt Redirect 404 /update.php Redirect 404 /UPGRADE.txt Redirect 404 /web.config
Preventing file resources from domains
You may want to prevent a specific directory from being accessed by the general public unless it is being pulled by a particular website. This example blocks requests to the /sites/default/files
directory unless the request comes from www?
, prod-kb
, or the kb
subdomains of example.com
.
RewriteCond %{REQUEST_URI} ^/sites/default/files RewriteCond %{HTTP_REFERER} !^http://prod-kb.example.com [NC] RewriteCond %{HTTP_REFERER} !^http://kb.example.com [NC] RewriteCond %{HTTP_REFERER} !^http://(www.)?example.com [NC] RewriteRule .* - [F]
Preventing access to a subfolder
Use the following code to block access to a subfolder:
RewriteCond %{THE_REQUEST} ^A-Z{3,9}\ /(/+)/.*\ HTTP NC RewriteRule .* - [F,L]
Preventing certain HTTP methods
You may not want to allow certain types of methods to be processed by your site. This blocks any HTTP request that is not a GET
or a POST
request.
RewriteCond %{REQUEST_METHOD} !^(GET|POST) RewriteRule .* - [F]