ServerAdmin.ru
27.1K subscribers
189 photos
27 videos
8 files
2.49K links
Авторская информация о системном администрировании.

Информация о рекламе: @srv_admin_reklama_bot
Автор: @zeroxzed

Второй канал: @srv_admin_live
Сайт: serveradmin.ru
Download Telegram
​​Ещё один способ организовать мониторинг Nginx - использовать prometheus-nginxlog-exporter. Принцип его действия следующий. В режиме реального времени анализируется лог Nginx. Распознанные метрики из него передаются в Prometheus.

Основная сложность этого способа - настроить соответствие лога nginx и шаблона экспортера. Я сказал "сложность" условно. Просто это единственное, что нужно учесть при настройке, остальное делается на автомате по инструкции. Реально никакой проблемы нет. Формат шаблона у nginxlog-exporter очень простой. Подогнать его под свой лог не проблема. Это не настройка grok фильтра, как у Logstash. Там придётся повозиться, прежде чем получится рабочий вариант.

В целом, использовать Nginxlog-exporter очень просто. Запустить можно сразу в Docker или установить из deb или rpm пакета. В качестве параметров запуска достаточно указать путь к конфигу службы и к логу Nginx. В репозитории есть все примеры.

Дальше всё как обычно. Метрики уходят в Prometheus, далее визуализация с помощью Grafana. В публичном доступе есть один актуальный дашборд, написанный конкретно под prometheus-nginxlog-exporter.

Исходники - https://github.com/martin-helmich/prometheus-nginxlog-exporter

#nginx #webserver
При настройке любой службы в Linux, которая пишет логи, надо обязательно следить за их ротацией. Типовая ситуация, когда логи забивают всё свободное место на диске, и сервак встаёт колом. Ротировать логи можно встроенной утилитой Linux - logrotate.

Для логов веб сайтов полезно включать ротацию не по заданному расписанию, а по размеру лог файла. Иногда случаются набеги ботов, которые могут раздуть логи до огромных размеров за несколько минут. Дождаться суточной ротации можно и не успеть. В этом случае полезно использовать следующий параметр logrotate:
size = 100M

Обычно люди ставят его и ожидают, что теперь логи будут автоматически ротироваться при достижении ими размера в 100 мегабайт. Ага, сейчас. Ничего подобного не произойдёт. По умолчанию logrotate запускается раз в сутки, поэтому он при всём желании не сможет следить за размером файла и ротировать его чаще, чем раз в сутки. Обычно за его запуск отвечает скрипт в директории /etc/cron.daily/logrotate.

Для того, чтобы logrotate мог проверять размер лог файла хотя бы раз в час, скрипт запуска надо перенести в директорию /etc/cron.hourly. А для более частой проверки, добавить его напрямую в cron с нужным интервалом запуска. Например, раз в 5 минут.

Допустим вы всё это сделали, но логи всё равно не будут ротироваться при достижении заданного размера. Понять, в чем же теперь проблема, не так просто. При запуске logrotate вы не увидите никаких ошибок. Он просто ничего не будет делать. Понять, в чём проблема, можно только при запуске в режиме отладки. Там вы увидите ошибку, если в этот день ротация уже была хотя бы раз.
destination /var/log/nginx/access.log.20220426.gz already exists, skipping rotation

Смысл тут в том, что logrotate сегодня уже произвел ротацию и создал архив лога с определенным именем и второй раз такой же файл он сделать не может. А маска имени файла при создании настроена в формате %Y%m%d. За эту маску отвечает параметр в /etc/logrotate.conf:
dateext

Самый простой вариант - это просто закомментировать этот параметр, тогда все архивы логов будут иметь следующую маску в файлах:
access.log.1.gz
access.log.2.gz
access.log.3.gz

Если же вам хочется сохранить исходный формат лога для всех файлов, а для тех, что ротируются по размеру, настроить другую маску имени, используйте дополнительный параметр:
dateformat -%Y-%m-%d_%H-%s

Формат имени архивного лога будет access.log.2022-04-26_15-1566819154.gz. Имена больше не будут дублироваться и logrotate сможет корректно запускать ротацию при достижении указанного размера файла.

Таким образом, чтобы настроить ротацию лог файла по достижении определенного размера, вам нужно:

1️⃣ Запускать через cron logrotate с достаточно высокой периодичностью, например раз в час или чаще.
2️⃣ Настроить маску файла для архива лога, чтобы она была уникальной в каждый момент запуска logrotate.

#logrotate #nginx #webserver
Предлагаю вашему вниманию некоторые изменения стандартного конфига Nginx, которые я лично выполняю. К каждому параметру сделаю небольшое пояснение.

worker_connections 8192;
Количество соединений для одного рабочего процесса. Повышать следует в зависимости от производительности сервера, но дефолтные значения я в любом случае увеличиваю.

worker_rlimit_nofile 65536;
Параметр указывает, сколько файловых дескрипторов будет использовать Nginx. На каждое соединение надо выделять по два дескриптора: один на соединение с клиентом, второй на открытие файла. Число соединений = worker_connections * worker_processes.

pcre_jit on;
Использование PCRE JIT способно существенно ускорить обработку регулярных выражений.

multi_accept on;
Позволяет рабочему процессу сразу принять все новые соединения. Иначе он их будет принимать по одному.

sendfile on; 
Параметр активирует передачу данных между файловыми дескрипторами средствами ядра ОС. Это ускоряет процесс и экономит ресурсы.

tcp_nopush on;
tcp_nodelay on;
Параметры ускоряют передачу данных HTTP запросов.

