Comments 63
А текст вообще вычитывался перед публикацией? Или подразумевается, что до некоторых с первого раза не доходит? :-)
я не глухой слепой, я не слепой. Поэтому не нужно мне повторять все по два раза, по два раза ))))

Отличная статья, с удовольствием прочитал ее дважды :)
А если серьезно, то реально попробую эту технику использовать

Для таких fail2ban придумали и даже с экспоненциальной системой бана.
Добавлю для Ubuntu/Debian:

sudo apt install xtables-addons-dkms
iptables -t raw -A PREROUTING -p tcp --dport 22 -j NOTRACK
iptables -A INPUT -p tcp --dport 22 -j TARPIT

Понадобятся хедеры ядра и компилятор, если ещё не стоят.
К сожалению вещь просто веселая (и классная), но никак не полезная. И никто не будет дорабатывать скрипты. Эти сканеры работают во-первых массово, во-вторых их цели ну настолько кривые устройства, где ssh сервера реализованы такими Ляо на коленке, весь этот сонм криво настроенного IoT, что среди них девайсов со странным поведением — 50%. Вообще никто не заметит что одно соединение кривое, их у сканера будут тысячи и сами по себе без специализированного тарпита через жопу.
Port knocking, имхо, удобнее и безопаснее. К тому же дорабатывать нужно только скрипты клиентов.
ну о чём вы, какой port knocking? Конечно же лучше потратить десяток килобайт памяти спамера ценой отдельного сервиса у себя)
т.е. тарпит не сервис, а что-то такое ангельское эфемерное, не заметное для системы… :) под ддосом весьма нехило может ресурсов пожрать.
порт-кнокинг имхо гораздо надежнее. без ключа не открыт ни один лишний порт, и одного лишнего движения.

есть еще пинг-кнокинг под некоторые системы прощее стучатся получается.

Вот не понимаю, зачем.
Вам шашечки или ехать?
У вас цель: обезопасить сервер или сделать мир лучше?
У меня, как правило, первая.
Поэтому sshd + blacklistd + ipfw ОТЛИЧНО справляются с данной задачей (по опыту, куда лучше fail2ban и sshguard).
И порт не меняю: а смысл?
Из-за того, что кто-то куда-то может пару раз постучать, корячиться и всегда помнить, что при ssh — одним способом порт указывать, при scp — другим?.. А скрипты: когда в одном проекте один порт, а в другом — он занят приложением?..
Безопасности добавли на ноль целых и ничего десятых, зато неудобства — на все 100 :)

Для желающих тут же погрузиться в поиск: blacklistd хорош, но FreeBSD-only. Ждём, как говорится, e-buildов

по опыту, куда лучше fail2ban и sshguard

Аргументировано.
На собственном опыте могу сказать, что "по опыту" как правило значит чуть более чем ничего. Кхе… кхе :)


На самом деле главный аргумент приспешников blacklistd ("не нужно парсить лог") "разбивается" единственным примером:
Демон sshd (при включенном UseBlacklist) отправит инфу (authentication success/failure) на blacklistd сокет, и… запишет это в лог. Ну а blacklistd прочитает её из сокета и распарсит.
Чем оно в принципе отличается от "распарсивания" fail2ban тех же строчек прочитанных из лога, никто так и не смог мне внятно объяснить.


Кроме того, fail2ban тоже это давно умеет, а в новых версиях уже официальным протоколом и для сообщения об отдельных неудачных попытках, т.е. достаточно отправить ему на сокет:


# отовсюду (симулируем простейший "маринад"):
f2b_attempt_msg="(lp0\nS'set'\np1\naS'%s'\np2\naS'attempt'\np3\naS'%s'\np4\na.<F2B_END_COMMAND><F2B_CLOSE_COMMAND>"
printf "$f2b_attempt_msg" sshd 192.0.2.1 | nc -q 0 -U '/run/fail2ban/fail2ban.sock'
# из питона:
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM);
s.connect('/run/fail2ban/fail2ban.sock'); 
s.send(pickle.dumps(['set', 'sshd', 'attempt', '192.0.2.2', 'unknown user'], 0) + b"<F2B_END_COMMAND>"); s.close()
# ну и из шела:
fail2ban-client set <jail> attempt <IP>  [<failure-message1> ... <failure-messageN>]
Демон sshd (при включенном UseBlacklist) отправит инфу (authentication success/failure) на blacklistd сокет, и… запишет это в лог.

