Принцип одного из отделов компании ответственного за взаимодействие с подрядчиками по сайту, так и самостоятельного написания какого-либо функционала для ответственного Web
-сервиса строится по принципу: «не предполагали столкнуться с такой ситуацией». Какова предыстория: есть портал по подбору жалюзей, штор, т.е. какой-то калькулятор, не важно. Ну так вот 13.03.2023
наши добросанные "Коллеги"
включили API и предоставили его дилерам и началось утро:
Андрей Сивков (09:58:23 13/03/2024)
привет
Андрей Сивков (09:58:31 13/03/2024)
глянь, что там на серваке
Андрей Сивков (09:58:35 13/03/2024)
чего-то не открывается
На вопрос, что Вы сделали раз до этого все, работало?
Андрей Сивков (10:29:41 13/03/2024)
да хз, ничего нового за последние дни не выкатывали
Приступил к анализу произошедшего.
По процессам nginx, mysql, логам вышел что идут массовые запросы на подключение к этому самому API и происходит исчерпание ресурсов.
Задал вопрос, а почему перед тем как что-то включить не проверили: может увеличить количество соединение, ресурсов или поэтапно включать клиентов, а не все скопом.
Ответ: см в начале заметки принцип «не предполагали столкнуться с такой ситуацией», т.е. разбираться с проблемой будем по мере возникновения проблемы.
Я же в свою очередь вышел уже после всего проанализированного на лог сайта в nginx где фигурируют WAN-IP тех кто задействует обращение к API и просто опираясь на свою заметку: "GEO блокировка через firewalld на Ubuntu 22.04"
создал source:wanblock и занес туда всех кто есть в параметре client: WAN-IP.
Ниже пример строки в логе:
2024/03/13 11:05:30 [error] 2163#2163: *2346 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 81.200.248.106, server: <VPS_SYSTEM>.site.ru, request: "GET /api/dealers/companies HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.3-fpm.sock:", host: "<VPS_SYSTEM>.site.ru", referrer: "https://<VPS_SYSTEM>.site.ru/account/"
т.е.
- f1 -> это 2024/03/13 11:05:30 [error] 2163#2163: *2346 recv() failed (104: Connection reset by peer) while reading response header from upstream
- f2 -> Это client: 81.200.248.106
- f3 -> это server: <VPS_SYSTEM>.site.ru
- f4 -> это request: «GET /api/dealers/companies HTTP/1.1»
- f5 -> это upstream: «fastcgi://unix:/run/php/php7.3-fpm.sock:»
- f6 -> это host: «<VPS_SYSTEM>.site.ru»
Шаг №1:
Чтобы выделить IP
адреса из лога, я сперва экспортировал весь лог в файл для последующего с оставления регулярного выражения по его преображению к вижу с которым я смогу работать задействую заметку выше:
ekzorchik@<VPS_SYSTEM>:~$ sudo bash -c "cat /var/log/nginx/site.error.log > error.log"
Шаг №2:
Чтобы из error.log
файла получить WAN-IP
адреса:
ekzorchik@<VPS_SYSTEM>:~$ cat error.log | cut -d ',' -f2 | grep -v excess | tr -d ' client: ' | uniq | head -n 10 87.103.134.145 27.115.124.34 101.68.211.2 195.151.251.89 79.171.173.178 109.195.114.131 87.237.41.144 185.41.41.190 95.26.24.117 109.195.114.131 ekzorchik@<VPS_SYSTEM>:~$
где
- grep -v excess — исключить строки содержащие excess
- tr -d ‘ client ‘ — удалить из строки «<пробел>client<пробел»
- uniq — отсортировать
- head -n 10 — > отобразить первые 10 строк
Шаг №3:
С учетом проработки выше, просто без какого-либо сохранения отдельно приступил к обработке лога вот прям здесь и сейчас:
ekzorchik@<VPS_SYSTEM>:~$ sudo bash -c "cat /var/log/nginx/site.error.log | cut -d ',' -f2 | grep -v excess | tr -d ' client: ' | uniq | head -n 10" 87.103.134.145 27.115.124.34 101.68.211.2 195.151.251.89 79.171.173.178 109.195.114.131 87.237.41.144 185.41.41.190 95.26.24.117 109.195.114.131 ekzorchik@<VPS_SYSTEM>:~$
и вывод копируем в wanblock.zone
sudo bash -c "cat /var/log/nginx/site.error.log | cut -d ',' -f2 | grep -v excess | tr -d ' client: ' | uniq | head -n 10" > wanblock.zone sudo firewall-cmd --zone=drop --ipset=wanblock.zone --add-entries-from-file=/home/ekzorchik/wanblock.zone --permanent sudo firewall-cmd --permanent --zone=drop --add-source="ipset:wanblock.zone" sudo firewall-cmd --reload
Шаг №4:
Если нужно удалить IP
адрес из списка wanblock.zone:
sudo bash -c "cat /etc/firewalld/ipsets/wanblock.zone.xml" | grep 101.68.211.2 <entry>101.68.211.2</entry> ekzorchik@<VPS_SYSTEM>:~$ sudo nano /etc/firewalld/ipsets/wanblock.zone.xml
находим через поиск строку <entry>101.68.211.2</entry>
, удаляем, сохраняем внесенные изменения
и перезапускаем:
sudo firewall-cmd --reload
Итого: после, когда помогли дилерам с правильной настройкой к API
уже по отдельности удаляли WAN-IP
дилеров из blocklist(а)
с наказом, если такое повторится, то не обессуте снова заблокируем. В очередной раз разобранное для себя с применением firewalld + ipset
выручило. В дополнении к этому я прикрутил fail2ban и уже все делается в автоматическом режиме.
На этом пока все, с уважением автор блога Олло Александр aka ekzorchik.