reset_timedout_connection on;
Параметр разрешает сброс соединений по таймауту.

server_tokens off;
Отключите server_tokens, чтобы nginx не показывал свою версию.

ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
Отключите старые версии ssl, а можно и tls1, tls1.1. Сейчас по умолчанию поддерживаются версии tls 1.2 и 1.3. Остальные считаются устаревшими.

log_format
Я обычно добавляю дополнительные поля в стандартный формат логов. Как минимум rt=$request_time и ut=$upstream_response_time. Это позволяет мониторить время ответа бэкендов. Отклонение от стандартных логов приводит к тому, что их перестают парсить стандартные шаблоны различного софта. Так что изменяйте на свой страх и риск. Я это делаю там, где потом и шаблоны редактирую сам.

client_max_body_size 10m;
Задаёт максимально допустимый размер тела запроса клиента. Дефолтное значение в 1m часто недостаточно.

Также я в обязательном порядке меняю дефолтные таймауты, типа proxy_connect_timeout, send_timeout, client_body_timeout и т.д. Но это уже делается под конкретные сайты и ситуации, поэтому не привожу примеры этих значений. В общем случае можно оставить дефолт, а потом изменять по мере необходимости.

📌 В завершении несколько полезных ссылок на мои материалы по теме Nginx:
- Подробная установка и настройка Nginx с примерами
- Автоматическое тестирование конфигурации Nginx
- Правильный redirect 301 для SEO в Nginx
- Nginx в качестве балансировщика нагрузки
- Проксирование запросов в nginx с помощью proxy_pass
- Сборка rpm пакета nginx с дополнительными модулями

 📌 Другие полезные ссылки:
- Генерация конфигов Nginx от DigitalOcen
- SSL Configuration Generator
- Проверка конфигурации Nginx

Пост достоин того, чтобы отправиться в закладки.

#nginx
​​🛡 Хочу поделиться с вами продуктом на базе Nginx, который мне понравился своей простотой и удобством. Речь пойдёт про Bunkerweb, который реализует в том числе функционал WAF (Web Application Firewall). Это собранный Docker контейнер с Nginx внутри и кучей дополнительного функционала для обеспечения безопасности.

Bunkerweb может работать как непосредственно локальный веб сервер, так и в режиме reverse proxy. Большая часть функционала реализована штатными средствами Nginx и модулями к нему. В качестве WAF используется ModSecurity, для защиты от ботов интеграция с различными каптчами.

📌 Для настройки есть мастер создания конфигурации. Оценить функционал и основные возможности проще всего через него, а не через просмотр описания или доков. Там сразу понятно, что он умеет и как настраивается. Перечислю основные фишки:
есть встроенный веб интерфейс для управления (видео с демонстрацией)
поддержка плагинов (уже есть интеграции с CrowdSec, ClamAV, Discord, Slack, VirusTotal)
WAF на базе ModSecurity и набора правил OWASP
распознавание ботов, их блокировка или показ каптчи
блок ip по странам или внешним списками
поддержка сертификатов let's encrypt

Весь функционал подробно описан в документации. Запускается Bunkerweb в Docker, Kubernetes, локально с ручной установкой или через Ansible. Доступны, по сути, все возможные способы, кому что ближе и удобнее.

Проект оставил очень хорошее впечатление. Он хорошо документирован, описан, понятно сделан, продуман. Мне показалось, что это хорошее решение не только с точки зрения безопасности, но и просто установки и управления Nginx. Можно через конструктор собрать набор опций, запустить Bunkerweb, а потом посмотреть в конфиге, как всё это реализовано. Так как всё собрано на базе open source продуктов, разобраться не трудно. При желании, можно что-то в свои наработки утащить.

Можно рассматривать этот продукт как панель управления для Nginx с базовым набором правил безопасности. Это если его просто с дефолтными настройками запустить. А дальше уже при желании можно наращивать функционал.

Сайт - https://docs.bunkerweb.io
Исходники - https://github.com/bunkerity/bunkerweb
Demo - https://demo.bunkerweb.io/

#waf #security #nginx
​​Недавно попал в любопытную панель управления веб серверами. Интерфейс явно напоминал о том, что где-то я его уже видел. Довольно быстро через поиск понял, в чём тут дело. Уже давно я писал про веб панель для управления haproxy - haproxy-wi. Проект с тех пор активно развивается, сменил имя, нарастил функционал и обзавёлся платной версией.

Теперь он называется Roxy-WI. У него, судя по всему, русскоязычные разработчики. Как минимум от двоих есть целая серия статей на хабре про этот продукт (тут и тут). К сожалению, с появлением платной версии, исчезли готовые пакеты для автоматической установки. Это не является какой-то большой проблемой, потому что по своей сути это обычное веб приложение, написанное на Python. Работает на базе Apache. В репозитории есть все конфиги, так что их просто нужно будет вручную разложить по нужным местам и самому установить зависимости. Подробная инструкция прилагается.

Roxy-WI умеет управлять настройками HAProxy, Apache, Nginx, Keepalived, Grafana, Prometheus, а так же HAProxy и Nginx exporters от него. Это такое комплексное решение по установке (указанные программы он умеет устанавливать самостоятельно, подключаясь по SSH) и управлению веб или прокси серверами.

Помимо непосредственно настройки, в Roxy-WI можно просматривать логи, настраивать WAF (Web Application Firewall), следить за сервисами с помощью мониторинга и оповещений. Есть интеграция с Fail2Ban.

Продукт функциональный и интересный. Если у вас задача поднять прокси сервер под HAProxy и для вас это не профильное направление, то можете воспользоваться панелью. Там есть в том числе и генератор конфигов под разные задачи.