настраиваемо.


Ну а blacklistd прочитает её из сокета и распарсит.
Чем оно в принципе отличается от "распарсивания" fail2ban тех же строчек прочитанных из лога, никто так и не смог мне внятно объяснить.

лучше уж хотя бы тем, что не нужно в системе держать питон ради единственного fail2ban.
размер используемой памяти — очевидно же, не в пользу fail2ban.
и решение в случае sshd+blacklistd+ipfw получается "искаропки".

"искаропки" оно было бы, если бы sshd умел всё то сам (это однако противоречило бы философии *nix).

Сделать мир лучше — тоже неплохая цель, особенно если требует всего несколько килобайт на сервере.

питон во многих сборках Linux есть по-умолчанию. Не во всех, естественно, но устанавливать специально его чаще всего не требуется.

Не понял, какое неудобство от смены порта? Просто один раз написать пару строчек в ssh config? Менять порт рекомендуют наряду с другими мероприятиями по усилению безопасности. Ясное дело, что OpenSSH (обычно эта реализация ssh) дофига безопасный сам по себе, но нежеланных гостей все равно лучше не ждать с вывеской «Добро пожаловать, назовите пароль».
наверное, когда куча машин, логиниться хочется со всех на все, а puppet еще не настроили, тогда неудобно
В принципе можно и шашечки и ехать: вместо того, чтобы банить — отправлять в ловушку.
отправляет бесконечный поток случайно сгенерированных данных

А как же стоимость исходящего трафика?
Подскажите, а какой смысл при работе Endlessh отправлять именно рандомные данные в строке с «SSH-»? Может быть можно ещё немного упростить программу?
Чтоб враги сразу не догадались и заморочились поиском способа «расшифровки»?
Так это до криптографии. Автор же писал, что можно отправлять любые данные до строки с версией. А просто так вещать не пойми кому свой рандом тоже не безопасно. Если генератор некачественный, то со стороны противника можно осуществлять анализ и это теоретически поспособствует другому вектору атак.
Я ж не просто так взял в кавычки, я имел в виду: пускай потенциальный взломщик сидит и ломает голову, что же это такое, тратит ресурсы и время. А реальную криптографию даже в виду не имел.
Лучше как раз взять самый некачественный программный псевдогенератор (PRNG(x)), и пусть хоть сколько ломают себе голову. Потому как в системе и openssl используются совсем другие.
59348 2465K TARPIT tcp — eth0 * 0.0.0.0/0 0.0.0.0/0 tcp multiport dports 20,22,25,80,135,139,5900,8080,8443 -j TARPIT --tarpit

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

С одной стороны да, а с другой — тарпнутые (пойманные в ловушку) соединения висят в conntrack и не протухают, так как тарпит не дает. Например, если тарпить на слабых роутерах, то из-за того, что контрэк распух — у вас снизится (и реально снижается!) скорость коммутации пакетов (табличку долго просматривать приходится). Очень этим грешили роутеры типа DIR-100, когда запуск torrent и последующее выключение забивали контрэк так, что до провайдера пинг подскакивал до сотен. Просто потому что соединения плодились, а не полоса была занята. Сейчас с этим получше, но в любом случае проблема остается.
Опять же, можно написать (уже написано примерно во времена появления TARPIT в iptables, но гуглить лень) генератор пакетов, который навешает у вас TARPIT соединений, которые вы сами же будете поддерживать и забивать свой контрэк, а со стороны хакера это не будут соединения, а просто пара пакетов с железяки, которая даже не знает что такое TCP.
Решение есть: на все порты, которые -j TARPIT делать еще -t raw -j NOTRACK (ну или совсем отказаться от conntrack)

