Безопасность сайта через .htaccess
Файл .htaccess — первая линия обороны сайта на Apache: им закрывают доступ к чувствительным файлам, ограничивают вход по IP или паролю, отключают листинг каталогов, запрещают выполнение PHP в папках загрузок, отбивают ботов и хотлинк, ставят заголовки безопасности. Ниже — готовые блоки под каждую задачу: вставляйте в .htaccess в корне сайта (или в нужном каталоге), плейсхолдеры (example.com, 203.0.113.x, пути) замените на свои. При сомнениях прогоните файл через линтер /check/, правила mod_rewrite — через тестер /rewrite/, а собрать .htaccess из чекбоксов можно в генераторе. В конце — чеклист на 5 минут.
Важно про синтаксис: блоки ниже даны для Apache 2.4 (Require all denied, Require ip). Если у вас Apache 2.2 — нужен старый синтаксис (Order / Allow / Deny); сконвертировать туда-обратно поможет конвертер 2.2↔2.4.
1. Заголовки безопасности (одной строкой)
HTTP-заголовки ответа защищают посетителей от кликджекинга, части XSS, downgrade-атак и «угадывания» MIME-типа. Ставятся через mod_headers директивой Header always set (always — чтобы заголовок добавлялся и к страницам ошибок 403/404).
<IfModule mod_headers.c> # HSTS — только если сайт уже полностью на HTTPS Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" # начните с Content-Security-Policy-Report-Only, потом ужесточайте Header always set Content-Security-Policy "default-src 'self'" Header always set X-Frame-Options "SAMEORIGIN" Header always set X-Content-Type-Options "nosniff" Header always set Referrer-Policy "strict-origin-when-cross-origin" Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()" </IfModule>
- HSTS (
Strict-Transport-Security) запрещает открыть сайт поhttp://в течениеmax-age— включайте осознанно, начните с маленького значения (например,max-age=300). - CSP легко ломает inline-скрипты и стили — сначала включите
Content-Security-Policy-Report-Only, посмотрите отчёты, потом переключайте на боевой заголовок. - Без
alwaysзаголовок не попадёт на ответы с ошибкой (403 / 404 / 500).
Подробный разбор каждого заголовка и его опций — справочник HTTP-заголовков; собрать нужные чекбоксами — генератор (блок «Security headers»).
2. Закрыть доступ к чувствительным файлам
По умолчанию веб-сервер отдаёт любой файл в корне сайта — включая конфиги с паролями БД, дампы, бэкапы, историю git. Закройте их явно.
<FilesMatch "^\.ht"> Require all denied </FilesMatch>
<FilesMatch "(^\.env|^wp-config\.php$|^configuration\.php$|^composer\.(json|lock)$|\.(bak|old|orig|save|swp|sql|sqlite|log)$|^readme\.html$)"> Require all denied </FilesMatch>
RedirectMatch 404 /\.(git|svn|hg)(/|$)Синтаксис выше — Apache 2.4 (Require all denied). На Apache 2.2 внутри <FilesMatch> нужно Order allow,deny + Deny from all — сконвертировать поможет конвертер 2.2↔2.4. Проверить, что блок без ошибок, — линтер .htaccess.
3. Отключить листинг каталогов
Если в папке нет index.php / index.html, Apache (mod_autoindex) показывает список её файлов — видно структуру, забытые бэкапы и дампы. Отключите автоиндекс:
Options -IndexesЕсли листинг где-то всё же нужен — спрячьте опасные расширения: IndexIgnore *.bak *.sql *.zip .*. Или просто положите в каталог пустой index.html.
- Грабли:
Options -Indexesможет требоватьAllowOverride Options(илиAllowOverride All) — иначе500 Internal Server Errorс.htaccess: Options not allowed here; тогда правило ставит хостер в конфиге сервера.
Что делать, если .htaccess уже отдаёт 500, — гид «Почему .htaccess не работает».
4. Доступ только с доверенных IP
Типовой кейс: закрыть /wp-admin/, staging-копию, /phpmyadmin/ или служебные скрипты — только со своего или офисного IP. Положите такой .htaccess в нужный каталог:
<RequireAll> Require ip 203.0.113.0/24 Require ip 192.0.2.15 </RequireAll>
Если условие одно — достаточно просто Require ip 203.0.113.0/24 192.0.2.15 без <RequireAll>. Наоборот — пускать всех, кроме нескольких IP:
<RequireAll> Require all granted Require not ip 198.51.100.7 </RequireAll>
- За CDN / прокси
%{REMOTE_ADDR}— это IP прокси, а не клиента; реальный IP передаётся в заголовкеX-Forwarded-For(его разбор — /headers/ → заголовки запроса), и фильтровать по нему в.htaccessненадёжно.
Apache 2.2-синтаксис (Order deny,allow / Allow from) — конвертер 2.2↔2.4. Подробный гайд — статья «Ограничение доступа по IP». Заблокировать целые страны (по GeoIP / Cloudflare / спискам IP) — генератор /geo-block/.
5. Защита паролем (HTTP Basic)
Быстрый способ закрыть staging или служебный раздел — HTTP Basic-авторизация. Подходит «для своих»; не подходит как серьёзная защита: сам по себе Basic не шифрует данные (нужен HTTPS), нет кнопки «выйти», пароль шлётся при каждом запросе.
AuthType Basic AuthName "Restricted area" AuthUserFile /home/USER/.htpasswd Require valid-user
AuthUserFile— абсолютный путь; файл.htpasswdкладите вне document root, чтобы его нельзя было скачать по прямой ссылке.- Пароли в
.htpasswdхраните хешированными (bcrypt или APR1-MD5), не открытым текстом.
Скомбинировать «или из офиса, или по паролю» (Apache 2.4):
AuthType Basic AuthName "Restricted" AuthUserFile /home/USER/.htpasswd <RequireAny> Require ip 203.0.113.0/24 Require valid-user </RequireAny>
Сгенерировать .htpasswd (bcrypt / APR1-MD5 / SHA / crypt) — генератор .htpasswd; пошаговый туториал — статья «Защита папки паролем».
6. Запретить выполнение PHP в загрузках
Главный вектор взлома CMS: через форму загрузки заливают shell.php в /uploads/ и запускают. Контрмера — в .htaccess внутри папки загрузок запретить отдачу и выполнение PHP-файлов:
<FilesMatch "\.(ph(p[0-9]?|tml|ar|tt)|phps)$"> Require all denied </FilesMatch> # на старых конфигурациях вместо/вместе: # php_flag engine off # RemoveHandler .php .phtml # RemoveType .php
- Грабли: злоумышленник может залить в
/uploads/и собственный.htaccess(включив выполнение обратно), еслиAllowOverrideв конфиге сервера это позволяет. Надёжная контрмера ставится хостером:AllowOverride None(или хотя бы безFileInfo) на каталоге загрузок — из.htaccessсебя так не «выключить».
Проверить, что правило написано без ошибок, — линтер .htaccess.
7. Блокировка ботов, сканеров и хотлинка
Плохие краулеры и сканеры уязвимостей жрут трафик и ищут дыры; хотлинк ворует трафик с картинок. Блокировка по User-Agent (через mod_setenvif — безопаснее, чем [OR]-цепочки в mod_rewrite):
SetEnvIfNoCase User-Agent "(libwww|wget|nikto|sqlmap|nmap|masscan|zgrab|python-requests)" bad_bot <RequireAll> Require all granted Require not env bad_bot </RequireAll>
Анти-хотлинк — отдавать 403 на чужие реферы для картинок (замените example\.com на свой домен):
RewriteEngine On RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !^https?://(www\.)?example\.com [NC] RewriteRule \.(jpe?g|png|gif|webp|svg)$ - [F]
- Не блокируйте по слишком общим словам (
bot,http) — случайно отрубите Googlebot, Bingbot или превью соцсетей (Facebook, Telegram, Twitter). - User-Agent и Referer тривиально подделываются — это фильтр от ленивых, не защита.
- Пустой
Referer(!^$) бывает у легитимных переходов из закладок и при HTTPS → HTTP — учитывайте.
Собрать списки ботов и доменов чекбоксами — генератор (блоки «Блокировка ботов», «Защита от хотлинка»); проверить правило на конкретном URL — RewriteRule-тестер; про блокировку по реферу подробно — статья. А если у вас уже есть access.log — прогоните его через анализатор access.log — он найдёт реальных нарушителей и предложит правила; полный гид по ботам, скраперам и AI-краулерам — хаб «Блокировка ботов».
8. Hardening PHP и веб-сервера
Уберите утечки версий и лишние возможности. Скрыть «визитку» PHP / фреймворка из заголовков ответа:
<IfModule mod_headers.c> Header always unset X-Powered-By Header always unset X-AspNet-Version </IfModule>
PHP-настройки — только если PHP подключён как модуль Apache (mod_php) и только те, что уровня PHP_INI_ALL / PHP_INI_PERDIR:
php_flag display_errors Off php_flag log_errors On php_value upload_max_filesize 8M LimitRequestBody 10485760
- Большие грабли: на PHP-FPM / FastCGI / CGI (это большинство современных хостингов) директивы
php_value/php_flagв.htaccessдают500 Internal Server Error(Invalid command 'php_flag'). Там настройки PHP правят через.user.iniв корне сайта или панель хостинга. Линтер /check/ ловитphp_value/php_flagи предупреждает. - Настройки уровня
PHP_INI_SYSTEM(expose_php,allow_url_include,allow_url_fopen) из.htaccessменять нельзя в принципе — только вphp.ini. ServerSignature Off/ServerTokens Prod(убрать версию Apache / ОС из ответов и страниц ошибок) в.htaccessне работают — только в конфиге сервера или виртхоста; упомянуто, чтобы вы не искали зря.LimitRequestBody— наоборот, core-директива Apache, работает на любой конфигурации.
9. Чеклист: проверь за 5 минут
- Заголовки безопасности стоят (HSTS, CSP, X-Frame-Options, nosniff)? — раздел 1, /headers/
- Листинг каталогов выключен (
Options -Indexes)? — раздел 3 wp-config.php/.env/*.sql/*.bakзакрыты? — раздел 2, /check/.git/.svnнедоступны снаружи? — раздел 2- Админка или staging под IP-фильтром либо паролем? — раздел 4, раздел 5, /htpasswd/
- В
/uploads/PHP не исполняется? — раздел 6 X-Powered-Byи версии PHP / Apache скрыты? — раздел 8- В
.htaccessнетphp_value/php_flag, если сайт на PHP-FPM? — раздел 8, /check/ - Все блоки в синтаксисе Apache 2.4 (
Require, неOrder/Allow/Deny)? — /apache24/ - Хочешь, чтобы это проверили автоматически? — прогони свой
.htaccessчерез аудит безопасности (он находит пункты из этого чеклиста + опасныеOptions/CORS/CSP).
10. Ссылки и инструменты
- Если
.htaccessуже скомпрометирован — как найти и вычистить вредоносные правила. - Генератор .htaccess — собрать блоки безопасности чекбоксами.
- Справочник HTTP-заголовков — разбор каждого заголовка безопасности, CORS, кэша.
- Генератор .htpasswd — bcrypt / APR1-MD5 / SHA / crypt.
- Линтер .htaccess — найдёт ошибки синтаксиса и опасные директивы.
- Конвертер 2.2↔2.4 —
Order/Allow/Deny↔Require. - RewriteRule-тестер — проверить правило
mod_rewriteна URL. - Рецепты .htaccess — готовые блоки под типовые задачи.
- Ограничение доступа по IP · Защита папки паролем · Блокировка по реферу · Справочник директив.
- .htaccess для WordPress — WP-специфика (стандартный файл, защита служебных файлов, /wp-admin/ по IP, uploads).