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!