# UK Data Services - Advanced .htaccess Configuration # Enhanced Security, Performance & SEO Optimizations # ================================================================== # SECURITY HEADERS & PROTECTION # ================================================================== # Security Headers # Prevent MIME type sniffing Header always set X-Content-Type-Options "nosniff" # Prevent page from being displayed in frames (clickjacking protection) Header always set X-Frame-Options "DENY" # Enable XSS protection Header always set X-XSS-Protection "1; mode=block" # Force HTTPS (HSTS) Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" # Referrer Policy Header always set Referrer-Policy "strict-origin-when-cross-origin" # Permissions Policy (formerly Feature Policy) Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=(), screen-wake-lock=()" # Content Security Policy Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://www.google-analytics.com https://analytics.google.com https://www.clarity.ms https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https: blob:; connect-src 'self' https://www.google-analytics.com https://analytics.google.com https://www.clarity.ms; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self'" # Remove Server Information Header always unset Server Header always unset X-Powered-By # Cache Control for Static Assets Header set Cache-Control "public, max-age=31536000, immutable" Header set Expires "Thu, 31 Dec 2025 23:59:59 GMT" # Cache Control for HTML files Header set Cache-Control "private, max-age=0, no-cache, no-store, must-revalidate" Header set Expires "0" # ================================================================== # RATE LIMITING & DDOS PROTECTION # ================================================================== DOSHashTableSize 3000 DOSPageCount 5 DOSPageInterval 1 DOSSiteCount 100 DOSSiteInterval 1 DOSBlockingPeriod 3600 DOSLogDir "/var/log/apache2/dos_logs" DOSEmailNotify security@ukdataservices.co.uk # Limit request size (10MB) LimitRequestBody 10485760 # ================================================================== # PERFORMANCE OPTIMIZATIONS # ================================================================== # Enable Compression # Compress HTML, CSS, JavaScript, Text, XML and fonts AddOutputFilterByType DEFLATE application/javascript AddOutputFilterByType DEFLATE application/rss+xml AddOutputFilterByType DEFLATE application/vnd.ms-fontobject AddOutputFilterByType DEFLATE application/x-font AddOutputFilterByType DEFLATE application/x-font-opentype AddOutputFilterByType DEFLATE application/x-font-otf AddOutputFilterByType DEFLATE application/x-font-truetype AddOutputFilterByType DEFLATE application/x-font-ttf AddOutputFilterByType DEFLATE application/x-javascript AddOutputFilterByType DEFLATE application/xhtml+xml AddOutputFilterByType DEFLATE application/xml AddOutputFilterByType DEFLATE font/opentype AddOutputFilterByType DEFLATE font/otf AddOutputFilterByType DEFLATE font/ttf AddOutputFilterByType DEFLATE image/svg+xml AddOutputFilterByType DEFLATE image/x-icon AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE text/javascript AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/xml # Remove browser bugs (only needed for very old browsers) BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4\.0[678] no-gzip BrowserMatch \bMSIE !no-gzip !gzip-only-text/html Header append Vary User-Agent # Enable Brotli Compression (if available) AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/xml text/css text/javascript AddOutputFilterByType BROTLI_COMPRESS application/javascript application/json application/xml AddOutputFilterByType BROTLI_COMPRESS application/rss+xml application/atom+xml AddOutputFilterByType BROTLI_COMPRESS image/svg+xml # Enable Expires Headers ExpiresActive On # Default expiration: 1 hour after request ExpiresDefault "access plus 1 hour" # CSS and JavaScript: 1 year ExpiresByType text/css "access plus 1 year" ExpiresByType application/javascript "access plus 1 year" ExpiresByType text/javascript "access plus 1 year" # Images: 1 year ExpiresByType image/png "access plus 1 year" ExpiresByType image/jpg "access plus 1 year" ExpiresByType image/jpeg "access plus 1 year" ExpiresByType image/gif "access plus 1 year" ExpiresByType image/svg+xml "access plus 1 year" ExpiresByType image/webp "access plus 1 year" ExpiresByType image/avif "access plus 1 year" ExpiresByType image/x-icon "access plus 1 year" # Fonts: 1 year ExpiresByType font/woff "access plus 1 year" ExpiresByType font/woff2 "access plus 1 year" ExpiresByType font/ttf "access plus 1 year" ExpiresByType font/otf "access plus 1 year" ExpiresByType application/font-woff "access plus 1 year" ExpiresByType application/font-woff2 "access plus 1 year" # Documents: 1 week ExpiresByType application/pdf "access plus 1 week" # Data: 1 day ExpiresByType application/json "access plus 1 day" ExpiresByType application/xml "access plus 1 day" ExpiresByType text/xml "access plus 1 day" # HTML: 1 hour ExpiresByType text/html "access plus 1 hour" # ================================================================== # SEO OPTIMIZATIONS # ================================================================== # Remove trailing slashes from URLs (except directories) RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{THE_REQUEST} /+[^\s]*?/{2,}[?\s] [OR] RewriteCond %{THE_REQUEST} /+[^\s]*?/[?\s] RewriteRule ^(.*)$ https://ukdataservices.co.uk/$1 [R=301,L] # Force HTTPS RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # Force www (optional - uncomment if you want to enforce www) # RewriteCond %{HTTP_HOST} ^ukdataservices\.co\.uk [NC] # RewriteRule ^(.*)$ https://www.ukdataservices.co.uk/$1 [L,R=301] # PHP Extensions Hidden RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^([^\.]+)$ $1.php [NC,L] # Custom Error Pages ErrorDocument 400 /400.php ErrorDocument 401 /401.php ErrorDocument 403 /403.php ErrorDocument 404 /404.php ErrorDocument 500 /500.php ErrorDocument 503 /503.php # ================================================================== # SECURITY RESTRICTIONS # ================================================================== # Block access to sensitive files Require all denied # Block access to .htaccess Require all denied # Block access to sensitive directories Require all denied # Block WordPress attack patterns RewriteCond %{QUERY_STRING} \.\./\.\. [OR] RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR] RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR] RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2}) [OR] RewriteCond %{QUERY_STRING} proc/self/environ [OR] RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|\%3D) [OR] RewriteCond %{QUERY_STRING} base64_(en|de)code\(.*\) [OR] RewriteCond %{QUERY_STRING} ^.*(\[|\]|\(|\)|<|>|ê|"|;|\?|\*|=$).* [NC] RewriteRule ^(.*)$ - [F,L] # Block SQL injection attempts RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR] RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR] RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2}) RewriteRule ^(.*)$ index.php [F,L] # Block common exploit attempts RewriteCond %{REQUEST_URI} ^/(wp-admin|wp-includes|wp-content)/.*$ [OR] RewriteCond %{REQUEST_URI} ^.*(\.php/|config\.php|phpinfo\.php|php\.ini).*$ [OR] RewriteCond %{REQUEST_URI} ^.*/(xmlrpc\.php|wp-config\.php|install\.php).*$ RewriteRule ^(.*)$ - [F,L] # ================================================================== # LOGGING & MONITORING # ================================================================== # Custom log format for security monitoring LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %D" ukds_combined # Block common bot patterns (optional) RewriteCond %{HTTP_USER_AGENT} ^$ [OR] RewriteCond %{HTTP_USER_AGENT} ^(java|curl|wget|libwww-perl|python|nikto|scan|winhttp|HTTrack|clshttp|loader|email|harvest|extract|grab|miner) [NC,OR] RewriteCond %{HTTP_USER_AGENT} ^.*(libwww-perl|curl|wget|python|nikto|scan|winhttp|clshttp|loader).*$ [NC] RewriteRule .* - [F,L] # ================================================================== # ADDITIONAL MIME TYPES # ================================================================== # Web fonts AddType application/font-woff .woff AddType application/font-woff2 .woff2 AddType application/vnd.ms-fontobject .eot AddType font/ttf .ttf AddType font/otf .otf # Modern image formats AddType image/webp .webp AddType image/avif .avif # Manifest files AddType application/manifest+json .webmanifest AddType application/json .json # Video formats AddType video/mp4 .mp4 AddType video/webm .webm # ================================================================== # HOTLINK PROTECTION (optional) # ================================================================== # RewriteCond %{HTTP_REFERER} !^$ # RewriteCond %{HTTP_REFERER} !^https?://(www\.)?ukdataservices\.co\.uk [NC] # RewriteRule \.(jpg|jpeg|png|gif|svg|css|js)$ - [F,L] # ================================================================== # MAINTENANCE MODE (uncomment when needed) # ================================================================== # RewriteCond %{REQUEST_URI} !/maintenance.html$ # RewriteCond %{REMOTE_ADDR} !^123\.456\.789\.012$ # Your IP address # RewriteRule $ /maintenance.html [R=302,L]