Посмотреть, как всё это выглядит на практике, можно в ютубе на канале продукта:
https://www.youtube.com/@roxy-wi2201/videos
Там много примеров того или иного функционала. Или воспользоваться публичным демо:
https://demo.roxy-wi.org
Учётка - admin / admin. Панелька реально приятно и удобно смотрится. Оцените, как выглядит просмотр логов или редактор конфигов.

Сам я не сторонник готовых панелей. Никогда их не использую, если обслуживаю инфраструктуру сам. Но люди пользуются. Постоянно их встречаю. Например, самому собрать весь этот функционал, что есть в панели, надо постараться. А если нет опыта, так вообще употеть. А тут всё в одном месте и сразу с нормальным мониторингом.

Сайт / Исходники

#webserver #nginx #haproxy
​​На днях писал про CIS. Решил не откладывать задачу и проработать документ с рекомендациями по Nginx. Делюсь с вами краткой выжимкой. Я буду брать более ли менее актуальные рекомендации для среднетиповых веб серверов. Например, отключать все лишние модули и делать свою сборку в обход готовых пакетов я не вижу для себя смыла.

📌Проверяем наличие настройки autoindex. В большинстве случаев она не нужна. С её помощью работает автоматический обзор содержимого директорий, если в них напрямую зайти, минуя конкретный или индексный файл.
# egrep -i '^\s*autoindex\s+' /etc/nginx/nginx.conf 
# egrep -i '^\s*autoindex\s+' /etc/nginx/conf.d/*
# egrep -i '^\s*autoindex\s+' /etc/nginx/sites-available/*
Не должно быть настройки autoindex on. Если увидите, отключите.

📌Обращения на несуществующие домены или по ip адресу лучше сразу отклонять. По умолчанию отдаётся приветственная страница. Проверить можно так:
# curl -k -v https://127.0.0.1 -H 'Host: invalid.host.com'
Если в ответ показывает приветственную страницу или что-то отличное от 404, то надо добавить в самую первую секцию server следующие настройки:
server { 
return 404;
}
Можно просто удалить конфиг с дефолтным хостом, а приведённый код добавить в основной nginx.conf. Тогда это точно будет первая секция server. В остальных секциях server везде должны быть явно указаны server_name.

📌Параметр keep-alive timeout имеет смысл сделать 10 секунд или меньше. По умолчанию он не указан и им управляет подключающийся.
keepalive_timeout 10;
То же самое имеет смысл сделать для send_timeout.
send_timeout 10;

Скрываем версию сервера параметром server_tokens. Проверяем так:
# curl -I 127.0.0.1 | grep -i server
Отключаем:
server {
...
server_tokens    off;
... 
}

📌Дефолтные страницы index.html и error page лучше отредактировать, удалив всё лишнее. Обычно они хранятся в директориях /usr/share/nginx/html или /var/www/html.

📌Запрещаем доступ к скрытым файлам и директориям, начинающимся с точки. Для этого в добавляем в самое начало виртуального хоста location:
location ~ /\. { deny all; return 404; }
Если нужно исключение, например для директории .well-known, которую использует let's encrypt для выпуска сертификатов, то добавьте его выше предыдущего правила.
location ~ /\.well-known\/acme-challenge { allow all; }

📌Скрываем proxy headers. Добавляем в location:
location /docs {
....
proxy_hide_header X-Powered-By; 
proxy_hide_header Server;
.... 
}

📌Не забываем про настройку логирования. Логи нужны, но настройка сильно индивидуальна. Если логи хранятся локально, то обязательно настроить ротацию не только с привязкой ко времени, но и к занимаемому объёму. В идеале, логи должны храниться где-то удалённо без доступа к ним с веб сервера.

📌Настраиваем передачу реального IP адреса клиента в режиме работы Nginx в качестве прокси.
server {
...
location / {
proxy_pass 127.0.0.1:8080);
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
}
}

📌Ограничиваем версию TLS только актуальными 1.2 и 1.3. Если используется режим проксирования, то надо убедиться, что эти версии совпадают на прокси и на сервере. Если не уверены, что все ваши клиенты используют современные версии TLS, то оставьте поддержку более старых, но это не рекомендуется. Настройка для секции http в nginx.conf
ssl_protocols TLSv1.2 TLSv1.3;

📌Настраиваем ssl_ciphers. Список нужно уточнять, вот пример из документа CIS:
ssl_ciphers ALL:!EXP:!NULL:!ADH:!LOW:!SSLv2:!SSLv3:!MD5:!RC4;

Дальше идут более узкие рекомендации типа ограничения доступа по IP, отдельных методов, настройка лимитов, более тонкие настройки таймаутов и т.д. В общем случае это не всегда требует настройки.

Ничего особо нового в документе не увидел. Большую часть представленных настроек я и раньше всегда делал. В дополнение к этому материалу будет актуальна ссылка на предыдущую заметку по настройке Nginx. Надо будет всё свести в общий типовой конфиг для Nginx и опубликовать.

#cis #nginx #security
​​Обработал несколько материалов на тему Nginx и подготовил универсальный конфиг с общими параметрами и некоторыми примерами настроек для виртуального хоста. Перед применением конфиг обязательно правится под ваш сервер. Нужно сделать некоторые подготовительные действия, чтобы на нём завестись. Как минимум, получить сертификаты, создать нужные директории, сгенерировать dhparam.pem, какие-то пути подправить и т.д.

https://pastebin.com/dHscS0Vi

