Bash Days | Linux | DevOps
22.9K subscribers
114 photos
21 videos
555 links
Авторский канал от действующего девопса

Самобытно про разработку, devops, linux, скрипты, тестирование, сисадминство, техдирство, пиэмство и за айтишную жизу.

Автор: Роман Шубин
Реклама: @maxgrue

Курс: @tormozilla_bot

РКН: https://two.su/bashdays
Download Telegram
😀😃😄😁😆

🔧 Утилиты: #utils
💳 Таблицы: #sheets
Скрипты: #bash
🎙 Мониторинг: #monitoring
🤔 Отладка: #debug
🎃 Линукс: #linux
✉️ Nginx: #nginx
📦 GIT: #git
📊 Mysql: #mysql
📱 Сервисы: #services
🔄 Девопс: #devops
🛡 Безопасность: #security
👻 Игры: #games
🌐 Сети: #networks
💬 Будни: #рабочиебудни
Please open Telegram to view this post
VIEW IN TELEGRAM
Будем расширять границы контента. Ща покажу магию, знать это мастхэв. Мотай на ус, если не индус знал, пригодится.

У нас в компании достаточно банальная инфраструктура, в которую входит балансировщик и несколько нод на которых крутится nodejs приложение с 3000м портом, короче говоря апиха.

bashdays-b1:443
-> bashdays-w1:3000
-> bashdays-w2:3000
-> bashdays-w3:3000
-> bashdays-w4:3000

К примеру от клиентов идут POST запросы к апихе, запросы попадают на сервер b1, затем nginx распределяет запросы по нодам w1-w4 и отдает в ответ json. Примитивная балансировка нагрузки, но достаточно стабильная.

В какой-то момент мне необходимо добавить еще одну ноду с новой версией nodejs приложения.

Назовем её bashdays-w5. Эта нода не должна обслуживать клиентов, но должна отдавать данные тестировщикам, чтобы те могли потыкать и протестировать в условиях продакшена. Ну а ты как думал? Тестируем на проде, можем себе позволить ))) 🎉

Городим в nginx на b1 такой велосипед:

map $http_x_backend $backend {
bashdays-w5 192.168.0.5:3000; # w5
default backend;
}

upstream backend {
server 192.168.0.1:3000; # w1
server 192.168.0.2:3000; # w2
server 192.168.0.3:3000; # w3
server 192.168.0.4:3000; # w4
}

location / {
add_header X-Upstream $upstream_addr;
proxy_pass http://$backend;
}

Объясняю что происходит, клиенты идут на b1 и попадают по умолчанию в upstream backend, где прописаны ноды w1-w4.

Тестировщики подставляют заголовок X-Backend: bashdays-w5 в своих запросах и попадают на w5. То есть для обычных пользователей ничего не изменилось, но QA теперь с помощью заголовка X-Backend: bashdays-w5 могут попасть на новую ноду и затыкать ее хоть до усрачки.

В location есть директива add_header X-Upstream, она выведет в ответе nginx на какую ноду ты попал, удобно для дебага.

В раздел map можно добавить еще кучу нод, которые не будут участвовать в обслуживании клиентов, но ты в любой момент сможешь на них попасть с помощью заголовка.

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

Конфигурация nginx это как стихи писать, есть какие-то базовые слова и правила, но в большинстве случаев 90% функционала вообще не используется. Потому что, документацию никто не читает и люди делают так, как научились или подсмотрели на stackoverflow. Вот такие пироги.

tags:
#nginx

🟢 Подпишись: @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
Сегодня мы будем делать с вами свой nginx plus (тот который платный), а именно реализуем плюшку «Active health checks».

Это когда у тебя к примеру 10 апстримов и если один из них дохнет, то какой-нибудь богатый клиент получит 502 ошибку, обозлится и ничего не купит. А должен автоматически попасть на другой, более живой апстрим и потратить денежку.

Само собой будем применять инновационные технологии и немного возьмем из фреймворка «гавно и палки». Ну а как ты хотел? Бест практик! На халяву и уксус сладкий, как говорится. Короче все элементарно. Погнали.

