Алексей Мичурин

Полезное

Работа с данными: передача, архивирование

Для Python-программиста

Нотификатор

Памятка с полезными скриптами и наборами опций

Mount/umount USB-Flash

Создание swap в файле

Русификация a2ps

Настройка Xorg

Работа с сетью: настройка, диагностика

Рort knocking

Как подготовить полноценную инсталляцию ArchLinux на USB Flash.

Настройка sudo под Linux

Фракталы

Фрактальная размерность

Применение фракталов

Фрактальные деревья

Комплексная размерность

Теория относительности

Пространство-время

Физический смысл

Скорость света

Эквивалентность систем

Относительность

Движение быстрее света

Парадокс близнецов

Любопытные соображения

Недоделанное

Редактор favicon on-line

Устаревшие страницы

Простой HTML-валидатор

Об авторе

Рort knocking


Условия

При реализации стучалки я отталкивался от таких условий:

  • Стук только в один порт. Очень часто, по крайней мере в моей жизни, мне доступен только один порт.
  • Стук с любого места и любыми средствами. Часто приходится стучаться тем, что есть под рукой.
  • Правила стука должны быть предельно простыми.
  • Механизм стука должен ограничивать частоту подключений.
  • Реализация средствами чистого iptables. Неохота что-то устанавливать, настраивать, обновлять, держать всегда поднятым.

Итого, какие я избрал правила стука:

  • Рассматриваем только попытки создать новое соединение.
  • Если не позволяем создать соединение, то используем не DROP, а REJECT. Чтобы клиенты не пытались соединиться повторно.
  • Если номер попытки меньше N — отклоняем.
  • Если номер попытки равен N — пропускаем.
  • Если номер попытки больше N — отклоняем.
  • Правило живёт заданное количество секунд, после первой попытки.

Реализация port knocking средствами iptables

Вызываем port-knocking цепочку в подходящем месте как-то так.

iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j KNOCK

Не забываем, что в цепочку для тука должны попадать только SYN-пакеты.

Правила цепочки очень просты:

# создаём или обновляем запись в /proc/net/xt_recent/KNOCK_SSH
-A KNOCK -m recent --set --name KNOCK_SSH --rsource
# если за последние 60 секунд было более 10 попыток подключиться, то не пропускаем попытку
-A KNOCK -m recent --rcheck --seconds 60 --hitcount 11 --name KNOCK_SSH --rsource -j RETURN
# если за последние 60 секунд это попытка 10-я пропускаем подключение
-A KNOCK -m recent --rcheck --seconds 60 --hitcount 10 --name KNOCK_SSH --rsource -j ACCEPT
# в противном случае возвращаемся из цепочки

Внимание! Я предполагаю, что основная цепочка правил закрытая.

Итого. Что мы получили

Первые 10 попыток подключиться будут безуспешными. Это отвадит большинство сканеров.

Если в порт стучат реже 10 раз в минуту, то у сканера не будет возможности подключиться.

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

Теоретически, сканер может стучаться ровно 10 раз в минуту, тогда он сможет выполнять проверку пароля раз в 6 секунд. Я считаю, что этого тоже недостаточно для успешной атаки.

Если ваша паранойя зашла дальше моей, то вы можете поменять цифры или добавить таблицы (аналогичные KNOCK_SSH) и цепочки (аналогичные KNOCK). Таким образом можно собрать сколь угодно сложную (в разумных пределах) машину состояний. Правда, при этом уже придётся помнить правильный "стук". Я считаю это слишком обременительным.

И ещё одно замечание: не ставьте hitcount больше 20, подробнее смотрите man iptables.

Полый пример фаервола с порт-кнокингом

# фаервол закрыт
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
# дополнительные цепочки для удобства
:KNOCK - [0:0]
:TCP - [0:0]
:TRUSTED - [0:0]
# пропускаем всё для установленных соединений
# (далее будет только обработка новых соединений)
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# пропускаем всё, что относится к локальному хосту
-A INPUT -i lo -j ACCEPT
# игнорируем весь сломанный трафик
-A INPUT -m state --state INVALID -j DROP
# пропускаем всё с доверенных IP
-A INPUT -j TRUSTED
# обрабатываем разные виды трафика (есть только TCP, но можно завести для чего угодно)
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j TCP
-A INPUT -p icmp -j ACCEPT
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable
# цепочка для обработки tcp
# 22 порт отправляем на анализ стука
-A TCP -p tcp -m tcp --dport 22 -j KNOCK
# торенты пропускаем
-A TCP -p tcp -m tcp --dport 6881:6889 -j ACCEPT
# цепочки для анализа стука
-A KNOCK -m recent --set --name KNOCK_SSH --rsource
-A KNOCK -m recent --rcheck --seconds 60 --hitcount 11 --name KNOCK_SSH --rsource -j RETURN
-A KNOCK -m recent --rcheck --seconds 60 --hitcount 10 --name KNOCK_SSH --rsource -j ACCEPT
# доверенные IP-адреса, пропускаемые без фильтрации
-A TRUSTED -s 194.67.3.229/32 -j ACCEPT

Вы можете связаться со мной по e-mail a.michurin@gmail.com.



Технология Google App Engine Python powered