
Автономный SSH-хоніпот для перехоплення взаємодій атакуючих і перетворення їх на структуровану розвідку з кібербезпеки.
SSHintel — это легковесный SSH-хоніпот, созданный с использованием Python и Paramiko. Он имитирует фейковую Linux-оболочку для регистрации несанкционированных попыток доступа, перехвата учетных данных и анализа поведения атакующих в контролируемой среде.
ls, cd, pwd, , , , , , , , , , , , , , , и др.)catechogrepfindtreeheadtailwcstatpsdffreeenvidwhoami--tarpit для замедления атакующих с задержкой выводаSSHintel — это не полноценная Bash/Linux-оболочка. Он имитирует правдоподобное подмножество распространённых команд для сбора телеметрии атакующих. Команды обрабатываются лёгким реестром; добавление команды означает добавление небольшой функции-обработчика.
pip install -r requirements.txt
Примечание: SSH-ключ хоста генерируется автоматически при первом запуске. Ручная генерация ключей не требуется.
Запустите хоніпот с указанным портом, именем пользователя и паролем:
python3 run.py serve --port 2222 --username user1 --password pass123
Порт по умолчанию —
2222, хост —0.0.0.0.
Хоніпот автоматически генерирует SSH-ключ хоста в static/server.key при первом запуске, если он не существует. Ручная генерация ключей не требуется.
Для включения режима tarpit:
python3 run.py serve --port 2222 --username user1 --password pass123 --tarpit
Для отключения телеметрии SQLite (только JSONL):
python3 run.py serve --port 2222 --username user1 --password pass123 --no-db
SSHintel защищает от исчерпания ресурсов из-за множества одновременных подключений или подключений, поддерживаемых бесконечно. Это настраивается через CLI:
| Флаг | По умолчанию | Назначение |
|---|---|---|
--max-connections | 50 | Максимальное количество одновременных активных подключений; дополнительные подключения отклоняются и регистрируются как событие connection_rejected |
--auth-timeout | 60 (с) | Время, отведённое на завершение SSH-рукопожатия/аутентификации; зависшие клиенты отключаются |
--session-idle-timeout | 300 (с) | Таймаут бездействия для аутентифицированной оболочки; бездействующая сессия завершается, но активно печатающий атакующий никогда не убивается |
Пример:
python3 run.py serve --port 2222 --username user1 --password pass123 \
--max-connections 25 --auth-timeout 30 --session-idle-timeout 300
Когда открыто слишком много подключений, дополнительное подключение немедленно закрывается, и в JSONL-журнал записывается событие безопасности connection_rejected (с reason: connection_limit). Зависшая аутентификация регистрируется как отключение с reason: auth_timeout; бездействующая оболочка завершается с reason: idle_timeout.
Режим tarpit намеренно отправляет вывод медленно, чтобы удерживать атакующего, поэтому цикл баннера tarpit не подчиняется таймауту бездействия — но tarpit-сессии учитываются в лимите подключений.
SSHintel включает локальную веб-панель, которая визуализирует телеметрию безопасности, хранящуюся в SQLite.
python3 run.py dashboard
Затем откройте http://localhost:5000 в браузере.
Панель по умолчанию читает данные из базы SQLite в
data/sshintel.db. Сначала запустите хоніпот, чтобы телеметрия собиралась, затем запустите панель и наблюдайте, как она заполняется.
Нажмите на ID сессии (или перейдите по адресу /session/<session_id>), чтобы открыть просмотр расследования сессии, который восстанавливает одну атаку в хронологическом порядке:
$ команда всего, что вводил атакующий, с рабочими директориями# Терминал 1: запуск хоніпота
python3 run.py serve --port 2222 --username user1 --password pass123
# Терминал 2: запуск панели
python3 run.py dashboard
# Терминал 3: имитация атакующего
ssh user1@localhost -p 2222
# (выполните несколько команд, затем выйдите)
Затем откройте http://localhost:5000, чтобы просмотреть захваченную активность.
Панель поддерживает живую телеметрию — она опрашивает хоніпот каждые 2 секунды и обновляется автоматически. Новые сессии, команды и события появляются в реальном времени без обновления страницы. Индикатор Live (● Live) показывает статус подключения.
Откройте второй терминал и попробуйте подключиться:
ssh user1@localhost -p 2222
Если учетные данные совпадают, вы попадёте в эмулированную оболочку.
Чтобы удалить устаревшие SSH-отпечатки:
notepad "%USERPROFILE%\.ssh\known_hosts"
Удалите соответствующую строку, содержащую
localhostили IP хоніпота.
creds_loggerfunnel_loggerlog_files/events.jsonl в формате JSON Lines (JSONL) — один корректный JSON-объект на строкуКаждое событие JSONL включает UTC ISO-8601 timestamp, event_type, уникальный session_id и source_ip. Подключения, попытки/результаты аутентификации, выполнение команд, активация tarpit и отключения — всё регистрируется как структурированные события.
Каждое входящее SSH-подключение отслеживается как независимая сессия со своим session_id. Сессия записывает исходный IP, время подключения/отключения, результат аутентификации и продолжительность подключения, и каждое событие, сгенерированное в рамках этого подключения, несёт тот же session_id (поэтому попытки аутентификации, команды и отключения можно связать с одним подключением). Сессии изолированы для каждого подключения — состояние не разделяется между одновременными клиентами.
Каждая сессия также получает свою собственную изолированную, in-memory фейковую файловую систему — имитированная файловая система создаётся заново для каждого подключения и очищается при завершении подключения. Файлы, директории и рабочая директория, созданные или изменённые одним атакующим, никогда не видны другому атакующему, подключённому одновременно. Вся файловая система имитируется в памяти Python и никогда не касается реальной файловой системы хоста.
Текущие значения event_type: connect, auth_attempt, auth_success, auth_failure, command, disconnect, connection_rejected, tarpit.
SSHintel/
├── honeypot/ # Основная логика хоніпота
│ ├── __init__.py
│ ├── main.py # Цикл приёма + ограничение подключений
│ ├── handlers.py # Настройка SSH-транспорта + эмулированная оболочка
│ ├── server.py # Интерфейс сервера Paramiko (аутентификация)
│ ├── session.py # Отслеживание сессии для каждого подключения
│ ├── fs.py # In-memory фейковая файловая система (изолирована для каждой сессии)
│ ├── shell.py # Фейковая оболочка: реестр команд + диспетчер
│ ├── limits.py # Потокобезопасное ограничение одновременных подключений
│ ├── logger.py # JSONL-регистрация событий + мост SQLite
│ └── telemetry_store.py # Хранилище телеметрии SQLite + слой запросов
│
├── dashboard/ # Локальная веб-панель
│ ├── app.py # Приложение Flask + API-маршруты
│ ├── templates/
│ │ ├── index.html # Основной шаблон панели
│ │ └── session.html # Шаблон расследования сессии
│ └── static/
│ ├── style.css # Стили панели
│ ├── dashboard.js # Основной JS панели (живые обновления)
│ └── session.js # JS расследования сессии
│
├── log_files/ # Журналы выполнения (игнорируются git)
│ ├── creds_audits.log # Попытки ввода учетных данных
│ ├── cmd_audits.log # Журнал аудита команд
│ └── events.jsonl # Структурированные события безопасности JSONL
│
├── data/ # База данных SQLite (игнорируется git)
│ └── sshintel.db
│
├── static/ # SSH-ключ хоста (автоматически генерируется)
│ └── server.key
│
├── .github/workflows/ # Конфигурация CI
│ └── tests.yml
│
├── Dockerfile
├── README.md
├── requirements.txt # Зависимости выполнения (paramiko, flask)
├── requirements-dev.txt # Тестовые зависимости (pytest, pytest-cov)
└── run.py # Точка входа CLI
Если вы предпочитаете запускать хоніпот в контейнеризированной среде, вы можете использовать включённый Dockerfile.
docker build -t sshintel .
Это создаёт Docker-образ с именем
sshintel.
docker run -p 2222:2222 sshintel
Это:
static/server.key (если он ещё не существует)2222 с учетными данными по умолчанию:username: user1, password: pass123Откройте второй терминал и подключитесь через SSH:
ssh user1@localhost -p 2222
Вы попадёте в имитированную оболочку, если учетные данные совпадают.
Чтобы остановить контейнер:
docker ps # Найдите ID контейнера
docker stop <container_id>
Чтобы удалить образ:
docker rmi sshintel
Вы также можете экспортировать образ с помощью
docker save -o sshintel.tar sshintelи загрузить его позже с помощьюdocker load -i sshintel.tar.
Этот проект лицензирован в соответствии с лицензией MIT.