У нас на хосте развернут стек LEMP использующий NGINX в качестве веб сервера. А для NGINX настроено логирование и ротация логов. Пришло время заглянуть непосредственно в access лог и разобраться, какую информацию он нам дает.
[root@waky ~]# tail /var/log/nginx/waky.ru/access.log
...
5.255.253.36 - - [17/Mar/2025:14:09:23 +0700] "GET /sitemap.xml HTTP/1.1" 200 4733 "-" "Mozilla/5.0 (compatible; YandexWebmaster/2.0; +http://yandex.com/bots)"
176.55.35.233 - - [17/Mar/2025:14:30:29 +0700] "GET / HTTP/2.0" 200 62058 "https://waky.ru/%d0%b2%d1%81%d0%b5-%d0%b7%d0%b0%d0%bc%d0%b5%d1%82%d0%ba%d0%b8/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36"
...
По умолчанию в NGINX используется именно такой формат. Он задан в файле конфигурации /etc/nginx/nginx.conf
...
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
...
Теперь имея под рукой пару примеров и шаблон, разберем каждый аргумент в строке лога.
$remote_addr – 176.55.35.233 / 5.255.253.36 – адрес, с которого пришел запрос, в большинстве случаев это IP адрес, а иногда доменное имя
– первый прочерк, не несет смысловой нагрузки, может немного путать, так как таким же прочерком может обозначаться отсутствие значения аргумента, но в данном случае это лишь прочерк в шаблоне
$remote_user – в обоих примерах на месте данного аргумента стоит прочерк –, так как значение отсутствует, такую картину вы будете видеть в подавляющем количестве случаев, $remote_user отображает имя пользователя, под которым была пройдена Basic Auth авторизация
[$time_local] – [17/Mar/2025:14:09:23 +0700] / [17/Mar/2025:14:30:29 +0700] – время поступления запроса, время указано локальное серверное.
“$request” – “GET /sitemap.xml HTTP/1.1” / “GET / HTTP/2.0” 200 – сам запрос, состоит из трех частей: тип запроса для обычного сайта это либо GET, либо POST; страница запроса, путь указан локальный, где / это корневая веб директория; версия HTTP протокола по которому происходит подключение.
$status – 200 / 200 – код статуса ответа от веб сервера, где 200 это успешно обработанный запрос
$body_bytes_sent – 4733 / 62058 объем данных в байтах отправленных по запросу
“$http_referer” – “-“ / “https://waky.ru/%d0%b2%d1%81%d0%b5-%d0%b7%d0%b0%d0%bc%d0%b5%d1%82%d0%ba%d0%b8/” – страница с которой пришел запрос, может быть как внешней, так и внутренней, в случае прямого обращения к странице – прочерк
“$http_user_agent” – “Mozilla/5.0 (compatible; YandexWebmaster/2.0; +http://yandex.com/bots)” / “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36” – юзер агент содержит информацию о клиентском браузере, либо название бота и информацию о нем если его создатели используют бота в открытую.
“$http_x_forwarded_for” – в примерах отсутствует, отображает реальный IP с которого пришел запрос, если тот поступил через прокси либо балансировщик нагрузки.
Понимая, что значит каждый элемент в логах, мы можем использовать это в повседневных задачах. Например, при всплеске нагрузки мы можем проверить с каких адресов в это время было сделано больше всего запросов.
[root@waky ~]# grep "17/Mar/2025:14" /var/log/nginx/waky.ru/access.log | awk '{print $1}' | sort | uniq -c | sort -n | tail
11 196.251.90.93
11 209.172.2.50
16 45.157.54.155
16 47.119.16.237
17 5.255.253.36
22 82.52.20.36
25 95.214.53.106
31 95.214.53.107
52 185.242.226.10
114 176.55.35.233
Мы ищем в лог файле все строки с датой 17/Mar/2025 и часом 14, и от каждой строки берем только первую часть (адрес) с помощью команды awk, сортируем по количеству и оставляем топ 10 значений.
Меняя значение в awk ‘{print $1}’ можно сортировать, например по странице обращения {print $7} или коду ответа {print $9}.
Если обнаружили подозрительный адрес, проверьте, какие запросы от него исходили за последнее время:
grep "17/Mar/2025:14" /var/log/nginx/waky.ru/access.log | grep "176.55.35.233" | awk '{print $7}' | sort | uniq -c | sort -n | tail
Так если один и тот же адрес, совершает аномальное количество запросов к одной и той же странице, это повод задуматься. А если с адреса исходят сотни запросов к логин форме или админке, то скорее всего, кто-то пытается ее ломать с помощью брутфорса. Это повод заблокировать адрес.
Основа работы с логами состоит в том, чтобы из всего объема информации выудить ту, которая связана непосредственно с решаемой задачей. Если это скачки нагрузки – найти адреса с которых приходит больше всего запросов. Если сайт стал чаще выдавать ошибки – собрать список страниц, которые возвращают соответствующие коды ответов.
Правильно сортируя и фильтруя логи по используемым аргументам, вы сможете сильно сузить зону поиска проблемы, а значит быстрее найдете решение.