Файл .htaccess позволяет реализовать базовый уровень защиты сайта без доступа к главной конфигурации Apache. Блокировка вредоносных ботов, защита от хотлинкинга, ограничение доступа к чувствительным файлам — эти и другие меры можно внедрить на shared-хостинге. В статье собраны практические правила с пояснениями. Для генерации готовых конфигураций используйте Генератор .htaccess на reChecker. Проверить заголовки безопасности можно через Security Headers.
Блокировка доступа к чувствительным файлам
Скрытие конфигурационных и служебных файлов — первый шаг к снижению поверхности атаки.
Запрет доступа к .htaccess и конфигурациям
<FilesMatch "^\.">
Require all denied
</FilesMatch>
Блокирует все файлы, начинающиеся с точки: .htaccess, .htpasswd, .env.
Защита конкретных расширений
<FilesMatch "\.(env|ini|log|sql|bak|config|yml|yaml)$">
Require all denied
</FilesMatch>
Защита директорий
# Запрет листинга директорий
Options -Indexes
# Запрет следования симлинкам за пределы DocumentRoot
Options -FollowSymLinks
Блокировка доступа к папкам
<DirectoryMatch "^/.*/\.(git|svn|hg)">
Require all denied
</DirectoryMatch>
Блокировка вредоносных ботов и сканеров
Агрессивные краулеры, сканеры уязвимостей и спам-боты создают нагрузку и могут использоваться для разведки. Блокировка по User-Agent — простой способ отсечь часть трафика.
Базовый список блокируемых User-Agent
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} (AhrefsBot|SemrushBot|MJ12bot|DotBot|BLEXBot) [NC]
RewriteRule .* - [F,L]
Флаг [F] возвращает 403 Forbidden.
Расширенный список
RewriteCond %{HTTP_USER_AGENT} (360Spider|Acunetix|sqlmap|nikto|masscan|nmap|zgrab) [NC]
RewriteRule .* - [F,L]
RewriteCond %{HTTP_USER_AGENT} (Scrapy|Python-urllib|curl|wget|libwww) [NC]
RewriteCond %{REQUEST_URI} !^/api/crawl
RewriteRule .* - [F,L]
Внимание: блокировка curl и wget может сломать легитимные интеграции (webhook, API-клиенты). Используйте осторожно.
Блокировка пустых и подозрительных User-Agent
RewriteCond %{HTTP_USER_AGENT} ^$ [OR]
RewriteCond %{HTTP_USER_AGENT} ^(-|$|Wget|curl|libwww) [NC]
RewriteRule .* - [F,L]
Блокировка по Referer (спам-комментарии)
RewriteCond %{HTTP_REFERER} (viagra|casino|porn|pharmacy) [NC]
RewriteRule .* - [F,L]
Защита от хотлинкинга
Хотлинкинг — использование ваших изображений или медиафайлов на чужих сайтах. Трафик идёт через ваш сервер, расходуя bandwidth.
Блокировка хотлинков с разрешением своего домена
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?example\.com [NC]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?google\.(com|ru) [NC]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?yandex\.(ru|com) [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp|svg|ico|pdf)$ - [F,L]
Пустой Referer (!^$) разрешён — иначе блокируются прямые переходы по ссылке.
Замена на заглушку вместо 403
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?example\.com [NC]
RewriteRule \.(jpg|jpeg|png|gif)$ /images/hotlink-blocked.png [L]
Ограничение методов HTTP
Разрешайте только нужные методы. Для статического сайта достаточно GET и HEAD.
<LimitExcept GET POST HEAD>
Require all denied
</LimitExcept>
Или через mod_rewrite:
RewriteCond %{REQUEST_METHOD} !^(GET|POST|HEAD)$
RewriteRule .* - [F,L]
Защита от injection и path traversal
Блокировка подозрительных запросов
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} (\.\./|\.\.\\|/etc/passwd|union.*select|insert.*into)
RewriteRule .* - [F,L]
Блокировка path traversal
RewriteCond %{REQUEST_URI} (\.\./|\.\.\\|%2e%2e%2f|%2e%2e/) [NC]
RewriteRule .* - [F,L]
Rate limiting (ограничение частоты запросов)
На shared-хостинге полноценный rate limiting обычно недоступен. Частично можно реализовать через mod_evasive или mod_qos, но они требуют доступа к конфигурации сервера. В .htaccess можно ограничить доступ к отдельным скриптам.
Ограничение по IP для форм
Используйте внешний сервис или приложение. В .htaccess — только блокировка по IP после выявления абуза:
# Блокировка конкретного IP
<RequireAll>
Require all granted
Require not ip 192.168.1.100
Require not ip 10.0.0.0/24
</RequireAll>
Защита wp-login.php (WordPress)
<Files wp-login.php>
Order Deny,Allow
Deny from all
Allow from 192.168.1.0/24
Allow from 203.0.113.50
</Files>
Синтаксис Order/Deny/Allow устарел в Apache 2.4, но ещё встречается. Современный вариант:
<Files wp-login.php>
<RequireAll>
Require not ip 0.0.0.0/0
Require ip 192.168.1.0/24
Require ip 203.0.113.50
</RequireAll>
</Files>
Защита от DDoS и брутфорса
Блокировка по стране (требует mod_geoip)
Если доступен GeoIP:
# Разрешить только РФ и СНГ
SetEnvIf GEOIP_COUNTRY_CODE RU AllowCountry
SetEnvIf GEOIP_COUNTRY_CODE BY AllowCountry
SetEnvIf GEOIP_COUNTRY_CODE KZ AllowCountry
Deny from all
Allow from env=AllowCountry
Ограничение размера запроса
В .htaccess нельзя задать LimitRequestBody для всего сайта — только в основной конфигурации. Но можно ограничить загрузку в PHP:
// В php.ini или .user.ini
upload_max_filesize = 2M
post_max_size = 2M
Безопасные заголовки HTTP
Часть заголовков можно задать через .htaccess:
<IfModule mod_headers.c>
Header set X-Content-Type-Options "nosniff"
Header set X-Frame-Options "SAMEORIGIN"
Header set X-XSS-Protection "1; mode=block"
Header set Referrer-Policy "strict-origin-when-cross-origin"
Header set Permissions-Policy "geolocation=(), microphone=(), camera=()"
</IfModule>
Проверить текущие заголовки можно через Security Headers на reChecker. Подробнее — в руководстве по заголовкам безопасности.
Защита от clickjacking
Header always set X-Frame-Options "SAMEORIGIN"
DENY запрещает встраивание в любые iframe. SAMEORIGIN разрешает только с того же домена.
Защита от MIME-sniffing
Header set X-Content-Type-Options "nosniff"
Запрещает браузеру «угадывать» тип контента и выполнять, например, JS из файла с типом text/plain.
Content Security Policy (упрощённая)
CSP лучше задавать в приложении, но базовая версия возможна в .htaccess:
Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.example.com; style-src 'self' 'unsafe-inline'"
Слишком строгая CSP может сломать сайт. Тестируйте постепенно.
Защита административных путей
Блокировка по IP для /admin
<LocationMatch "^/admin">
Require ip 192.168.1.0/24
Require ip 203.0.113.50
</LocationMatch>
Скрытие версии Apache
В .htaccess нельзя убрать Server — только в httpd.conf:
ServerTokens Prod
ServerSignature Off
Защита от спама в комментариях (дополнительно)
Помимо блокировки по Referer, можно ограничить доступ к скрипту комментариев:
<Files "comment.php">
# Разрешить только POST
<LimitExcept POST>
Require all denied
</LimitExcept>
</Files>
Логирование подозрительной активности
Создание кастомного лога (если разрешено):
SetEnvIf Request_URI "wp-login\.php" suspicious_request
CustomLog /var/log/apache2/suspicious.log combined env=suspicious_request
На shared-хостинге путь к логам может быть другим или недоступным.
Чек-лист безопасности .htaccess
| Мера | Директива / Действие |
|---|---|
| Скрыть .htaccess, .env | <FilesMatch "^\."> |
| Запретить листинг | Options -Indexes |
| Блокировать ботов | RewriteCond %{HTTP_USER_AGENT} |
| Защита от хотлинков | RewriteCond %{HTTP_REFERER} |
| Ограничить методы | <LimitExcept GET POST HEAD> |
| XSS/injection в query | RewriteCond %{QUERY_STRING} |
| Path traversal | RewriteCond %{REQUEST_URI} |
| Заголовки безопасности | Header set X-Frame-Options и др. |
| /admin по IP | <LocationMatch> + Require ip |
Ограничения .htaccess
.htaccess не заменяет полноценную настройку безопасности:
- Нет доступа к
mod_evasive,mod_security— продвинутый WAF только в конфигурации сервера. - Rate limiting ограничен.
- Некоторые заголовки (например, HSTS) лучше задавать на уровне сервера.
- Блокировка по User-Agent легко обходится подменой заголовка.
Используйте .htaccess как первый уровень защиты, особенно на shared-хостинге. Для критичных проектов — выделенный сервер с полноценным WAF и мониторингом.
Блокировка по Referer (пустой и подозрительный)
Пустой Referer может означать прямую ссылку или бота. Разрешить только с известных источников:
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?example\.com [NC]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?google\. [NC]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?yandex\. [NC]
RewriteRule .* - [F,L]
Осторожно: блокировка пустого Referer ломает закладки, ввод URL вручную и часть мобильных приложений.
Защита от directory traversal в URL
RewriteCond %{REQUEST_URI} (\.\./|\.\.\\|%2e%2e%2f|%2e%2e/) [NC]
RewriteRule .* - [F,L]
Ограничение доступа к XML-RPC (WordPress)
WordPress по умолчанию открывает xmlrpc.php для пингбэков и удалённой публикации. Часто используется для брутфорса:
<Files xmlrpc.php>
Require all denied
</Files>
Или через mod_rewrite:
RewriteRule ^xmlrpc\.php$ - [F,L]
Защита от подделки запросов (CSRF)
CSRF защищается на уровне приложения (токены, SameSite cookie). В .htaccess можно лишь ограничить методы для форм:
<LocationMatch "/submit|/comment|/login">
<LimitExcept POST>
Require all denied
</LimitExcept>
</LocationMatch>
Логирование заблокированных запросов
SetEnvIf Request_URI "wp-login\.php" blocked_request
SetEnvIf Remote_Addr "192.168.1.100" blocked_request
CustomLog /var/log/apache2/blocked.log combined env=blocked_request
На shared-хостинге путь к логам может отличаться или быть недоступным.
Проверка после внедрения
После добавления правил:
- Убедитесь, что сайт открывается и статика загружается.
- Проверьте формы входа и отправки данных.
- Протестируйте API и webhook, если они используют curl/wget.
- Проверьте заголовки через Security Headers.
Резервное копирование .htaccess
Перед изменениями создайте копию:
cp .htaccess .htaccess.backup.$(date +%Y%m%d)
При ошибке 500 восстановите файл и проверьте синтаксис. Некорректный .htaccess может заблокировать доступ к сайту.
Подробнее о настройке Apache — в полном руководстве по .htaccess.