notes

DDOS

============

Что делать если вас начали досить или и того хуже - ддосить?

Ну вообще-то желательно обратиться к профи антиддоса, но если надо прямо здесь и сейчас - есть один небольшой лайфхак.

Обычно ддос идет из стран, которые вашему сервису не интересен. Например, если у вас интернет магазин работает в России, то навряд ли можно считать валидными пользователей из Вьетнама. Абсолютно понятно, что it depends, но если вы подходите под этот случай, то быстро отбить небольшую атаку можно и с помощью nginx. Делает это примерно так.

В начале определяется map:

map $geoip_country_code $allowed_country {
default no;
RU yes;
UA yes;
}

Мапим мы переменную, которую предоставляет geoip модуль, поэтому он должен быть подключен к nginx. В данном примере если пользователь пришел из России или Украины, то $allowed_country будет содержать значение yes. В остальных случаях - no.

Ну а дальше дело техники добавить в нужный server или location простенький if:

if ($allowed_country = no) {
return 403;
}

=============

CURL

=============

Вы еще не используете curl? Тогда мы идем к вам!
Потрясающая утилита, которая позволяет вам очень быстро протестировать любой http сервис. Посмотреть хедеры, протестировать api, проверить ssl и многое многое другое. Возможно если бы я разрабатывал API целыми днями, то поставил бы себе какой-нибудь gui клиент и работал бы в нем. Но по долгу службы чаще всего приходится быстро сделать запрос и проверить ответ. И в этом curl'у нет равных.
Чаще всего я использую curl в таком виде:

curl -D - -s -o /dev/null -H 'Host: domain.com' -k https://app1.domain.com/

Немного об опциях:
1. -D - - дампить хедеры в -, что означает stdout.
2. -s - silent mode - не показывать скорость загрузки и не выводить ошибки
3. -o /dev/null - все что отдаст нам вебсервер выкинуть в /dev/null
4. -H 'Host: domain.com - добавить к запросу хедер Host: domain.com
5. -k - игнорировать валидность ssl сертификата - мы же обращаемся на конкретную ноду (app1.domain.com) и сертификат явно не совпадет с domain.com. Хотя возможно вы используете wildcard сертификаты и тогда в данном случае можно не заморачиваться.

Вот таким нехитрым способом можно быстро протестировать любой endpoint. Еще из полезных опций можно отметить:
1. -u user:password - указываем логин/пароль для basic auth
2. -d '{data}' - передать данные в POST запросе
3. -d @/path/to/file - передать в POST запросе данные из файла

А еще очень удобно смотреть json, передавай вывод curl на вход jq:

curl -s -o - http://google.com/json_response | jq .

Из интересного можно посмотреть еще на http://http-prompt.com, но у меня он не прижился - не любою интерактивные утилиты.

===========

nginx+monitor

===========

Хмельной Девопс, [16.01.18 15:15]
Про мониторинг nginx.
Помимо стандартных url чек и /status страниц можно собирать еще кучу дополнительных параметров. Я использую связку prometheus + nginx + несколько экспортеров. Немного подробнее о них:

1. https://github.com/vozlt/nginx-module-vts - vts модуль, которые выдает расширенную статистку по запросам/ответам прямо из недр nginx. Единственный минус данного модуля - нет разделения на коды ответов (только 2xx,3xx,4xx,5xx,...) и нет данных по времени ответа.
К этому модулю идет экспортер: https://github.com/hnlq715/nginx-vts-exporter, получаются вполне хорошие графики, по которым можно смотреть всплески 4-ых и 5-ых ошибок.

2. https://github.com/martin-helmich/prometheus-nginxlog-exporter - парсит лог файлы nginx'а, агрегирует все данные и потом отдает prometheus'у на хранение. Работает в режиме tail -f, то есть как демон. Позволяет выдавать интересную статистику по 90,99th percentile времени ответов и кодам ошибок. На скриншоте ниже данные с nginx-log-exporter с одной ноды. Главное не забыть добавить в лог файлы nginx время ответа клиенту и время ответа upstream, чтобы эти данные появились:


log_format time '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'$upstream_response_time $request_time';

 

====================

У многих очень часто возникают проблемы с настройкой firewall. А все потому что никто и никогда не пытается рисовать упрощенную схемку сети. Я для себя используют примерно такой алгоритм при настройке firewall:

1. Нарисовать схемку со всеми заинтересованными сторонами - локальная сеть, сервера, клиенты и тд и тп
2. Показать на этой схемке движение пакетов/сегментов/whatever
3. Описать словами или символами какие потоки должны быть разрешены, какие запрещены, какие перекинуты.
4. Переписать пункт 3 на языке фаервола (в нашем случае iptables).

Ниже будет приведена очень простая схема с локальной сетью и двумя серверами внутри.

Первый кейс - разрешить клиенту А доступ к firewall по ssh:

1.a Входящий трафик на интерфейсе eth0 от клиента с ip 1.1.1.1 на порт 22 разрешить
1.b iptables -I INPUT -i eth0 -s 1.1.1.1/32 -p tcp -m tcp --dport 22 -j ACCEPT

Второй кейс - нам надо пробрасывать все запросы, идущие к нам на порт 80, на зеленый сервер на порт 80:

2.a Весь входящий трафик на интерфейс eth0 на порт 80 проксировать на зеленый сервер на порт 80
2.b iptables -t nat -I PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j DNAT --to-destination green_ip:80

Третий кейс - нам надо запретить красному серверу выходить в интернет:

3.a Весь входящий трафик на eth1 идующий от красного сервера в интернет запретить
3.b iptables -I INPUT -i eth1 -s red_ip/32 ! -d 172.16.0.0/24 -j DROP

Как вы можете заметить - весь локальный трафик, обращенный к firewall'у от красного сервера будет разрешен, что соответствует условию задачи.

И последний, четвертый кейс - маскировать исходящий адрес от всех клиентов локальной сети:

4.a Во всем трафике от пользователей локальной сети, идущим в интернет, маскировать исходящий адрес
4.b iptables -t nat -I POSTROUTING -o eth0 -s 172.16.0.0/24 -j MASQUERADE

Ну и вишинка на торте - блокируем весь остальной входящий трафик. Вообще есть два подхода к настройке firewall - blacklisting или whitelisting. При первом мы разрешаем все, что не запрещено. При втором наоборот - запрещаем все, что не разрешено. Я придерживаюсь подходе whitelisting и обычно меняю политику входящего (и исходящего) трафика на DROP. Так образом все что не разрешено явно будет запрещено:

iptables -P INPUT DROP

Кстати, про исходящие правила. Тут все точно так же как и с входящими, просто меняется вектор движения трафика. По этому поводу циско рекомендует придерживаться следующий правил:

1. Входящий трафик должен блокироваться как можно ближе к получателю
2. Исходящий трафик должен блокироваться как можно ближе к отправителю