Ставим ванильный nginx и делаем так:

upstream backend {
server unix:/var/run/haproxy/backend.sock;
}

location / {
proxy_pass http://backend;
}

Ставим рядом haproxy, и конфигурируем блоки frontend и backend таким образом:

defaults
retries 3
timeout check 5s

frontend bashdays-backend
bind /var/run/haproxy/backend.sock user nginx mode 600
mode tcp
default_backend bashdays-backend
option tcplog

backend bashdays-backend
balance roundrobin
option tcplog
server bashdays-w1 192.168.0.1:80 check
server bashdays-w2 192.168.0.2:80 check
server bashdays-w3 192.168.0.3:80 check
server bashdays-w4 192.168.0.4:80 check

Что это за хрень, щас объясню. Смотри. Клиент идет на хуй корень / и попадает в nginx апстрим backend, а апстрим сконфигурирован на сокет backend.sock от haproxy.

Далее запрос клиента пролетает по сокету, как фанера над загнивающим парижем и попадает в блок haproxy «backend» где у меня описаны все бэкенд-сервера (w1, w2, w3, w4).

Если по какой-то причине к примеру сервер w2 отдаст концы, haproxy это задетектит (timeout check 5s) и закинет запрос клиента на рабочий инстанс, тем самым клиент получит статус 200. А 200 == заебись хорошо! 🗒

Ну а потом когда w2 очухается, то haproxy снова заберет его в свои сети и будет использовать на всю катушку, как провинившуюся падшую женщину.

Вот так это и работает. Вот так вот и живем. Балансировка нагрузки + roundrobin + active health checks

У haproxy еще есть встроенный визуальный мониторинг, но об этом я расскажу тебе в одной из следующих статей.

tags:
#nginx

🟢 Подпишись: @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
Ну вот и пятница на носу. Хотя какая разница какой день недели, если ты работаешь 24/7. Чем займёмся сегодня? Давай чём-нибудь простым и интересным.

Порой необходимо определить количество ядер на сервере. Понятно, ты можешь вызвать top/htop и визуально глянуть цифру.

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

Для подсчета количества ядер, есть несколько способов:

1. grep -wc '^processor' /proc/cpuinfo
2. getconf _NPROCESSORS_ONLN
3. nproc --all

Это не единственные способы заполучить желаемое, но самые релевантные. Кстати getconf актуален и для макаводов (osx).

Для чего нам знать количество ядер? Вопрос хороший, каждый для себя сам решает. Всё зависит от задач.

К примеру заскейлил ты тачку в Selectel, через их веб панельку, но nginx продолжает работать на старом конфиге. После этого очень желательно сразу переопределить в nginx.conf параметр worker_processes.

Если Nginx выполняет работу нагружающую процессор (например SSL или gzipping), то оптимально установить эту директиву в значение, равное количеству ядер процессора.

Также, директива worker_processes, умноженная на worker_connections из секции event, даст максимально возможное количество клиентов.

Конечно же справедливо всё это ансиблом (ansible) или террой (terraform) раскатать, но это дополнительный геморрой, который никому не нужен. По крайней мере, когда это нужно было еще вчера и нет возможности писать лапшу из плейбуков.

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

Прототип без ифов, так, для наглядности:

#!/bin/bash

CPU_CORES=$(grep -wc '^processor' /proc/cpuinfo)

sed -i "s/worker_processes.*/worker_processes $CPU_CORES;/" /etc/nginx/nginx.conf

systemctl reload nginx

Бери на вооружение, пригодится. 😮‍💨

Ну а я желаю тебе хороших предстоящих выходных и береги себя! Мож чо на выходные еще закину интересного почитать.

tags: #linux #nginx

🟢 Подпишись: @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
Привет. Как оказалось, не все знают что nginx позволяет нативно писать логи в json формате. Вообще в продакшене это бест-практика. Для этого в конфиг nginx.conf нужно добавить такой блок:

