|
# ###################################################################### |
|
# # SECURITY # |
|
# ###################################################################### |
|
|
|
# ---------------------------------------------------------------------- |
|
# | File access | |
|
# ---------------------------------------------------------------------- |
|
|
|
# Block access to directories without a default document. |
|
# Usually you should leave this uncommented because you shouldn't allow anyone |
|
# to surf through every directory on your server (which may includes rather |
|
# private places like the CMS's directories). |
|
|
|
<IfModule mod_autoindex.c> |
|
Options -Indexes |
|
</IfModule> |
|
|
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
|
|
# Block access to hidden files and directories. |
|
# This includes directories used by version control systems such as Git and SVN. |
|
|
|
<IfModule mod_rewrite.c> |
|
RewriteCond %{SCRIPT_FILENAME} -d [OR] |
|
RewriteCond %{SCRIPT_FILENAME} -f |
|
RewriteRule "(^|/)\." - [F] |
|
</IfModule> |
|
|
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
|
|
# Block access to backup and source files. |
|
# These files may be left by some text editors and can pose a great security |
|
# danger when anyone has access to them. |
|
|
|
<FilesMatch "(^#.*#|\.(bak|config|dist|fla|inc|ini|log|psd|sh|sql|sw[op])|~)$"> |
|
Order allow,deny |
|
Deny from all |
|
Satisfy All |
|
</FilesMatch> |
|
|
|
# Rules to block access to WordPress specific files |
|
<files readme.html> |
|
Order allow,deny |
|
Deny from all |
|
</files> |
|
<files readme.txt> |
|
Order allow,deny |
|
Deny from all |
|
</files> |
|
<files README.md> |
|
Order allow,deny |
|
Deny from all |
|
</files> |
|
<files install.php> |
|
Order allow,deny |
|
Deny from all |
|
</files> |
|
<files wp-config.php> |
|
Order allow,deny |
|
Deny from all |
|
</files> |
|
|
|
# Rules to disable XML-RPC |
|
<files xmlrpc.php> |
|
Order allow,deny |
|
Deny from all |
|
</files> |
|
|
|
# Deny access to all .htaccess files |
|
<files ~ "^.*\.([Hh][Tt][Aa])"> |
|
order allow,deny |
|
deny from all |
|
satisfy all |
|
</files> |
|
|
|
<IfModule mod_rewrite.c> |
|
RewriteEngine On |
|
|
|
# Rules to protect wp-includes |
|
RewriteRule ^wp-admin/includes/ - [F] |
|
RewriteRule !^wp-includes/ - [S=3] |
|
RewriteCond %{SCRIPT_FILENAME} !^(.*)wp-includes/ms-files.php |
|
RewriteRule ^wp-includes/[^/]+\.php$ - [F] |
|
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F] |
|
RewriteRule ^wp-includes/theme-compat/ - [F] |
|
|
|
# Rules to prevent php execution in uploads |
|
RewriteRule ^(.*)/uploads/(.*).php(.?) - [F] |
|
|
|
# Rules to block unneeded HTTP methods |
|
RewriteCond %{REQUEST_METHOD} ^(TRACE|DELETE|TRACK) [NC] |
|
RewriteRule ^(.*)$ - [F] |
|
|
|
# Rules to block foreign characters in URLs |
|
RewriteCond %{QUERY_STRING} ^.*(%0|%A|%B|%C|%D|%E|%F).* [NC] |
|
RewriteRule ^(.*)$ - [F] |
|
|
|
# Rules to help reduce spam |
|
RewriteCond %{REQUEST_METHOD} POST |
|
RewriteCond %{REQUEST_URI} ^(.*)wp-comments-post\.php* |
|
RewriteCond %{HTTP_REFERER} !^(.*)CHANGETHENAMEOFYOURWEBSITEHERE.com.* |
|
RewriteCond %{HTTP_REFERER} !^http://jetpack\.wordpress\.com/jetpack-comment/ [OR] |
|
RewriteCond %{HTTP_USER_AGENT} ^$ |
|
RewriteRule ^(.*)$ - [F] |
|
</IfModule> |
|
|
|
|
|
# ###################################################################### |
|
# # WEB PERFORMANCE # |
|
# ###################################################################### |
|
|
|
# ---------------------------------------------------------------------- |
|
# | Compression | |
|
# ---------------------------------------------------------------------- |
|
|
|
<IfModule mod_deflate.c> |
|
|
|
# Force compression for mangled `Accept-Encoding` request headers |
|
# https://developer.yahoo.com/blogs/ydn/pushing-beyond-gzipping-25601.html |
|
|
|
<IfModule mod_setenvif.c> |
|
<IfModule mod_headers.c> |
|
SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding |
|
RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding |
|
</IfModule> |
|
</IfModule> |
|
|
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
|
|
# Compress all output labeled with one of the following media types. |
|
# |
|
# (!) For Apache versions below version 2.3.7 you don't need to |
|
# enable `mod_filter` and can remove the `<IfModule mod_filter.c>` |
|
# and `</IfModule>` lines as `AddOutputFilterByType` is still in |
|
# the core directives. |
|
# |
|
# https://httpd.apache.org/docs/current/mod/mod_filter.html#addoutputfilterbytype |
|
|
|
<IfModule mod_filter.c> |
|
AddOutputFilterByType DEFLATE "application/atom+xml" \ |
|
"application/javascript" \ |
|
"application/json" \ |
|
"application/ld+json" \ |
|
"application/manifest+json" \ |
|
"application/rdf+xml" \ |
|
"application/rss+xml" \ |
|
"application/schema+json" \ |
|
"application/vnd.geo+json" \ |
|
"application/vnd.ms-fontobject" \ |
|
"application/x-font-ttf" \ |
|
"application/x-javascript" \ |
|
"application/x-web-app-manifest+json" \ |
|
"application/xhtml+xml" \ |
|
"application/xml" \ |
|
"font/eot" \ |
|
"font/opentype" \ |
|
"image/bmp" \ |
|
"image/svg+xml" \ |
|
"image/vnd.microsoft.icon" \ |
|
"image/x-icon" \ |
|
"text/cache-manifest" \ |
|
"text/css" \ |
|
"text/html" \ |
|
"text/javascript" \ |
|
"text/plain" \ |
|
"text/vcard" \ |
|
"text/vnd.rim.location.xloc" \ |
|
"text/vtt" \ |
|
"text/x-component" \ |
|
"text/x-cross-domain-policy" \ |
|
"text/xml" |
|
|
|
</IfModule> |
|
|
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
|
|
# Map the following filename extensions to the specified |
|
# encoding type in order to make Apache serve the file types |
|
# with the appropriate `Content-Encoding` response header |
|
# (do note that this will NOT make Apache compress them!). |
|
# |
|
# If these files types would be served without an appropriate |
|
# `Content-Enable` response header, client applications (e.g.: |
|
# browsers) wouldn't know that they first need to uncompress |
|
# the response, and thus, wouldn't be able to understand the |
|
# content. |
|
# |
|
# https://httpd.apache.org/docs/current/mod/mod_mime.html#addencoding |
|
|
|
<IfModule mod_mime.c> |
|
AddEncoding gzip svgz |
|
</IfModule> |
|
|
|
</IfModule> |
|
|
|
# ---------------------------------------------------------------------- |
|
# | ETags | |
|
# ---------------------------------------------------------------------- |
|
|
|
# Remove `ETags` as resources are sent with far-future expires headers. |
|
# |
|
# https://developer.yahoo.com/performance/rules.html#etags |
|
# https://tools.ietf.org/html/rfc7232#section-2.3 |
|
|
|
# `FileETag None` doesn't work in all cases. |
|
<IfModule mod_headers.c> |
|
Header unset ETag |
|
</IfModule> |
|
|
|
FileETag None |
|
|
|
# ---------------------------------------------------------------------- |
|
# | Expires headers | |
|
# ---------------------------------------------------------------------- |
|
|
|
# Serve resources with far-future expires headers. |
|
# |
|
# (!) If you don't control versioning with filename-based |
|
# cache busting, you should consider lowering the cache times |
|
# to something like one week. |
|
# |
|
# https://httpd.apache.org/docs/current/mod/mod_expires.html |
|
|
|
<IfModule mod_expires.c> |
|
|
|
ExpiresActive on |
|
ExpiresDefault "access plus 1 month" |
|
|
|
# CSS |
|
ExpiresByType text/css "access plus 1 year" |
|
|
|
# Data interchange |
|
ExpiresByType application/atom+xml "access plus 1 hour" |
|
ExpiresByType application/rdf+xml "access plus 1 hour" |
|
ExpiresByType application/rss+xml "access plus 1 hour" |
|
|
|
ExpiresByType application/json "access plus 0 seconds" |
|
ExpiresByType application/ld+json "access plus 0 seconds" |
|
ExpiresByType application/schema+json "access plus 0 seconds" |
|
ExpiresByType application/vnd.geo+json "access plus 0 seconds" |
|
ExpiresByType application/xml "access plus 0 seconds" |
|
ExpiresByType text/xml "access plus 0 seconds" |
|
|
|
# Favicon (cannot be renamed!) and cursor images |
|
ExpiresByType image/vnd.microsoft.icon "access plus 1 year" |
|
ExpiresByType image/x-icon "access plus 1 year" |
|
|
|
# HTML |
|
ExpiresByType text/html "access plus 0 seconds" |
|
|
|
# JavaScript |
|
ExpiresByType application/javascript "access plus 1 year" |
|
ExpiresByType application/x-javascript "access plus 1 year" |
|
ExpiresByType text/javascript "access plus 1 year" |
|
|
|
# Manifest files |
|
ExpiresByType application/manifest+json "access plus 1 year" |
|
|
|
ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds" |
|
ExpiresByType text/cache-manifest "access plus 0 seconds" |
|
|
|
# Media files |
|
ExpiresByType audio/ogg "access plus 1 month" |
|
ExpiresByType image/bmp "access plus 1 month" |
|
ExpiresByType image/gif "access plus 1 month" |
|
ExpiresByType image/jpeg "access plus 1 month" |
|
ExpiresByType image/png "access plus 1 month" |
|
ExpiresByType image/svg+xml "access plus 1 month" |
|
ExpiresByType video/mp4 "access plus 1 month" |
|
ExpiresByType video/ogg "access plus 1 month" |
|
ExpiresByType video/webm "access plus 1 month" |
|
|
|
# Web fonts |
|
|
|
# Embedded OpenType (EOT) |
|
ExpiresByType application/vnd.ms-fontobject "access plus 1 year" |
|
ExpiresByType font/eot "access plus 1 year" |
|
|
|
# OpenType |
|
ExpiresByType font/opentype "access plus 1 year" |
|
|
|
# TrueType |
|
ExpiresByType application/x-font-ttf "access plus 1 year" |
|
|
|
# Web Open Font Format (WOFF) 1.0 |
|
ExpiresByType application/font-woff "access plus 1 year" |
|
ExpiresByType application/x-font-woff "access plus 1 year" |
|
ExpiresByType font/woff "access plus 1 year" |
|
|
|
# Web Open Font Format (WOFF) 2.0 |
|
ExpiresByType application/font-woff2 "access plus 1 year" |
|
|
|
# Other |
|
ExpiresByType text/x-cross-domain-policy "access plus 1 week" |
|
|
|
</IfModule> |
I added some more security code, so be sure to
CHANGETHENAMEOFYOURWEBSITEHERE.com
where it exists above.