Это компиляция из моих же настроек в постах про Nginx (1, 2). Настройки TLS частично подсмотрел в генераторе от Mozilla:
https://ssl-config.mozilla.org/

Также кое что посмотрел в генераторе конфигов от Digital Ocean:
https://www.digitalocean.com/community/tools/nginx

Проверил всё это дело на nginx playground:
https://nginx-playground.wizardzines.com

А также с помощью анализатора конфигов Nginx от Яндекса gixy:
https://github.com/yandex/gixy

Настройки TLS проверил тут:
https://www.ssllabs.com/ssltest

Параметры моего конфига поддерживают работу TLS 1.0 и 1.1. За это дают большой штраф. Можете отключить эти протоколы и соответствующие шифры, но тогда, к примеру, отвалятся все старые андроиды версии 4 и ниже. Смотрите сами, нужна ли вам поддержка максимального числа оборудования, или важнее соответствие современным протоколам безопасности.

Конфиг получился не сферическим конём в вакууме, а рабочим вариантом. Я сам постоянно его использую, поэтому обновил свой рабочий шаблон, которым сам буду пользоваться.

📌 В завершении несколько полезных ссылок на мои материалы по теме Nginx:
Подробная установка и настройка Nginx с примерами
Автоматическое тестирование конфигурации Nginx
Правильный redirect 301 для SEO в Nginx
Nginx в качестве балансировщика нагрузки
Проксирование запросов в nginx с помощью proxy_pass
Сборка rpm пакета nginx с дополнительными модулями

#nginx #webserver
Ещё один пример защиты веб сервера с помощью fail2ban. На этот раз пример будет более универсальный, который защитит не только от брута, но и от любых множественных подключений к серверу.

Для этого нам понадобятся модули nginx limit_req и limit_conn. С их помощью можно ограничить скорость обработки запросов с одного IP адреса. Для этого в основной конфигурации nginx, в разделе http, нужно добавить одну или несколько зон с максимальной скоростью обработки запросов или количеством числа соединений с одного IP. Я обычно использую несколько зон, чаще всего четыре. Одна для общего ограничения соединений, вторая для статики, третья для легких динамических запросов (обычные php страницы), четвёртая для тяжёлых динамических запросов (аутентификация, поиск, формирование большого каталога и т.д.).

Выглядят настройки примерно так:

limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_req_zone $binary_remote_addr zone=lim_50r:10m rate=50r/s;
limit_req_zone $binary_remote_addr zone=lim_10r:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=lim_3r:10m rate=3r/s;

Зону лучше называть по разрешённому лимиту, чтобы проще было использовать в настройках. Далее идём в конфиг виртуального хоста и там расставляем зоны в общей настройке server и разных locations. Примерно так:

server {
...
limit_conn perip 100;
...

# поиск
location /?s= {
limit_req zone=lim_3r burst=5 nodelay;
...
}

# динамика
location ~ \.php$ {
limit_req zone=lim_10r burst=15 nodelay;
...
}

# всё остальное
location / {
limit_req zone=lim_50r burst=65 nodelay;
...
}
}

Здесь главное без фанатизма использовать лимиты, особенно на общие страницы и статику, чтобы не блокировать поисковые системы или какие-то другие полезные боты. После настройки некоторое время понаблюдайте за ограничениями.

Сработанные ограничения будут отображаться в error.log nginx. Его мы и будем проверять с помощью fail2ban. Для этого добавляем в директорию /etc/fail2ban/filter.d два конфига.

nginx-limit-conn.conf:
[Definition]
failregex = ^\s*\[[a-z]+\] \d+#\d+: \*\d+ limiting connections by zone.*client: <HOST>
ignoreregex =