Но такие сложности уже напоминают ситуацию — обе стороны наелись гов.. мыла, и остались при своем

Но все же в целом с вами соглашусь: использовать -j TARPIT, если уж хочется именно потроллить ботнеты (ведь сканят именно ботнеты, вручную мало что сканят), куда практичнее, чем запускать демона на питоне или даже С, симулирующего ssh
iptables -t raw -A PREROUTING -p tcp --dport 22 -j NOTRACK
iptables -A INPUT -p tcp --dport 22 -j TARPIT


UPD: увидел, что вы уже написали про NOTRACK. Но всё равно пусть коммент висит, лишним не будет. Тратить conntrack на мусорные соединения действительно как-то не очень.
Запустил питоновскую версию, добавив чуть логов. Несколько часов не было ни одного подключения, потом подзабыл об этом. Сейчас смотрю — 39 клиентов уже подключалось.
Добавил еще немного логов, чтобы удобнее отслеживать длительность коннектов.
В результате, 6 из 7 подключений отваливаются через 30 секунд, седьмое протянулось на 17 минут и 30 секунд.
Если хотите больше подопытных, перенесите хонейпот на порт 445 или 23. А если 80 свободен, то перенесите его туда, поскольку там вся тусовка.
Не очень понятно зачем это нужно. Повесить на 22 порт, а реальный sshd поднять на рандомном? И наказывать кулхацкеров?
1378 бесполезных соединений на сервере висящих в течение 20 часов против ботнета который сканирует порты на уязвимости, за счет ресурсов зараженных пользователей, не совсем похоже на правильный подход. Всегда считал что лучше минимизировать свои затраты, чем сделать кому то хуже чем себе. Ханипоты нужны для обнаружения и предотвращения атак, но никак не для наказывания, замучаятесь наказывать.
Я кстати в недоумении. 3 дня пытаюсь достучаться до поддержки avito и dns-shop по поводу их систем защиты. И в одном и в другом месте необычайная тупость технической поддержки.
Дословный ответ: Наша система работает отлично, а вам не надо подключатся через VPN к нашему сайту.

Ответ от других еще более глобален:
image
Давно известно, что авито блокирует доступ к некоторым ресурсам сайта с адресов прокси и прочих левых диапазонов. И ещё википедия не даёт статьи редактировать.
В Википедии это вынужденная мера, чтобы затруднить многократную реинкарнацию заблокированного вандала. Добросовестному участнику с положительным вкладом при необходимости выдают технический флаг исключения из IP-блокировок, позволяющий редактировать с заблокированного IP-адреса, а также через прокси, VPN и Tor; 24–25 августа 2015 года в связи с тогдашними событиями активным участникам (более трёхсот) выдали такой технический флаг, а 27 августа его почти у всех забрали за ненадобностью.
Ну дак и в авито это точно такая же вынужденная мера. Только флаг не выдают.
Python без отступов в форматировании работать не будет. Поправьте форматирование.
Мне кажется, на продакшене правильный «хонейпот» должен привести к INPUT DROP.
DROP сразу же говорит о том, что порт открыт и трафик фильтруется.
Правильнее
-A INPUT -p tcp -m tcp -j REJECT --reject-with tcp-reset
-A INPUT -p udp -m udp -j REJECT --reject-with icmp-port-unreachable

Так это выглядит закрытыми (не открытыми приложениями) портами, и в скане nmap, к примеру, порты будут 'closed', а не 'FILTERED'.
Дроп ни о чём не говорит, а вот пришедший в ответ резет явно говорит о фильтрации.
Вы заблуждаетесь и плохо себе представляете функционирование сетей. Всё именно так, как я сказал.
Когда кто-то обращается к хосту на порт, который не «слушает» ни одно приложение (порт closed), он (хост) отвечает ICMP-сообщением «icmp-port-unreachable» («Порт недоступен»). Если недоступен весь хост, то предыдущий роутер отправляет icmp-host-unreachable («Узел недоступен»).
Т. е. при нормальном функционировании сети пакеты не должны пропадать «в никуда» и бесследно. Таким образом, отсутствие ответа (и, к примеру, «повисшая» в стадии установки соединения TCP-сессия, как в примере) как раз говорит о фильтрации, и именно так и показывает это nmap. О чём прямо написано в «man nmap»:
«The state is either open, filtered, closed, or unfiltered. Open means that an application on the target machine is listening for connections/packets on that port. Filtered means that a firewall, filter, or other network obstacle is blocking the port so that Nmap cannot tell whether it is open or closed. Closed ports have no application listening on them… »

