Краулерлерге арналған тұзақ
Сайттың өзі шексіз көп мекенжай тудырады, іздеу роботы оларды тәулік бойы аралайды, ал сервер адал түрде «бет табылды» деп жауап береді. Мұны қалай анықтап, nginx-тің екі ережесімен жабуға болатынын қарастырамыз.
Не болып жатыр
Бетте ағымдағы мекенжайға қызметтік параметрді – ол параметрдің онда бар-жоғын тексермей – қосып жазатын сілтеме немесе скрипт бар. Робот сілтеме бойынша өтіп, мекенжайы сәл ұзарған сол бетке түседі, онда дәл сондай сілтемені табады – осылай шеңбер бойынша қайталана береді.
Әр шеңбер URL-кодтаудың тағы бір қабатын қосады: ? сұрақ белгісі %3F болып, ол %253F-ке, одан әрі %25253F-ке айналады. Мекенжай ұзарады, ал бет сол күйінде қалады.
Негізгі белгі – сұрау жолының ішінде кез келген кодтау түріндегі екінші сұрақ белгісі пайда болады. Дұрыс мекенжайда мұндай болуы мүмкін емес: бірінші ? жолды параметрлерден бөледі, ал одан әрі бөлгіш ретінде тек & қолданылады.
Неліктен бұл қымбатқа түседі
- Сервер. Әрбір осындай мекенжай – беттің толыққанды жинақталуы. Талданған сайтта бұл тәулігіне 18 мың мағыналы жинақтауға қарсы 94 мың артық жинақтау.
- Іздеу нәтижелері. Робот краулингтік бюджетті тауар карточкаларының орнына қоқысқа жұмсайды. Бұл мекенжайлардың бәрі – бір беттің дубльдері, ал сервер оларға 200 деп жауап береді, яғни: бет бар, индекстеңіз деп растайды.
- Аналитика. Кіру санының көрсеткіштері бірнеше есе ұлғайып кетеді, шешімдер дұрыс емес деректер бойынша қабылданады.
- Диагностика. Логтар қоқысқа толып, ондағы нақты мәселелер көрінбей қалады.
Талданған сайтта негізгі тұтынушы Meta краулерлік желісі болып шықты: ішкі желінің ондаған мекенжайының әрқайсысынан 1700-ге жуық сұрау. Формалды түрде бұл шабуыл емес – робот сайттың өзі берген сілтемелер бойынша адал жүріп отыр.
Кез келген сайтты қалай тексеруге болады
Қолжетімділік логы бойынша бір команда. Ол сұрау жолының ішінде екінші сұрақ белгісі кездесетін сұраулардың үлесін санайды:
# логқа өз жолыңызды қойыңыз
LOG=/var/log/nginx/access.log
TOTAL=$(grep -ac . "$LOG")
LOOP=$(grep -acE '"[A-Z]+ [^ "]*\?[^ "]*(\?|%3F|%253F)' "$LOG")
echo "циклге түскен: $LOOP / барлығы $TOTAL"
Егер үлесі байқаларлық болса, нақты қандай мекенжайлар және қай параметр кінәлі екенін қараңыз:
grep -aoE '"[A-Z]+ [^ "]*\?[^ "]*(\?|%3F|%253F)[^ "]*' "$LOG" \
| sed 's/"[A-Z]* //' | cut -c1-90 | sort | uniq -c | sort -rn | head -20
Нәтижеде қайталанатын параметр көрінеді. Битриксте бұл әдетте HOME_PAGE және bxrand; басқа қозғалтқыштарда – сессия идентификаторлары, «артқа қайту» сілтемелері, сүзгі және сұрыптау параметрлері, күнтізбелік мұрағаттар. Параметр атауын әрдайым осы мәтіннен емес, өз логыңыздан алыңыз.
nginx-ке не қосу керек
Ережелер сайттың server блогына, басқа location блоктарынан жоғары қойылады. Жауап – параметрсіз таза мекенжайға 301: робот «нақты бет міне осы жерде» деген бірмәнді сигнал алады, жинақталған дубльдер біртіндеп біріктіріледі.
Мекенжайлық нұсқа – ұсынылатын
# Параметрдің қайталануы, соның ішінде өз мәнінің ішінде
if ($args ~* "HOME_PAGE.*HOME_PAGE") { return 301 $scheme://$host$uri; }
# Өсудің «ұрығы»: параметр мәнінен кейін бірден келетін сұрақ белгісі
if ($args ~* "HOME_PAGE=[^&]*([?]|%3F|%253F)") { return 301 $scheme://$host$uri; }
# Қатысатын екінші параметрдің қайталануы
if ($args ~* "bxrand.*bxrand") { return 301 $scheme://$host$uri; }
Параметрдің бір рет кездесуін жұмыс күйінде қалдырамыз – ол үлгінің өзіне қажет. Тек қайталану мен өсуді ғана үземіз.
Әмбебап нұсқа – параметрлер көп болса
# Сұрау жолындағы кез келген кірістірілген сұрақ белгісін ақау деп есептейміз
if ($args ~ "([?]|%3F|%253F)") { return 301 $scheme://$host$uri; }
Мәннің ішінде %3F болуы рұқсат етілетін заңды мекенжайлар бар: кірістірілген сілтемесі бар параметрлер – back_url, backurl, redirect, return_url, сондай-ақ жарнамалық белгілер. «Кез келген сайтты қалай тексеруге болады» қадамындағы командамен логты тексеріп, сәйкестіктер арасында нақты жұмыс істейтін ештеңе жоқ екеніне көз жеткізіңіз. Егер бар болса, мекенжайлық нұсқаны алыңыз.
robots.txt – тіл алатын роботтар үшін
Disallow: /*HOME_PAGE=
Disallow: /*?bxrand=
Бұл алмастыру емес, толықтыру: кейбір роботтар бұл файлды елемейді, сондықтан nginx-тегі ереже негізгі қорған болып қала береді.
Сонымен қатар: сканерлер сүзгісі
Сол бір кезеңде және сол база негізінде орнатылады. Екі бөлігі бар: http контекстіндегі карталар және олардың сайт конфигурациясында қолданылуы.
/etc/nginx/conf.d/bot-protection.conf
# Сенімді мекенжайлар. Өзіңіздікімен толтырыңыз – әйтпесе өз мониторингіңізді кесіп тастайсыз.
geo $oh_trusted {
default 0;
127.0.0.1/32 1;
СЕРВЕР_IP/32 1; # сайттың крондары curl арқылы жүреді!
МОНИТОРИНГ_IP/32 1; # Zabbix, Blackbox-Exporter
КЕҢСЕ_IP/32 1;
}
# Пайдалы боттар – әрдайым өткіземіз
map $http_user_agent $oh_good_bot {
default 0;
"~*(Googlebot|Google-InspectionTool|Storebot-Google|AdsBot-Google)" 1;
"~*(YandexBot|YandexMetrika|YandexRenderResourcesBot|YandexImages|YandexDirect)" 1;
"~*(bingbot|BingPreview|Applebot|DuckDuckBot|Mail\.RU_Bot)" 1;
"~*(facebookexternalhit|Twitterbot|TelegramBot|WhatsApp|Slackbot|vkShare)" 1;
}
# Қажетсіздер: осалдық сканерлері, желінің «ғылыми» сканерлері,
# пайдасыз SEO-краулерлер, жалаң http-кітапханалар, бос UA
map $http_user_agent $oh_bad_bot {
default 0;
"" 1;
"~*(zgrab|masscan|zmap|nmap|nikto|sqlmap|wpscan|nuclei|httpx|dirbuster|gobuster|acunetix|netsparker|qualys|openvas)" 1;
"~*(Censys|Shodan|InternetMeasurement|Expanse|NetSystemsResearch|CriminalIP|leakix|Stretchoid|BinaryEdge|ProjectDiscovery)" 1;
"~*(MJ12bot|DotBot|AhrefsBot|SemrushBot|BLEXBot|DataForSeo|Barkrowler|SeekportBot|serpstat|ZoominfoBot|PetalBot|Bytespider|MegaIndex)" 1;
"~*(python-requests|python-httpx|aiohttp|Go-http-client|libwww-perl|Wget/|Scrapy|Java/|okhttp|PostmanRuntime|curl/|WinHttp)" 1;
}
# Лимит кілті: бос = шектеусіз (сенімділер мен іздеу жүйелері)
map "$oh_trusted$oh_good_bot" $oh_limit_key {
default $binary_remote_addr;
"~^1" "";
"~^01" "";
}
limit_req_zone $oh_limit_key zone=oh_req:16m rate=10r/s;
limit_req_zone $oh_limit_key zone=oh_static:16m rate=100r/s;
limit_req_status 429;
Сайттың server блогында
# Реті маңызды: алдымен тыйым, содан кейін ерекшеліктер оны алып тастайды
set $oh_deny 0;
if ($oh_bad_bot) { set $oh_deny 1; }
if ($oh_good_bot) { set $oh_deny 0; }
if ($oh_trusted) { set $oh_deny 0; }
if ($oh_deny) { return 403; }
limit_req zone=oh_req burst=40 nodelay;
# Статика блогында – өзінің еркін аймағы
location ~* \.(jpg|jpeg|png|gif|svg|webp|ico|css|js|woff2?|ttf|otf|pdf)$ {
limit_req zone=oh_static burst=300 nodelay;
expires 30d;
}
| Кім | Жауап | Негіздеме |
|---|---|---|
| Нақты браузер | 200 | ешбір картаға сәйкес келмейді |
| Googlebot, YandexBot, bingbot | 200 | UA ақ тізімі, лимит қолданылмайды |
| Мониторинг, сайт крондары | 200 | IP ақ тізімі – UA-дан маңыздырақ |
| python-requests, curl, Wget, Go-http | 403 | ақ IP-сыз жалаң кітапхана |
| zgrab, masscan, sqlmap, Nikto | 403 | осалдық сканері |
| Censys, Shodan, InternetMeasurement | 403 | желіні «ғылым үшін» сканерлеу |
| MJ12bot, AhrefsBot, PetalBot | 403 | пайдасы жоқ SEO-краулер |
| User-Agent-сыз сұрау | 403 | браузерлер бұлай жүрмейді |
| Циклге түскен мекенжай | 301 | таза URL-ге бағыттаймыз |
Төрт тұзақ
Тырнақшадағы кері қиғаш сызық жұмыс істемейді. nginx оны конфигурацияны талдау кезеңінде алып тастайды: "\?" ? болып қалады да, квантификаторға айналады – ереже nginx -t тексерісінен өтеді де, үнсіз іске аспайды. [?] символдық класын жазыңыз.
Крондар көбіне curl арқылы жүреді. Ал curl/ қажетсіздер тізімінде тұр. IP бойынша ақ тізімсіз сіз өз сайтыңыздың тапсырмаларын бұғаттап аласыз және мұны бірден байқамайсыз – сырттай бәрі жұмыс істеп тұрады. Алдымен мекенжайларды енгізіңіз, содан кейін бұғаттауды қосыңыз.
Беттер мен статикаға бір лимит – нақты адамдарға бас тарту деген сөз. Каталог бетіндегі өлшеу: бірінші секундта 121 сұрау – суреттер, стильдер, скрипттер. Ортақ аймақта келуші лимитке тіреліп, суреттердің жартысының орнына 429 алады. Статикаға бөлек еркін аймақ қажет.
Сенімді мекенжайдан бұғаттауды тексеру мүмкін емес. Серверден және кеңседен әрдайым 200 келеді – олар ақ тізімде. Тексеру үшін geo блогындағы қажетті жолды уақытша түсініктемеге айналдырып, тестті өткізіп, қайтадан қалпына келтіріңіз.
Сайтқа енгізу тәртібі
- Лог бойынша циклге түскен мекенжайлардың үлесін анықтаңыз – «Кез келген сайтты қалай тексеруге болады» қадамындағы команда. Өзгерістерге дейінгі санды жазып алыңыз.
- Кінәлі параметрді нұсқаулықтағы үлгі бойынша емес, өз логыңыз бойынша анықтаңыз.
- IP ақ тізімін жинаңыз: сервердің өзі, мониторинг, кеңсе, төлемдік callback-тер, 1С-пен алмасу.
- Конфигурациялардың атауында күні бар сақтық көшірмелерін жасаңыз.
- Тұзақты үзу ережелерін қосыңыз. Тексеріңіз: жалғыз параметр – 200, қайталану – 301.
- Карталар мен боттарды бұғаттауды қосыңыз. Сырттан, ақ тізімнен тыс мекенжайдан тексеріңіз.
- Нақты браузер, Googlebot, YandexBot, мониторинг, крондар өтетінін тексеріңіз.
- Каталогтың ауыр бетін браузерде ашып, ешбір ресурста 429 жоқ екеніне көз жеткізіңіз.
- robots.txt файлына Disallow жолдарын қосыңыз.
- Бір сағаттан кейін статистиканы алыңыз: қанша 403 және 301, ең бастысы – қанша 429. Соңғыларының нөл болуы нақты келушілерге әсер етпегенін білдіреді.
- Тапсырыс берушіге ескертіңіз: метрикалардағы кіру саны төмендейді. Бұл сатып алушылар емес, қоқыс кетіп жатыр.
Жұмыс істеп тұрған сайттағы 23.08.2026 жұмыстарының нәтижелері бойынша құрастырылды. Конфигурация nginx 1.30, Ubuntu 24.04, FastPanel-де тексерілді. User-Agent және мекенжайлар тізімдері нақты сайттың логтары бойынша толықтырылады.