nginx-limit-req.conf:
[Definition]
ngx_limit_req_zones = [^"]+
failregex = ^\s*\[[a-z]+\] \d+#\d+: \*\d+ limiting requests, excess: [\d\.]+ by zone "(?:%(ngx_limit_req_zones)s)", client: <HOST>,
ignoreregex = 
datepattern = {^LN-BEG}

И в /etc/fail2ban/jail.d два файла конфигурации:

nginx-limit-conn.conf
[nginx-limit-conn]
enabled = true
filter = nginx-limit-conn
port = http
action = iptables-multiport[name=ConnLimit, port="http,https", protocol=tcp]
logpath = /web/sites/*/logs/error.log
bantime = 3600
maxretry = 20

nginx-limit-req.conf
[nginx-limit-req]
enabled = true
filter = nginx-limit-req
action = iptables-multiport[name=ReqLimit, port="http,https", protocol=tcp]
logpath = /web/sites/*/logs/error.log
bantime = 3600
maxretry = 10

Теперь нарушители лимитов будут отправляться в бан. При этом не так критично разрастание логов, так как error лог редко растёт быстро, даже если вас ддосят. Но всё равно не нужно забывать про его ротацию.

Все лимиты и реакции настраивайте в зависимости от вашей ситуации. Не надо брать мои значения из примера. Они сильно зависят от типа сайта и производительности сервера. Главное, как я уже сказал, без фанатизма. Лимиты должны быть комфортными для легитимных пользователей и систем.

Есть более простой в плане нагрузки способ блокировать тех, кто открывает слишком много соединений. Использовать системную информацию о подключениях, например, с помощью netstat и если превышен лимит, отправлять IP в бан. Я не очень люблю этот способ и редко использую, так как нет гибкой настройки по сайтам, урлам и т.д. Его стоит использовать, если вас ддосят и вам надо максимально быстро и дёшево по ресурсам блокировать атакующих. Иногда это помогает, если ддос не очень сильный и провайдер вас не отключает. Если интересно посмотреть эту реализацию, то напишите в комментах, я расскажу с примером.

#security #fail2ban #webserver #nginx
​​На днях в комментариях подсказали полезный ресурс для проверки настроек безопасности в заголовках веб сервера — securityheaders.com. Для теста проверил свой сайт, получилась неутешительная картинка. Многие полезные с точки зрения безопасности заголовки не настроены. Стал разбираться.

Ключевым заголовком в плане обеспечения безопасности является CSP (Content Security Policy). С его помощью можно указать, с каких доменов может загружаться контент при просмотре сайта. Значение этого заголовка передаётся браузеру. Если он видит, что какие-то скрипты или прочие объекты пытаются загрузится с домена, который не разрешён в CSP, то блокирует их. Подобная защита, к примеру, помогает от XSS (cross site scripting) атак.

На деле оказалось, что конкретно мне настроить CSP будет очень непросто. Сначала бодро взялся за написание правил, потом приуныл. У меня крутится реклама от Яндекса, счётчики от Яндекс Метрики и Google Analytics. Чтобы все их корректно разрешить, надо прилично заморочиться, чтобы ничего не упустить. Вот пример настроек для метрики и рекламной сети. Ошибку можно сразу не заметить, а это приведёт к некорректному сбору статистики или ошибок в ней. А у кого-то ещё и шрифты внешние грузятся, библиотеки. Надо всё аккуратно проверять и настраивать.

Пока отложил вопрос. Конкретно для моего блога это некритично, но если у вас коммерческий сайт, то рекомендую заморочить и всё аккуратно настроить. По остальным заголовкам в сервисе есть описание, можно настроить. Но они уже не так важны и настраиваются проще.

У меня в итоге получилось вот так:

add_header X-Frame-Options "SAMEORIGIN";
add_header Strict-Transport-Security max-age=15768000;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "origin-when-cross-origin";
add_header Permissions-Policy "geolocation=(),midi=(),sync-xhr=(),\
microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=*,payment=()";

#nginx #webserver
​​▶️ В интернете масса статей и видео по настройке одного из самых популярных веб серверов Nginx. Разработчики в какой-то момент озаботились тем, чтобы самим выпустить канонические руководства, по которым стоит настраивать их веб сервер. Эти руководства они поддерживают и по мере необходимости обновляют.

Если вы отдаёте предпочтение информации от вендора, то для поиска инструкций разумнее обратиться на его официальный канал. К тому же все основные темы они вынесли в отдельный плейлист:

https://youtube.com/playlist?list=PLGz_X9w9raXf748bzuGOV6XJv7q3wLxhZ

🎓 Список тем из него:

How to define and publish APIs using NGINX Controller
How to Set Quotas with NGINX Plus
How to Set Up SSL with NGINX
How to Serve Static Content
How to Install NGINX on Debian and Ubuntu
How to create an API Dev Portal using NGINX Controller
Key Files, Commands, and Directories with NGINX
How to Install NGINX on CentOS and Red Hat
How to Install NGINX Amplify on Linux
NGINX Unit: From Zero to Lift Off
Dynamic SSL Key Management with NGINX
Getting Started with NGINX Service Mesh
NGINX as an API Gateway
How to Configure NGINX Plus as a WAF Using NGINX App Protect
NGINX App Protect Denial of Service (DoS) Overview
Configure NGINX as a Reverse Proxy
How to Streamline API Operations with API Connectivity Manager

Все видео на английском. Если не знаете его, можно спокойно всё понять через переводчик в режиме реального времени от Яндекса, или с английскими субтитрами. Часть тем актуальна для только версии Plus.

#nginx #видео #обучение
​​Веб сервер Nginx уже давно умеет писать логи в json формате. В настройке по умолчанию используются текстовые логи. Да и почти везде, где мне приходится видеть логи веб сервера, они в текстовом формате. Если ещё не используете json формат для логов, то предлагаю вам пересмотреть свои привычки и использовать. Это удобно и для ручного просмотра логов, и для парсинга в тех или иных системах.

Настроить json логи очень просто. Вот пример для привычного формата combined, только в json. Добавляем в основной конфиг в раздел http { }.

log_format json_combined escape=json
 '{'
  '"time_local":"$time_local",'
  '"remote_addr":"$remote_addr",'
  '"remote_user":"$remote_user",'
  '"request":"$request",'
  '"status": "$status",'
  '"body_bytes_sent":"$body_bytes_sent",'
  '"request_time":"$request_time",'
  '"http_referrer":"$http_referer",'
  '"http_user_agent":"$http_user_agent"'
 '}';

И дальше либо в общую настройку, либо в настройку логов виртуального хоста добавляем:

access_log /var/log/nginx/access.log json_combined;

Теперь, если отправить логи в ELK или Zabbix, их обработка будет упрощена, так как для json формата там есть готовые обработчики. А в консоли логи удобно смотреть с помощью jq. Смотрим весь лог:

# jq '.' access.log

Смотрим только список урлов, к которым были обращения:

# jq '.request' access.log

Выводим полные записи логов, где только 404 коды ответов:

# jq '. | select(.status=="404")' access.log

Теперь то же самое, только выводим не полные строки, а урл, где код ответа был 404:

# jq '. | select(.status=="404") | .request' access.log

Добавим сюда же информацию о времени запроса:

# jq '. | select(.status=="404") | .time_local,.request' access.log

Думаю, идею вы поняли. Json смотреть проще, быстрее и гибче, нежели грепать или обрабатывать утилитами типа sed, awk и т.д. Надо только немного изучить синтаксис jq. Если хотите получить значения без кавычек " ", то добавьте к jq ключ -r:

# jq -r '.request' access.log

Все переменные, которые вы можете использовать в логе, перечислены в документации к модулю ngx_http_core_module. Я обычно добавляю некоторые переменные к стандартным, а именно:

$request_length, $upstream_addr,
$upstream_status,
$upstream_response_time,
$upstream_connect_time,
$upstream_header_time,
$server_name,
$ssl_protocol,
$ssl_cipher.

#nginx #jq
​​Более двух лет назад я вам уже рассказывал про Nginx Proxy Manager. Это веб панель для управления Nginx в режиме proxy_pass. С той заметки прошло много времени, а панелька эта очень активно развивается. Недавно в одном из видео я увидел эту панель в работе. Автор её очень сильно нахваливал.

Посмотрел на неё ещё раз. Она с тех пор заматерела. Изменила адрес репозитория, собрала много звёзд на гитхабе (14,1k, было ~2k). Получила красивую документацию. При этом не обросла лишним функционалом, не стала платной. Автору явно нравится его детище. Постоянно видны исправления, выход новых версий.

Живёт всё в одном контейнере, если ваc устраивает хранить состояние панели в базе SQLite. В противном случае можете настроить хранение в MySQL. В документации автор предлагает docker-compose файл для запуска, но так как контейнер всего один, проще запустить напрямую через docker:

# docker run -d --restart unless-stopped \
-p 80:80 -p 81:81 -p 443:443 \
-v ./data:/data -v ./letsencrypt:/etc/letsencrypt \
jc21/nginx-proxy-manager:latest

Далее идёте на 81-й порт своего сервера и логинитесь под учёткой admin@example.com / changeme. Не забудьте сразу поменять, если он смотрит в интернет. Вся конфигурация и сертификаты будут храниться в созданных директориях, так что их удобно бэкапить.

Это хобби-проект одного разработчика, так что в прод такое ставить не стоит. А себе домой или для тестов вполне сойдёт. Приятный продукт с красивым веб интерфейсом, который решает одну конкретную задачу. И делает это хорошо. Рекомендую, если вам нужна подобная функциональность.

Сайт / Исходники / Обзор / NPM vs Traefik

#nginx #webserver
​​Веб сервер Nginx поддерживает интеграцию с языком программирования Lua. Реализуется это с помощью специального модуля для Nginx. В стандартных пакетах с nginx чаще всего нет этого модуля. В Debian и Ubuntu его можно поставить с помощью пакета nginx-extras:
# apt install nginx-extras

Также существует веб сервер на основе Nginx и Lua — OpenResty . Он полностью совместим с Nginx и следует за его релизами. Отличает его только наличие дополнительных модулей для работы с Lua.

Чаще всего в Nginx Lua используют для борьбы с ddos атаками. Вот навороченный пример готового скрипта на lua для этого — Nginx-Lua-Anti-DDoS. Я его попробовал, работает нормально. И очень удобно. У него куча возможностей по блокировке тех или иных клиентов. С базовыми настройками он блокирует некоторых ботов, подсети некоторых хостеров и осуществляет защиту от ботов с помощью страницы заглушки на javascript (пример на картинке), которая добавляет зашифрованную куку. Потом редиректит на основную страницу и проверяет эту куку.

Не буду расписывать установку и настройку этого скрипта. Всё необходимое есть в репозитории. Я немного повозился, но всё настроил. Если вас донимают какие-то боты, попробуйте, должно помочь. Скрипт позволяет в одном месте работать со всеми ограничениями и настройками, что удобно. Если не нужен, можно очень быстро его отключить. Все настройки прокомментированы в самом скрипте.

По теме nginx и lua очень много всего гуглится, если искать по словам nginx lua antiddos. Вот ещё пару примеров:
⇨ LUA в nginx: слегка интеллектуальный firewall
⇨ Защита от DDoS на уровне веб-сервера

Кстати, CloudFlare как раз и осуществляет свою защиту на базе Lua с помощью веб сервера OpenResty. Или осуществлял. Сейчас может уже на что-то другое перешли. Так что если работаете с веб серверами и не используете Lua, обратите на него внимание. Очень многие вещи с его помощью делать удобно.

#nginx #webserver
​​Некоторое время назад я рассказывал про программу Vector, с помощью которой удобно управлять потоками данных. Сейчас покажу, как с её помощью отправить логи Nginx в сервис axiom.co, где бесплатно можно хранить и обрабатывать до 500 ГБ в месяц. Это отличная возможность быстро собрать дашборд для анализа логов веб сервера.

Сначала зарегистрируйтесь в axiom.co. Там не нужны ни кредитки, ни какая-то ещё информация, кроме email. Сразу получите аккаунт с очень солидными бесплатными лимитами. Там же создайте новый Dataset и к нему API ключ. Это условный аналог облака Elastic на минималках. Я собственно, про него и хотел рассказать, но решил сразу на конкретном примере. К тому же у вектора не очень очевидная документация, особенно в плане преобразований. В своё время долго разбирался, как там парсинг json и grok фильтры правильно настраивать и описывать в конфигах.

Установите Vector любым удобным способом из документации. Настройте логи Nginx в формате json. Это можно не делать, но тогда понадобится grok фильтр для обработки access лога, что дольше и сложнее, чем использование сразу json. Рисуем конфиг для Vector.

[sources.nginx_access_logs]
type     = "file"
include   = ["/var/log/nginx/access.log"]

[transforms.nginx_access_logs_parsed]
type = "remap"
inputs = ["nginx_access_logs"]
source = '''
. = parse_json!(.message)
'''

[sinks.axiom]
inputs = ["nginx_access_logs_parsed"]
type = "axiom"
token = "xaat-36c1ff8f-447f-454e-99fd-abe804aeebf3"
dataset = "webserver"

У Vector есть готовая интеграция с axiom, что я и указал в sinks. Теперь запускайте Vector и идите в axiom.co. На вкладке Streams увидите свои логи в режиме реального времени.

Теперь можно зайти в Dashboards и собрать любой дашборд на основе данных лога Nginx. Чем более насыщенный лог, что настраивается в конфиге Nginx, тем больше данных для визуализации. Я для тестового сервера собрал дашборд буквально за 10 минут. Смотрите во вложении к заметке.

Такая вот заметка-инструкция получилась. Vector я уже рекомендовал, теперь советую посмотреть на описанный сервис. Меня никто не просил его рекламировать. Он просто удобный и есть функциональный бесплатный тарифный план. В него включены также 3 оповещения. Например, можно настроить, что если у вас в минуту будет больше 10 500-х ошибок сервера, прилетит оповещение. Или что-то ещё. Там большие возможности для насыщения, аггегации и других манипуляций с данными. Разобраться проще, чем в ELK или OpenSearch.

Для любителей grok, как я, покажу пример transforms в Vector своего формата логов Nginx. Вот пример формата лога, который я обычно использую, где есть всё, что мне надо:

  log_format full   '$remote_addr - $host [$time_local] "$request" '
        'request_length=$request_length '
        'status=$status bytes_sent=$bytes_sent '
        'body_bytes_sent=$body_bytes_sent '
        'referer=$http_referer '
        'user_agent="$http_user_agent" '
        'upstream_status=$upstream_status '
        'request_time=$request_time '
        'upstream_response_time=$upstream_response_time '
        'upstream_connect_time=$upstream_connect_time '
        'upstream_header_time=$upstream_header_time';

Вот grok фильтр в Vector:

[transforms.nginx_access_logs_parsed]
type = "remap"
inputs = ["nginx_access_logs"]
source = '''
. = parse_grok!(.message, "%{IPORHOST:remote_ip} - %{DATA:virt_host} \\[%{HTTPDATE:access_time}\\] \"%{WORD:http_method} %{DATA:url} HTTP/%{NUMBER:http_version}\" request_length=%{INT:request_length} status=%{INT:status} bytes_sent=%{INT:bytes_sent} body_bytes_sent=%{NUMBER:body_bytes_sent} referer=%{DATA:referer} user_agent=\"%{DATA:user_agent}\" upstream_status=%{DATA:upstream_status} request_time=%{NUMBER:request_time} upstream_response_time=%{DATA:upstream_response_time} upstream_connect_time=%{DATA:upstream_connect_time} upstream_header_time=%{DATA:upstream_header_time}")
'''

#nginx #logs #devops
​​Если вам нужно заблокировать какую-то страну, чтобы ограничить доступ к вашим сервисам, например, с помощью iptables или nginx, потребуется список IP адресов по странам.

Я сам всегда использую вот эти списки:
https://www.ipdeny.com/ipblocks
Конкретно в скриптах забираю их по урлам. Например, для России:
https://www.ipdeny.com/ipblocks/data/countries/ru.zone
Это удобно, потому что списки уже готовы к использованию — одна строка, одно значение. Можно удобно интегрировать в скрипты. Например, вот так:

#!/bin/bash

# Удаляем список, если он уже есть
ipset -X whitelist
# Создаем новый список
ipset -N whitelist nethash

# Скачиваем файлы тех стран, что нас интересуют и сразу объединяем в единый список
wget -O netwhite http://www.ipdeny.com/ipblocks/data/countries/{ru,ua,kz,by,uz,md,kg,de,am,az,ge,ee,tj,lv}.zone

echo -n "Загружаем белый список в IPSET..."
# Читаем список сетей и построчно добавляем в ipset
list=$(cat netwhite)
for ipnet in $list
 do
 ipset -A whitelist $ipnet
 done
echo "Завершено"
# Выгружаем созданный список в файл для проверки состава
ipset -L whitelist > w-export

Тут я создаю список IP адресов для ipset, а потом использую его в iptables:

iptables -A INPUT -i $WAN -m set --match-set whitenet src -p tcp --dport 80 -j ACCEPT

Если в списке адресов более 1-2 тысяч значений, использовать ipset обязательно. Iptables начнёт отжирать очень много памяти, если загружать огромные списки в него напрямую.

Есть ещё вот такой сервис:
https://www.ip2location.com/free/visitor-blocker
Там можно сразу конфиг получить для конкретного сервиса: Apache, Nginx, правил Iptables и других. Даже правила в формате Mikrotik есть.

Ссылки рекомендую в закладки забрать.

#iptables #nginx #security #script
​​На практике регулярно приходится собирать Nginx с дополнительными модулями. Чаще всего это модули brotli, vts или lua. У меня когда-то была статья для Centos по этой теме, но она уже неактуальна. Решил сделать мини-инструкцию по сборке своего пакета Nginx для Debian на примере добавления туда модуля статистки vts. А завтра отдельной публикацией покажу, как с его помощью очень быстро организовать мониторинг Nginx.

Выполнять сборку следует на отдельной машине, а не на рабочем сервере, чтобы не засорять его лишними пакетами. Я буду использовать небольшой читинг, а не полноценную сбоку пакета, которая не очень проста. Возьму готовые файлы настроек для упаковки в Debian 11 из официального репозитория Nginx. Распакую их, немного изменю настройки и запакую с ними свой пакет.

Устанавливаем необходимые зависимости, которые понадобятся для сборки Nginx и упаковки в deb пакет:
# apt install dpkg-dev devscripts quilte quivs wget dh-make build-essential \
git libpcre++-dev libssl-dev libgeoip-dev libxslt1-dev zlib1g-dev libpcre2-dev

Скачиваем файлы, которые нам понадобятся: исходники и настройки:
# mkdir build && cd build
# wget http://nginx.org/packages/debian/pool/nginx/n/nginx/nginx_1.24.0-1~bullseye.debian.tar.xz
# wget http://nginx.org/download/nginx-1.24.0.tar.gz

Распаковываем всё и удаляем архивы, чтобы не мешали:
# tar xvf nginx_1.24.0-1~bullseye.debian.tar.xz
# tar xzvf nginx-1.24.0.tar.gz
# rm -rf nginx_1.24.0-1~bullseye.debian.tar.xz nginx-1.24.0.tar.gz

Создаём директорию для модулей:
# mkdir debian/modules

Копируем туда исходники nginx-module-vts:
# cd debian/modules
# git clone https://github.com/vozlt/nginx-module-vts

Возвращаемся обратно в build и переносим директорию debian/ в папку с исходниками:
# cd ../../
# mv debian ./nginx-1.24.0
# cd nginx-1.24.0

Редактируем некоторые файлы. Начинаем с debian/changelog. Добавьте в начало по аналогии новую запись с описанием нового пакета. Примерно так:
nginx (1.24.0-1~bullseye) bullseye; urgency=low

 * 1.24.0-1
 * Add nginx-module-vts

 -- Serveradmin <root@serveradmin.ru> Fri, 18 Aug 2023 10:03:46 +0300

Важно следить за всеми отступами и пробелами. Если просто скопируете отсюда, то будут ошибки. Копируйте строки из исходного файла и меняйте их.

Далее вам может понадобиться файл debian/control, где можно добавить зависимости. В моём случае новых зависимостей не появится. А если вы, к примеру, захотите добавить модуль с lua, то там нужно будет пару пакетов в систему установить. Просто добавьте их в Build-Depends.

Открываем файл debian/rules и добавляем туда:
MODULESDIR = $(CURDIR)/debian/modules
Можете эту строку добавить сразу же после строки с BASEDIR. Далее ищем строки с ./configure и добавляем к ним в конец дополнительный параметр:
--add-module=$(MODULESDIR)/nginx-module-vts
Здесь же можете удалить лишние модули, которые вам точно не понадобятся.

Удаляем файл debian/source/format. Он не даст собрать пакет.
# rm -rf debian/source/format

Сохраняем файл и собираем архив с настройками пакета:
# dh_make --copyright gpl -s -e root@serveradmin.ru --createorig -y -p nginx_1.24.0
В директории build должен появиться файл nginx_1.24.0.orig.tar.xz.

Собираем пакет:
# dpkg-buildpackage -rfakeroot

В директории build должен появиться в том числе файл с пакетом nginx_1.24.0-1~bullseye_amd64.deb. Его можно установить и проверить:
# dpkg -i nginx_1.24.0-1~bullseye_amd64.deb

Проверяем, есть ли там наш модуль:
# nginx -V
В самом конце должно быть
--add-module=/root/build/nginx-1.24.0/debian/modules/nginx-module-vts

На этом всё. Таким образом можно собирать любые сборки Nginx под свои потребности и размещать их в своих репозиториях. Например, с помощью Nexus, aptly, apt-offline и т.д.

Заметка получилась полноценной инструкцией с информацией, которую я в интернете не нашёл в готовом виде. Пришлось написать самому.

#debian #nginx
​​Популярный вопрос к моим статьям и заметкам по настройке проксирования HTTP запросов с Nginx куда-то на backend. Нужно ли настраивать HTTPS и как вообще правильно это сделать. Поясню, о чём идёт речь.

Допустим, у вас есть какой-то сервер Nginx, работающий в режиме proxy_pass и раскидывающий соединения к разным доменам по разным серверам или контейнерам. Либо это один большой сайт с несколькими бэкендами. Очевидно, что соединение клиента с этим Nginx настроено по HTTPS. А от Nginx до остальных серверов нужно ли настраивать по HTTPS?

В общем случае я такие соединения пускаю по HTTP. Не вижу смысла использовать в этом случае шифрование, которое усложняет настройку, потому что надо сертификаты передавать на все сервера. Так оно ещё и ресурсы дополнительные тратит. На небольших нагрузках это не особо заметно, а вот на тысячах запросах в секунду будет заметно.

Исключение делаю тогда, когда проксируемое приложение или сервис начинают работать некорректно при такой схеме. Это бывает нередко. Приходится либо настройки сайта крутить, либо дополнительные заголовки добавлять, либо что-то ещё делать. Если простых способов решить проблемы нет, то приходится настраивать всю цепочку соединений по HTTPS.

Некоторые примеры подобных ошибок и их решения я публиковал на сайте (phpmyadmin, wordpress). Точно надо что-то делать с Bitrix, если проксируешь его по HTTP. Сейчас уже не помню, что именно. Не записывал. Каждый раз по месту разбираюсь.

А вы как считаете? Нужно ли в этом случае настраивать HTTPS, при условии, что запросы гуляют по нашей внутренней сети, которая считается доверенной? Если речь идёт про проксирование через сторонний сервис, тот же Cloudflare, или другую систему защиты от DDOS, то HTTPS я всегда настраиваю.

#nginx #webserver