Так что, прежде чем что-то безапелляционно утверждать, — проверяйте себя.
Стоит учитывать, что такое поведение характерно только для хоста, который торчит всеми открытыми портами непосредственно в Интернет. Если хост находится за брандмауэром (как частный случай, брандмауэр включен на самом хосте), в котором по умолчанию стоит deny all (DROP), то обычным поведением будет как раз DROP.
Если используется INPUT DROP, то атакующий видит FILTERED для всех портов, вне зависимости от того, открыт порт или нет. Используя REJECT, атакующий видит то же самое, только вместо FILTERED, отображается CLOSED. Однако есть проблема: REJECT, в отличии от DROP, не обрывает соединение, а всё же отвечает на запрос.

Учитывая то, что ни в одном из этих случаев атакующий не может знать, используется тот или иной порт на целевой машине, то правильнее всего использовать DROP, а не заставить машину отвечать на ненужные запросы.
Для FTP в наше время есть переключение протокола на SFTP с авторизацией по ключу и скорейшему забыванию про существование FTP.
В своём блоге автор приводит пример для веб-сервера и говорит, что решение «идеально подходит» для создания подобных ловушек. Если немного его поправить, думаю, для FTP тоже должно работать.
Небольшое замечание:

> И там же приписка: «Сервер МОЖЕТ послать другие строки данных перед отправкой строки с версией». И нет ограничения на объём этих данных, просто каждую строку нужно начинать с SSH-.

По поводу начала строки RFC говорит прямо противоположное: The server MAY send other lines of data before sending the version string. Each line SHOULD be terminated by a Carriage Return and Line Feed. Such lines MUST NOT begin with «SSH-»

> Именно этим занимается программа Endlessh: она отправляет бесконечный поток ..., а каждая строка начинается с SSH-

Чтобы убедиться что это не так достаточно сделать telnet localhost 2222
Или посмотреть в исходник.
static int
randline(char *line, int maxlen, unsigned long s[1])
{
    int len = 3 + rand16(s) % (maxlen - 2);
    for (int i = 0; i < len - 2; i++)
        line[i] = 32 + rand16(s) % 95;
    line[len - 2] = 13;
    line[len - 1] = 10;
    if (memcmp(line, "SSH-", 4) == 0)
        line[0] = 'X';
    return len;
}
</code>

Странно, что никто этого не заметил. 
А разве if (memcmp(line, "SSH-", 4) == 0) не проверяет, что строка начинается с «SSH-» и если да, то line[0] = 'X'; заменяет первый символ на «X»? То есть, такая строка становится «XSH-».
Именно так. Для того чтобы выполнить требование RFC: lines MUST NOT begin with «SSH-»
Спасибо. Оказывается, это ошибка перевода. В оригинале автор пишет:
There is no limit on the number of lines, just that these lines must not begin with “SSH-“
localhost не является аргументом. Запускается лишь для tcp6, на гх есть репорт на эту тему.
Если целью злоумышленников является один сервер, то они могут просканировать все его порты (все 216). Если же злоумышленники сканируют диапазон IP-адресов, то у каждого адреса они будут проверять несколько стандартных портов, или даже только 22 порт — потому что как бы много ресурсов ни было у злоумышленников, эти ресурсы не бесконечны. Впрочем, использование нестандартного порта — не единственная необходимая мера предосторожности; в частности, надо отключить SSH-доступ по паролю (оставить только по ключу).
Only those users with full accounts are able to leave comments. Log in, please.
Information
Founded

Since 1996

Location

Япония

Employees

Неизвестно

Registered

30 January 2018