Is Your Site’s .htaccess File Being Used to Its Potential?

Every web site should have a file called .htaccess at the root folder for the domain.  You can leave it blank, but why do that, when there’s so much good stuff to be done with it? Over the last year or so I’ve spent a lot of time researching the latest, best ways to secure & optimize web sites, as well as redirect visitors in both VPS & Shared environments, and I’ve compiled a few of my favorite .htaccess tricks here in one place, which you’ll hopefully find as useful as I would have before I spent hours researching & testing it all!

 


 

Securing a web site isn’t a matter of “ok, now THAT should do it.”  Instead, it’s a matter of tons of layers of one little thing after another, each step building on and adding to the others.  No web site that’s connected to the Internet is ever truly “secure” from tampering, but every little thing you do toward that ideal goal is a step in the right direction.  Here are a few of the basics:

Put this in .htaccess to secure sensitive files.  This particular entry was taken from a Drupal site, so modify to taste:

# Prevent viewing of sensitive files
<Files .htaccess>
 order allow,deny
 deny from all
</Files>
<Files CHANGELOG.txt>
 order allow,deny
 deny from all
</files>
<Files PATCHES.txt>
 order allow,deny
 deny from all
</files>

 

Put this in .htaccess to stop advertising to people some of the details about what server software you’re running on:

# Disable the server signature
 ServerSignature Off
# Hide info about what is running
<IfModule mod_headers.c>
 Header unset X-Generator
 Header unset X-Powered-By
</IfModule>

 

Here are some more pretty self-explanatory entries for .htaccess – just read the comment preceding each for a brief explanation:

# Secure site from click-jacking attack
Header append X-FRAME-OPTIONS "SAMEORIGIN"
# Preserve bandwidth for PHP enabled servers
<ifmodule mod_php4.c>
 php_value zlib.output_compression 16386
</ifmodule>
# Set the server administrator email
SetEnv SERVER_ADMIN admin@domain.com
# Set the default language
DefaultLanguage en-US
# Set the default character set
AddDefaultCharset UTF-8
# Cache images and flash content in Apache for six hours
 <FilesMatch ".(flv|gif|jpg|jpeg|png|ico|swf)$">
 Header set Cache-Control "max-age=21600"
 </FilesMatch>
# Cache fonts, text, css, and javascript files in Apache for six hours
 <FilesMatch ".(js|css|pdf|txt|eot|woff|ttf|svg)$">
 Header set Cache-Control "max-age=21600"
 </FilesMatch>
# Cache html and htm files in Apache for six hours
 <FilesMatch ".(html|htm)$">
 Header set Cache-Control "max-age=21600"
 </FilesMatch>

 

I don’t know if it’s true, but I’ve heard that Google takes into account your site’s “bounce rate” when ranking in their search results, as an indication of how useful/authoritative your content is.  (i.e., if everyone leaves as soon as they visit, then you’re probably not what they were looking for.)  So when your shiny new site is finally online and you’re already seeing lots of random spammy-looking domain names listed as traffic sources, it’s not a reason to celebrate lots of apparent backlinks – instead those sites could be bringing down your search ranking (to say nothing of additional server load dealing with them)!  To eliminate them, add this code to your .htaccess file, and update it every time you spot a new spammy referrer, following the pattern using two lines per referrer.  (This list is what I found on one new site over about 2 months in Winter/Spring, 2015.)

# Block Spammy Website Referrers
SetEnvIfNoCase Referer humanorightswatch spam=yes
SetEnvIfNoCase User-Agent "humanorightswatch" spam
SetEnvIfNoCase Referer o-o-6-o-o spam=yes
SetEnvIfNoCase User-Agent "o-o-6-o-o" spam
SetEnvIfNoCase Referer semalt spam=yes
SetEnvIfNoCase User-Agent "semalt" spam
SetEnvIfNoCase Referer buttons-for-website spam=yes
SetEnvIfNoCase User-Agent "buttons-for-website" spam
SetEnvIfNoCase Referer buttons-for-your-website spam=yes
SetEnvIfNoCase User-Agent "buttons-for-your-website" spam
SetEnvIfNoCase Referer simple-share-buttons spam=yes
SetEnvIfNoCase User-Agent "simple-share-buttons" spam
SetEnvIfNoCase Referer free-share-buttons spam=yes
SetEnvIfNoCase User-Agent "free-share-buttons" spam
SetEnvIfNoCase Referer free-social-buttons spam=yes
SetEnvIfNoCase User-Agent "free-social-buttons" spam
SetEnvIfNoCase Referer hulfingtonpost spam=yes
SetEnvIfNoCase User-Agent "hulfingtonpost" spam
SetEnvIfNoCase Referer theguardlan spam=yes
SetEnvIfNoCase User-Agent "theguardlan" spam
SetEnvIfNoCase Referer best-seo-solution spam=yes
SetEnvIfNoCase User-Agent "best-seo-solution" spam
SetEnvIfNoCase Referer Get-Free-Traffic-Now spam=yes
SetEnvIfNoCase User-Agent "Get-Free-Traffic-Now" spam
SetEnvIfNoCase Referer best-seo-offer spam=yes
SetEnvIfNoCase User-Agent "best-seo-offer" spam
SetEnvIfNoCase Referer buy-cheap-online spam=yes
SetEnvIfNoCase User-Agent "buy-cheap-online" spam
SetEnvIfNoCase Referer torture.ml spam=yes
SetEnvIfNoCase User-Agent "torture.ml" spam
SetEnvIfNoCase Referer event-tracking spam=yes
SetEnvIfNoCase User-Agent "event-tracking" spam
Order allow,deny
Allow from all
Deny from env=spam

 

You also may want to redirect all pages/visitors to http from https, or vice-versa, and/or you may want to move all inbound traffic without the “www” prefix” to be forced to use it. If so, then you’ll want to do what’s called a “permanent 301 redirect.” Always put that code at the end of the file. (Generally, the .htaccess order should go: security stuff, access control and bot-blocking, followed by general to more specific redirects, followed by https and then www redirects.)

Every environment is a little different – VPS is different from Shared hosting, etc. – so here’s what’s worked for me. YMMV….

# First permanently redirect http to https
# Then permanently redirect domain.com to www.domain.com
<IfModule mod_rewrite.c>
 RewriteEngine on
 RewriteCond %{HTTPS} off
 RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301]
 RewriteCond %{HTTP_HOST} !^www\.
 RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>

Alternatively, to redirect from https to http you can reverse it, like this:

RewriteCond %{HTTPS} on
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=301]

Sometimes, when the above doesn’t work for redirecting https to http, I’ve had success with this instead:

RewriteCond %{SERVER_PORT} 443
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=301] 

NOTE however, that if your website does not have a security certificate, you will continue to get the browser’s “warning” when visitors hit your web site via HTTPS, even if you tell .htaccess to redirect all traffic to HTTP.  This is because that warning message gets triggered before .htaccess is checked.  If your site doesn’t have an SSL certificate, the http-https redirect will not work no matter how perfect your code is.  (If you’re on a VPS you may have enough access to fix it on the server manually though. Go to /etc/httpd/conf.d/ssl.conf and comment out the part about the virtual server 443.)

Those are my favorites, so you’re just about done.  The last thing I always like to do for security is chmod the file permissions on .htaccess from 644 to 444.

Hope this helps someone!

Steve