log_format nginx_json escape=json '{"time_local":"$time_local", "cloud_ip":"$http_x_real_ip", "ip":"$http_cf_connecting_ip", "connection":"$connection", "request_completion":"$request_completion", "status":"$status", "rtime":"$request_time", "rlenght":"$request_length", "content_type":"$content_type", "content_length":"$content_length", "bytes_sent":"$bytes_sent", "body_bytes_sent":"$body_bytes_sent", "raddr":"$remote_addr", "ruser":"$remote_user","upstream_addr":"$upstream_addr", "upstr_resp_time":"$upstream_response_time", "upstr_cache_status":"$upstream_cache_status", "upst_status":"$upstream_status", "gzip_ratio":"$gzip_ratio", "http_x_forwarded_for":"$http_x_forwarded_for", "proxy":"$proxy_host:$proxy_port", "proxy_int_body_length":"$proxy_internal_body_length", "server_proto":"$server_protocol", "rmethod":"$request_method", "uri":"$uri", "args":"$args", "http_referer":"$http_referer", "uag":"$http_user_agent"}';

access_log /var/log/nginx/access.log nginx_json;
error_log /var/log/nginx/error.log;


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

Но хранить логи в файлах, такое себе. Поэтому мастхэв запихать логи непременно в system journal.

Забиваем пару строк в nginx.conf и всё логирование будет перенаправлено в system journal.

error_log syslog:server=unix:/dev/log;
access_log syslog:server=unix:/dev/log nginx_json;


А можно комбинировать, писать одновременно логи в файл в дефолтном шаблоне nginx’а и параллельно писать в system journal в json. Я иногда такое проворачиваю для дебага, где в логах требуется вывести лишь время, айпишник и ури-ури. Типа такого:

log_format nginx_json ...
log_format nginx_default ...

access_log /var/log/nginx/access_json.log nginx_json;
access_log /var/log/nginx/access_default.log nginx_default;


Но конечно если есть Kibana, дела с отладкой в разы становятся лучше. Ну а чтобы посмотреть логи в system journal, воспользуйся такой командой: journalctl -f

Сегодня если руки дойдут, обсудим судо-мудо или другие линукс кишочки. Давай, хорошей тебе пятницы, увидимся!

tags: #nginx

💩 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
Поднимал тут у себя огородик с wg-easy, всё ок. Но из коробки, морда для создания ключей работает по протоколу http. Вроде ничего страшного, но не серьезно. Ну и настраивать nginx + acme.sh тоже капец лень.

Пока искал готовое решение (кстати нашел нативный мануал от wg-easy), набрел на интересную штуку. Называется Nginx Proxy Manager.

Короче это морда для nginx, чтобы не руками конфиг задрачивать, а мышкой галочки натыкивать + из коробки нативная интеграция с letsencrypt.

Возможно у нас в чатике где-то это уже и пролетало, но я не видал.

Поднимается за минуту через docker-compose, без лишних велосипедов и костылей. Дружит с sqlite и mysql. Есть система распределения прав, каждый юзер может редактировать свои локейшены и хосты. Поддерживает малину и arm архитектуры. Ну и естественно есть гибкий Access List и Basic Auth.

Киллер-фича: Можно генерить wildcard ssl, выбираешь из большого выпадающего списка к примеру cloudflare и оно тебе DNS Challenge делает. Это прям порадовало.

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

В общем рекомендую как для локальной разработки, так и для каких-то своих сервисов вроде bitwarden и т.п.

Картинки у них на сайте посмотрите, не буду сюда запихивать.

🌐 https://nginxproxymanager.com/

tags: #nginx #services

💩 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
Привет, тут на днях в нашем чатике пролетала софтина которая делает этакий ханипот на 22 порту. И все кто ломится по ssh просто вязнут в этом болоте.

Но сегодня не про это. Сегодня про злоумышленников, которые методом тыка пытаются найти и украсть бэкап. Зачастую бэкапы хранятся в папках проекта, либо вообще в корне пылятся годами.

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

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

Как с этим бороться? Ничего не бэкапить в папки проекта, удалять промежуточные файлы если что-то переносил, настраивать политики nginx чтобы 403 отдавал и т.п.

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

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

Давай настроем такой ханипот на примере nginx

Добавляем в nginx конфиги:

location ~* "^/(new|old|bkup|tmp|temp|upload|ftp|sql|file|www|drupal|joomla|wordpress|x|user|admin|a|b|r|rezerv|arch|arx|111|archive|auth|backup|clients|com|dat|dump|engine|files|home|html|index|master|media|my|mysql|old|site|sql|website|wordpress)\.tar.gz$" {
access_log /var/log/nginx/honeypot.log;
default_type application/zip;
root /var/www/bashdayz/files/backup;
rewrite ^(.*)$ /backup break;
max_ranges 0;
limit_rate 4k;
limit_conn addr 1;
}

# а это в секцию http
limit_conn_zone $binary_remote_addr zone=addr:10m;


Указываем список на что будем триггериться. Ограничиваем скорость, ограничиваем число потоков, запрещаем докачку.

Создаем файл затычку размером 1гиг, этого вполне хватит. Но можешь конечно сделать и больше.

dd if=/dev/zero of=/var/www/bashdayz/files/backup bs=1G count=1


Вот и всё. Теперь если кто-то попытается вытянуть у тебя бэкап к примеру mysql.tar.gz, то будет страдать. Идея думаю тебе понятна, вокруг нее можно городить вообще сумасшедшие схемы. Но опять же это всего лишь концепт, из которого можно сделать что-то большое и нужное.

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

Ничего особенного, но с сюрпризом, бэкап никогда не скачается. Тащить 10 гигабайт со скоростью dial-up ну такое себе. А когда те начинали орать как свинья из avp, мой ответ был простой - проблема на твоей стороне. У меня видишь все работает и показываю скриншот с нормальной скоростью.

Но таким быть фу, заподлостроением пусть школьники занимаются. Мы с вами взрослые и ответственные ребята. Правда? )

Ладно, рад всех видеть. Всем хорошей рабочей недели!

tags: #nginx #networks

💩 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
Event loop из семи залуп.

✔️ Сегодня запускаем bash скрипт из nginx по локейшену.

Идея такая, при открытии урла в браузере https://bashdays.com/bashdays.sh запускается bash скрипт, который лежит на сервере в папке /tmp/bashdays.sh.

А зачем это нужно? Элементарно — чтобы запустить Bash скрипт!

Но никогда так не делай.


Чтобы подобное реализовать, тебе понадобится fcgiwrap либо lua. Из обычного nginx, который в коробке, это сделать невозможно. Политика безопасности, вся хуйня.

Я возьму fcgiwrap, не хочу компилить модуль lua. Если у тебя есть lua, можешь через него подобное реализовать. Примеры ниже.

Ставим врапер:

apt install fcgiwrap


Закидываем скрипт в /tmp/bashdays.sh

#!/bin/bash

echo "Content-type: text/html"
echo ""
echo "<h1>Hello Bashdays</h1>"
echo "<p>This is a test bash script.</p>"

echo "hello bashdays" > file.txt


В конфиге nginx городим локейшен:

location /bashdays.sh {
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_param SCRIPT_FILENAME /tmp/bashdays.sh;
include fastcgi_params;
}


Заранее убедись что сокет fcgiwrap создался и лежит в нужном месте. На этом собственно всё. Да, надо сделать еще nginx reload.

Открываем https://bashdays.com/bashdays.sh и лицезрим «Hello Bashdays This is a test bash script.».

Но это еще не все. В папке /tmp появился файл file.txt. Как видишь все получилось. Дальше включай фантазию и твори.

Для lua это будет выглядеть как-то так:


location /bashdays.sh {
content_by_lua_block {
os.execute("/tmp/bashdays.sh")
}
}


Я этот код не проверял, он всяко не работает, на коленке накидал, но думаю главное тут суть.

Кстати через php наверное тоже можно башник дернуть, там сокет так же подкинуть и через «хуй-пизда-лопата» запустить скрипт.

Вообще промышлять таким - фу! Если ты кому-то расскажешь, то тебя выгонят ссаными тряпками. Всё чисто ради экспериментов. Изучай!

tags: #linux #nginx #bash

@ВАSНDАYS | BАSHDАYS.CОM
Please open Telegram to view this post
VIEW IN TELEGRAM