
Сегодня речь пойдёт о том, что такое хотлинкинг и почему вебмастеру (владельцу сайта) надо срочно настроить защиту от него. Сейчас вы поймёте, как кормить чужих котиков, оплачивая их корм из своего кармана, и надо ли вам это.
Что такое хотлинкинг, или «Эй, дружок, а можно я твой сервер в рабство возьму?»
Представьте: у вас есть холодильник, полный вкусняшек. А ваш сосед (который вам даже не друг) просто встраивает дверцу своего холодильника в ваш и спокойно берёт оттуда еду. При этом вы платите за электричество, а он ещё и хвастается перед гостями: «Смотрите, какой у меня крутой холодильник!».
Вот хотлинк — это и есть та самая наглая дверца.
Чем это плохо для вас, дорогой вебмастер?
- Ваш сервер работает за вас и за того парня
Каждый раз, когда кто-то загружает страницу с вашей картинкой, но не на вашем сайте, ваш сервер тратит ресурсы на отдачу контента. Трафик — не резиновый, а хостинг-провайдеры любят выставлять счета за превышение лимитов. - Вы спонсируете чужой успех
Какой-то левый сайт использует ваш контент, привлекает посетителей, зарабатывает на рекламе… А вы? А вы просто платите за его хостинг. Красиво, правда? - Ваш сайт может лечь от нагрузки
Если вдруг картинку с вашего сервера запостит какой-нибудь популярный форум или (не дай бог) реддит, ваш сервер захлебнется в запросах. А потом прилетит счет за апгрейд тарифа или (еще хуже) ваш хостинг вежливо пошлет вас в бан за превышение лимитов. - SEO? Какое ещё SEO?
Поисковики видят, что ваш контент висит на чужих сайтах, и могут решить, что это не ваш контент. В итоге ваш сайт проседает в выдаче, а ворующий — растёт. Ирония? Нет, просто интернет.
Как защититься? Или «Нет, дружок, это мой холодильник!»
К счастью, есть несколько способов дать отпор воришкам.
.htaccess — старый добрый «Не влезай, убьёт!»
Если у вас Apache, можно добавить в .htaccess магические строки:
1 2 3 4 |
RewriteEngine on RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !^https://(www\.)?ваш-сайт\.ру [NC] RewriteRule \.(jpg|jpeg|png|gif|mp4|css|js)$ - [F,L] |
Это значит: «Если запрос пришел не с моего сайта — получи, дружок, ошибку 403 (Forbidden)!».
Замена картинок на «сюрпризы»
Можно настроить сервер так, чтобы для хотлинкеров картинки подменялись на что-то неожиданное. Например:
— Грустный пепельник с надписью «Хотлинкинг — это плохо».
— Мем «Ты что, совсем совести нет?».
— Гифка с бесконечно грузящимся пингвином.
(Особо злобные вебмастера ставят порно или вирусы, но мы, конечно, не советуем нарушать законы. Хотя идея заманчивая.)
CDN с защитой от хотлинкинга
Многие CDN (Cloudflare, Imgix и др.) умеют блокировать хотлинкинг на лету. Включил галочку — и спи спокойно.
Водяные знаки (для особо циничных)
Если картинки важные и уникальные, можно залить их с водяными знаками. Пусть воришки краснеют, когда на их сайте красуется логотип «Украдено с example.com».
Защита от хотлинка на уровне веб-сервера
Если ваш сайт хостится на виртуальной машине, то считайте, что вы счастливчик. Настроить анти хотлинкинг можно на уровне сервера за несколько простых ходов. Сейчас расскажу, как это сделать.
Если вы на виртуальной машине, VPS, VDS, то, безусловно, имеете доступ к серверу по SSH.
Для Apache
Добавьте в .htaccess в корне сайта или в конфиг виртуального хоста (/etc/apache2/sites-available/ваш-сайт.conf):
1 2 3 4 5 6 7 8 9 |
RewriteEngine On RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !^https?://(www\.)?ваш-домен.com [NC] RewriteCond %{HTTP_REFERER} !^https?://(www\.)?другой-разрешенный-домен.com [NC] RewriteRule \.(jpg|jpeg|png|gif|webp|svg|mp4)$ - [NC,F,L] После правки перезапустите Apache: sudo systemctl restart apache2 |
Для Nginx
📌 Пошаговая инструкция по применению:
Подключаемся к серверу по SSH:
1 |
ssh ваш_пользователь@IP_сервера |
Откройте конфиг вашего сайта для редактирования:
1 |
sudo nano /etc/nginx/sites-available/site.ru |
Вставьте правила защиты от хотлинкинга в блок, который фактически обрабатывает HTTPS-запросы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# 🔒 ЗАЩИТА ОТ ХОТЛИНКИНГА location ~* \.(jpg|jpeg|png|gif|webp|svg|mp4)$ { valid_referers none blocked site.ru www.site.ru facebook.com www.facebook.com twitter.com www.twitter.com t.co vk.com www.vk.com telegram.org www.telegram.org; if ($invalid_referer) { return 403; # Или можно показывать заглушку: # rewrite ^ /blocked-image.jpg; } # Отключаем кэширование этих правил add_header Cache-Control "no-cache, no-store, must-revalidate"; expires 0; } # ... остальные настройки ... |
Весь конфиг целиком должен выглядеть примерно так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# Блокируем прямой доступ по IP server { listen 80; server_name 85.205.117.134; return 403; } server { listen 443 ssl; server_name 85.205.117.134; ssl_certificate /etc/letsencrypt/live/site.ru/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/site.ru/privkey.pem; return 403; } # Редирект с HTTP на HTTPS server { listen 80; server_name site.ru www.site.ru; return 301 https://site.ru$request_uri; } # Основной сервер server { listen 443 ssl; server_name site.ru www.site.ru; root /var/www/site.ru; index index.php index.html index.htm; ssl_certificate /etc/letsencrypt/live/site.ru/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/site.ru/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # 🔒 ЗАЩИТА ОТ ХОТЛИНКИНГА (добавлено) location ~* \.(jpg|jpeg|png|gif|webp|svg|mp4)$ { valid_referers none blocked site.ru www.site.ru facebook.com www.facebook.com twitter.com www.twitter.com t.co vk.com www.vk.com telegram.org www.telegram.org; if ($invalid_referer) { return 403; # Или можно показывать заглушку: # rewrite ^ /blocked-image.jpg; } # Отключаем кэширование этих правил add_header Cache-Control "no-cache, no-store, must-revalidate"; expires 0; } location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.1-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location ~ /\.ht { deny all; } } |
Сохраните конфиг: Ctrl+O → Enter → Ctrl+X.
Проверяем синтаксис и перезагружаем Nginx:
1 |
sudo nginx -t && sudo systemctl restart nginx |
📌 Проверка работы
Тест 1: Запрос с вашего сайта → Должен разрешаться (200 OK):
1 |
curl -I -H "Referer: https://site.ru" https://site.ru/image.jpg |
Тест 2: Запрос для соцсетей (эмулируем запрос от Facebook) → Должен быть статус 200 OK:
1 |
curl -I -H "Referer: https://facebook.com" https://site.ru/image.jpg |
Тест 3: Запрос для чужого сайта → Должен быть статус 403 Forbidden:
1 |
curl -I -H "Referer: https://example.com" https://site.ru/image.jpg |
Тест 4: Запрос прямого доступа (пустой Referer) → Должен быть статус 403 Forbidden:
1 |
curl -I https://site.ru/image.jpg |
🔥 Важные нюансы:
Для WordPress добавьте в wp-config.php:
1 |
define('WP_CACHE', false); // На время тестов |
Если используете Cloudflare, добавьте его рефереры:
1 |
valid_referers ... cloudflare.com www.cloudflare.com; |
Для полного сброса кэша:
1 |
sudo rm -rf /var/cache/nginx/* |
Правила должны быть в HTTPS-блоке (который слушает порт 443).
После изменений обязательно перезагружайте Nginx.
Проверяйте через curl (как в предыдущих инструкциях).
Если хотите использовать вариант с блокировкой прямой загрузки изображений, то надо немного скорректировать код:
1 2 3 4 5 6 7 |
location ~* \.(jpg|jpeg|png|gif|webp|svg|mp4)$ { # Убрали "none" - теперь запрещаем пустые Referer valid_referers blocked site.ru www.site.ru ... Остальной код без изменений |
Убрали none из valid_referers — теперь запросы без Referer будут блокироваться.
Оставили blocked — разрешает запросы с пустым Referer, но только для авторизованных пользователей (на практике лучше тоже убрать, если хотим полный запрет).
После изменений не забудьте:
1 |
sudo nginx -t && sudo systemctl restart nginx |
📌 Проверка после изменений:
1 2 |
# Должен вернуть 403 (запрет) curl -I https://site.ru/image.jpg |
Что делать, если миниатюра записи не подтягивается в сниппет социальных сетей?
Проблема с отображением миниатюр в соцсетях при работающей защите от хотлинкинга обычно связана с кэшированием или некорректными Open Graph-тегами. Можно попробовать это исправить так.
1. Проверка Open Graph-тегов
Добавьте в
1 2 3 4 |
<meta property="og:image" content="https://site.ru/image.jpg"> <meta property="og:image:width" content="1200"> <meta property="og:image:height" content="630"> <meta name="twitter:image" content="https://site.ru/image.jpg"> |
2. Обновление правил Nginx
Замените текущий блок защиты на этот (учитывает User-Agent соцсетей):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
location ~* \.(jpg|jpeg|png|gif|webp|svg|mp4)$ { # Инициализируем переменную set $allow_request 0; # Проверяем User-Agent ботов if ($http_user_agent ~* (facebookexternalhit|Twitterbot|VKShare|TelegramBot)) { set $allow_request 1; } # Проверяем разрешенные рефереры if ($http_referer ~* (nakuhonke\.ru|facebook\.com|twitter\.com|vk\.com|t\.me)) { set $allow_request 1; } # Блокируем если не прошло проверку if ($allow_request = 0) { return 403; } add_header Cache-Control "public, max-age=3600"; } |
3. Очистка кэша
В WordPress:
- Отключите кэширующие плагины на время теста.
- Обновите постоянные ссылки (Настройки → Постоянные ссылки → Сохранить).
В соцсетях:
Facebook: Facebook Sharing Debugger
VK: Очистка кэша ВК
На сервере:
1 2 |
sudo rm -rf /var/cache/nginx/* sudo systemctl restart nginx |
✅ Ещё раз проверим включение защиты от хотлинкинга:
1. Для соцсетей (должен быть 200 OK):
1 2 |
curl -I -H "Referer: https://facebook.com" https://site.ru/image.jpg curl -I -H "User-Agent: FacebookExternalHit" https://site.ru/image.jpg |
2. Для ваших сайтов (должен быть 200 OK):
1 |
curl -I -H "Referer: https://site.ru" https://site.ru/image.jpg |
3. Для прямых загрузок (должен быть 403 Forbidden):
1 |
curl -I https://site.ru/image.jpg |
4. Для чужих сайтов (должен быть 403 Forbidden):
1 |
curl -I -H "Referer: https://example.com" https://site.ru/image.jpg |
4. Проверка работы
Протестируйте через официальные валидаторы:
Вывод: защищайтесь, или за вас это сделает счет за хостинг
Хотлинкинг — это не просто «некрасиво». Это деньги из вашего кармана, нагрузка на сервер и подрыв SEO. Если вы до сих пор не настроили защиту — ваш сервер уже, возможно, спонсирует десяток левых сайтов.
Так что включите защиту, пока какой-нибудь гиковский блог не решил, что ваш сервер — это бесплатный CDN для гифок с котиками.
(А если решите не защищаться — хотя бы выставляйте им счет. Вдруг заплатят?) 🚀
