СофтХабрахабр

Ловушка (тарпит) для входящих SSH-соединений

Не секрет, что интернет — очень враждебная среда. Как только вы поднимаете сервер, он мгновенно подвергается массированным атакам и множественным сканированиям. На примере ханипота от безопасников можно оценить масштаб этого мусорного трафика. Фактически, на среднем сервере 99% трафика может быть вредоносным.

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

Технику впервые разработали для защиты от компьютерных червей. Чаще всего тарпиты применяют для защиты. Программа открывает порт (по умолчанию для тестирования указан порт 2222) и притворяется SSH-сервером, а на самом деле устанавливает бесконечное соединение с входящим клиентом, пока тот не сдастся. А сейчас её можно использовать, чтобы испортить жизнь спамерам и исследователям, которые занимаются широким сканированием всех IP-адресов подряд (примеры на Хабре: Австрия, Украина).
Одному из сисадминов по имени Крис Веллонс, видимо, надоело наблюдать за этим безобразием — и он написал маленькую программку Endlessh, тарпит для SSH, замедляющий входящие соединения. Это может продолжаться несколько дней или больше, пока клиент не отвалится.

Установка утилиты:

$ make
$ ./endlessh &
$ ssh -p2222 localhost

Правильно реализованный тарпит отнимет у злоумышленника больше ресурсов, чем у вас. Но дело даже не в ресурсах. Автор пишет, что программа вызывает привыкание. Прямо сейчас в его ловушке 27 клиентов, некоторые из них подключены в течение недель. На пике активности в ловушке сидели 1378 клиентов в течение 20 часов!

Стандартные рекомендации по безопасности всегда советуют переместить SSH на другой порт, что сразу на порядок сокращает размер логов. В рабочем режиме сервер Endlessh нужно ставить на обычный порт 22, куда массово стучатся хулиганы.

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

В общем, всё по стандарту. Именно этим занимается программа Endlessh: она отправляет бесконечный поток случайно сгенерированных данных, которые соответствуют RFC 4253, то есть отправка перед идентификацией, а каждая строка начинается с SSH- и не превышает 255 символов, включая символ окончания строки.

Это предотвращает отключение по таймауту, так что клиент будет сидеть в ловушке вечно. По умолчанию программа ожидает 10 секунд между отправками пакетов.

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

В отличие от современных антивирусов и других «систем безопасности», она не должна тормозить компьютер. Автор постарался, чтобы утилита потребляла минимум ресурсов и работала абсолютно незаметно на машине. Если бы он просто запускал отдельный процесс на новое соединение, то потенциальные злоумышленники могли бы провести DDoS-атаку, открыв множество соединений для исчерпания ресурсов на машине. Ему удалось минимизировать и трафик, и потребление памяти за счёт чуть более хитрой программной реализации. По одному потоку на соединение — тоже не лучший вариант, потому что ядро будет тратить ресурсы на управление потоками.

Чтобы не выделять буферы получения и отправки для каждого клиента, Endlessh открывает сокет прямого доступа и напрямую транслирует пакеты TCP, игнорируя почти весь стек TCP/IP операционной системы. Поэтому Крис Веллонс выбрал для Endlessh самый легковесный вариант: однопоточный сервер poll(2), где клиенты в ловушке практически не потребляют лишних ресурсов, не считая объекта сокета в ядре и ещё 78 байт для отслеживания в Endlessh. Входящий буфер вообще не нужен, потому что входящие данные нас не интересуют.

Если бы он знал об asycio, то свою утилиту мог бы реализовать всего в 18-ти строчках на Python: Автор говорит, что на момент своей программы не знал о существовании питоновского asycio и других тарпитов.

import asyncio
import random async def handler(_reader, writer):
try:
while True:
await asyncio.sleep(10)
writer.write(b'%x\r\n' % random.randint(0, 2**32))
await writer.drain()
except ConnectionResetError:
pass async def main():
server = await asyncio.start_server(handler, '0.0.0.0', 2222)
async with server:
await server.serve_forever() asyncio.run(main())

Asyncio идеально подходит для написания тарпитов. Например, такая ловушка на много часов подвесит Firefox, Chrome или другого клиента, который пытается подключиться к вашему HTTP-серверу:

import asyncio
import random async def handler(_reader, writer):
writer.write(b'HTTP/1.1 200 OK\r\n')
try:
while True:
await asyncio.sleep(5)
header = random.randint(0, 2**32)
value = random.randint(0, 2**32)
writer.write(b'X-%x: %x\r\n' % (header, value))
await writer.drain()
except ConnectionResetError:
pass async def main():
server = await asyncio.start_server(handler, '0.0.0.0', 8080)
async with server:
await server.serve_forever() asyncio.run(main())

Тарпит — отличный инструмент для наказания интернет-хулиганов. Правда, есть некоторый риск, наоборот, привлечь их внимание к необычному поведению конкретного сервера. Кто-то может подумать о мести и нацеленной DDoS-атаке на ваш IP. Впрочем, пока таких случаев не было, и тарпиты отлично работают.

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»