Статья LLM Honeypot: строим приманку на базе языковой модели для мониторинга всех 65535 портов

Стальная рыболовная приманка в форме серверного шасси с мигающими светодиодами лежит на чёрном антистатическом коврике. Позади светится экран ноутбука с зелёными строками терминала.


Классический Cowrie с дефолтным SSH-баннером обманывает автоматический сканер ровно до момента, когда тот шлёт нестандартную команду и получает заскриптованный ответ. Один и тот же баннер, десяток захардкоженных команд, идентичная файловая система на каждом экземпляре - Mirai-подобные ботнеты и Masscan раскусывают такие детерминированные паттерны на раз. Для современного threat detection этого давно мало.

LLM honeypot решает проблему принципиально: вместо шаблонов за каждую реплику отвечает языковая модель, генерирующая контекстно-зависимый вывод в реальном времени. По данным исследования HoneyGPT (Wang et al., 2024, arXiv:2406.01882), такой подход значительно увеличивает среднюю длину атакующей сессии по сравнению с Cowrie и позволяет фиксировать ранее неизвестные тактики, маппящиеся на MITRE ATT&CK. Атакующий думает, что ломает живую машину, расслабляется - и сливает свои TTPs.

Дальше - как построить такой honeypot своими руками на Linux: развернуть единый proxy-listener на все 65535 портов через nftables, подключить языковую модель для генерации ответов, настроить rate limiting (чтобы массовое сканирование не сожрало бюджет на API), и организовать логирование для threat intelligence.

Почему статические ловушки больше не работают как приманка для хакеров​

Honeypot-системы fingerprint-ятся по нескольким категориям признаков. Согласно SoK-обзору «Honeypots & LLMs» (arxiv, 2025), даже после интеграции LLM фундаментальные ограничения могут выдать систему достаточно опытному атакующему. Но ключевой вывод исследователей: целевой adversary для LLM honeypot - не человек, который занимается пентестом, а автоматизированные агенты и ботнеты. Именно их мы и ловим.

Проект Palisade Research подтверждает это реальными цифрами: по состоянию на начало 2025 года (ai.agenthoneypot.com) их LLM Agent Honeypot зафиксировал значительное количество взаимодействий, из которых небольшая часть идентифицирована как потенциальные AI-агенты с высокой достоверностью - через prompt injection detection и temporal analysis (точные цифры меняются, актуальные значения на ai.agenthoneypot.com). Среди основных источников атак по географии - США, Китай и Нидерланды. Ничего неожиданного.

Классические detection-векторы, по которым атакующие распознают ловушку:
  • Статические баннеры - SSH-версия Cowrie легко находится поиском, Shodan маркирует такие хосты автоматически.
  • Ограниченный набор команд - нестандартная утилита возвращает одинаковый «command not found» вместо вариативного ответа реальной ОС.
  • Идентичная файловая система - содержимое /etc/passwd, hostname, /proc одинаковы на каждом экземпляре.
  • Тайминг - шаблонные ответы прилетают за микросекунды, тогда как реальный сервер отвечает с вариативной задержкой.
  • Сетевой fingerprinting - TCP window size, TTL, опции в SYN-ACK выдают, что за «маршрутизатором Cisco» стоит Linux-процесс.
LLM honeypot снимает первые три проблемы полностью: модель генерирует уникальные ответы, имитирует произвольную файловую систему и поддерживает нестандартные команды. Но вносит собственные артефакты - о них в финальном разделе.

Канонический pipeline: архитектура LLM honeypot от пакета до лога​


1776879824404.webp


За последние два года (по данным SoK-обзора) сформировалась устойчивая архитектурная модель deception technology на базе языковых моделей. Ниже - компоненты, которые затем реализуем на практике.

Компоненты системы обнаружения вторжений​

Network front-end (listener). Принимает TCP-подключения на целевых портах. В нашем случае это единый asyncio-процесс, получающий трафик со всех 65535 портов через nftables REDIRECT.

Protocol router. По оригинальному порту назначения определяет эмулируемый сервис: порт 80/443 - HTTP, 23 - Telnet и т.д. Для неизвестных портов - generic TCP-баннер. Бинарные протоколы (SSH, TLS, MySQL handshake) требуют protocol-aware фронтенда (например, Cowrie для SSH) - generic text-LLM тут не катит.

Prompt manager. Формирует system prompt для LLM с учётом протокола, «личности» системы (конкретная ОС, hostname, набор пакетов) и текущей сессионной истории. Исследователи VelLMes описывают этот компонент как protocol personality template - шаблон, задающий жёсткие поведенческие рамки вплоть до символа приглашения командной строки.

LLM engine. Принимает промпт и пользовательский ввод, возвращает ответ. Может быть локальным (Ollama) или облачным (OpenAI API). Лично я для тестирования предпочитаю Ollama - данные никуда не утекают, и задержка предсказуемая.

State manager. Хранит историю сессии, чтобы ls после cd /tmp показывал содержимое /tmp, а не корня. Согласно оригинальной статье HoneyGPT (arXiv:2406.01882), система использует score-weighted pruning: когда токенный бюджет исчерпан, команды с наименьшим «весом влияния» удаляются из контекста первыми.

Output formatter. Адаптирует raw-вывод LLM под протокольные требования: добавляет $ для bash, mysql> для MySQL-клиента, HTTP-заголовки для веб-сервера. Без него модель периодически выдаёт markdown-разметку посреди терминальной сессии - моментальное палево.

Logger. Пишет всё в JSON: timestamp, src_ip, оригинальный dst_port, payload атакующего, ответ LLM, session_id. Формат рассчитан на прямую загрузку в ELK или Graylog.

Облако или локальный inference - что выбрать​

Выбор модели для AI honeypot detection - компромисс между качеством, задержкой и стоимостью:

ПараметрОблако (GPT-3.5 / GPT-4)Локально (Ollama + Llama 3 8B)
Качество ответовВысокоеСреднее, но хватает для большинства протоколов
Задержка200–800 мс50–200 мс на GPU, 500–2000 мс на CPU
СтоимостьТарифицируется за токеныЭлектричество + амортизация GPU
Контроль данныхЛоги атакующих уходят провайдеруВсё остаётся локально
МасштабОграничен rate limit APIОграничен мощностью железа

Для production-развёртывания рекомендую гибридную схему: локальная модель через Ollama обрабатывает массовые сканирования, а облачный API подключается для «интересных» сессий - тех, где атакующий отправил больше двух-трёх команд и прошёл фильтр тривиальности. Так 90% мусорного трафика не стоит ни копейки, а на оставшиеся 10% тратится GPT-4 - и оно того стоит.

Мониторинг портов honeypot: один процесс на 65535 портов​

Наивный подход - вызвать bind() на каждом из 65535 портов - убьёт систему. Каждый слушающий сокет требует файлового дескриптора, и даже при поднятом ulimit -n 65535 overhead на 65 тысяч listener-ов составит сотни мегабайт только на структуры ядра (не считая asyncio-задач). На типовом VPS с 2 ГБ RAM это нереализуемо.

Решение - единый listener + перенаправление на уровне ядра.

Требования к окружению​

  • ОС: Ubuntu 22.04 LTS или Debian 12+ (ядро 5.15+)
  • Python: 3.10+ с модулями asyncio, struct, socket
  • nftables: версия 1.0.2+ (в Ubuntu 22.04 из коробки)
  • LLM backend: Ollama 0.1.30+ с моделью llama3:8b - или API-ключ OpenAI
  • RAM: 8 ГБ при локальном inference, 2 ГБ при облачном
  • Сеть: выделенный VPS с публичным IP, без production-сервисов на этом хосте
  • Режим: online (нужна связь с LLM API или локально запущенный Ollama)

Перенаправление через nftables и извлечение оригинального порта​


1776880006632.webp


Идея простая: nftables перенаправляет весь входящий TCP на единственный порт (допустим, 8443), где слушает asyncio-сервер. Сервер через getsockopt с опцией SO_ORIGINAL_DST узнаёт, на какой порт клиент обращался изначально, и выбирает соответствующий промпт-шаблон.
Bash:
nft add table ip honeypot
nft add chain ip honeypot prerouting { type nat hook prerouting priority -100 \; }
nft add rule ip honeypot prerouting iif "eth0" tcp dport != { 22, 8443, 11434 } redirect to :8443
Порт 22 исключён - это ваш реальный SSH для управления сервером. В production добавьте исключения для порта мониторинга и Ollama API (11434 по умолчанию). Забудете исключить - заблокируете себе доступ к собственной машине, проверено.

Asyncio-обработчик, который извлекает оригинальный destination port:
Python:
import asyncio, struct, socket

SO_ORIGINAL_DST = getattr(socket, 'SO_ORIGINAL_DST', 80)  # нативно в Python 3.12+; fallback для старых версий

async def handle_client(reader, writer):
    sock = writer.get_extra_info('socket')
    # только IPv4 (sockaddr_in, 16 байт); для IPv6 нужен SOL_IPV6 и буфер 28 байт
    dst = sock.getsockopt(socket.SOL_IP, SO_ORIGINAL_DST, 16)
    orig_port = struct.unpack('!H', dst[2:4])[0]
    prompt = select_prompt(orig_port)  # 22→SSH, 80→HTTP, generic
    # server-first протоколы (SMTP:25, FTP:21, Telnet:23) - отдаём баннер до read()
    # бинарные протоколы (SSH:22, MySQL:3306, TLS) требуют protocol-aware прокси
    banner = get_static_banner(orig_port)
    if banner:
        writer.write(banner.encode())
        await writer.drain()
    data = await reader.read(4096)
    if not data:
        writer.close()
        return
    response = await call_llm(prompt, data.decode(errors='replace'))
    writer.write(response.encode())
    await writer.drain()

async def main():
    server = await asyncio.start_server(handle_client, '0.0.0.0', 8443)
    async with server:
        await server.serve_forever()

asyncio.run(main())
select_prompt(port) возвращает system prompt для сервиса. Для портов без явного маппинга - generic-промпт, имитирующий закрытый или нестандартный сервис. call_llm делает запрос к Ollama через HTTP API на localhost:11434/api/generate или к OpenAI - в зависимости от конфигурации.

Prompt engineering: как языковая модель имитирует реальные сервисы​

Качество обмана целиком зависит от промпта. Вот ключевые принципы, собранные из нескольких исследований и собственных экспериментов:
🔓 Эксклюзивный контент для зарегистрированных пользователей.

Управление памятью в stateful-сессиях​

Атакующий ожидает, что pwd после cd /var/log вернёт /var/log, а не /root. Для этого нужна stateful-сессия: вся история команд и ответов передаётся в контекст LLM при каждом запросе.

Проблема: при длинной сессии контекстное окно переполняется. В honeypot на основе ИИ это критично - потеря контекста означает, что повторный cat /etc/passwd вернёт другое содержимое файла. Атакующий моментально поймёт, что перед ним не реальная машина.

Решение из HoneyGPT - score-weighted pruning. Каждой команде в истории присваивается вес влияния с временным затуханием. Когда бюджет токенов исчерпан, записи с наименьшим весом удаляются первыми. Команды файловой навигации (cd, ls, mkdir) получают высокий вес - они влияют на весь дальнейший контекст. Повторные whoami или id - низкий.

На практике это словарь {session_id: [(command, response, weight, timestamp), ...]} с периодическим пересчётом суммарного количества токенов через tiktoken или аналогичную библиотеку. Не самая элегантная конструкция, но работает.

Защита бюджета при массовом сканировании портов​

Это та самая ловушка, о которой не пишут в academic papers, но которая ломает реальные деплои. Когда сканер с banner grabbing (nmap -sV или Masscan с --banners) проходит по всем 65535 портам, каждое TCP-подключение с payload потенциально генерирует вызов LLM. SYN-сканирование (дефолтный режим Masscan без --banners) не отправляет данных после handshake и LLM не вызывает - см. Уровень 2 ниже.

Расчёт для наихудшего сценария без защиты (version scan с payload на каждый порт): 65535 подключений, каждое ~200 input-токенов (промпт+команда) и ~200 output-токенов (ответ), при тарифах gpt-4o-mini ($0.15/1M input, $0.60/1M output) - примерно $10 за один полный скан одного сканера. При сотне таких сканеров в сутки (типичная нагрузка публичного IP; по данным Palisade Research, отдельные IP генерировали сотни тысяч попыток) бюджет улетает в тысячу долларов и выше. Неприятный сюрприз в конце месяца.

Многоуровневая защита:

Уровень 1 - nftables rate limit. Ограничьте новые подключения с одного IP через meter. Рабочее правило (в отдельном filter-chain с приоритетом выше nat): nft add chain ip honeypot filter_prerouting { type filter hook prerouting priority -150 \; } и затем nft add rule ip honeypot filter_prerouting tcp flags syn ip saddr meter flood size 65535 { ip saddr limit rate over 10/second } drop - пакеты сверх лимита дропаются до попадания в nat-цепочку с REDIRECT. Masscan и Zmap отсекаются ещё до того, как трафик достигнет Python-процесса.

Уровень 2 - engagement threshold. LLM вызывается только если атакующий отправил данные после TCP handshake. SYN-сканирование не генерирует LLM-вызовов, потому что соединение закрывается до передачи payload. Бесплатно.

Уровень 3 - tiered response. Первый ответ - статический баннер из словаря (SSH version string, HTTP 200 с минимальным body). LLM подключается после второй-третьей команды, когда ясно, что это целевое взаимодействие, а не массовый скан. 99% ботов отваливаются после первого баннера.

Уровень 4 - token budget per IP. Программный лимит: максимум 4000 токенов на один source IP в час. При превышении - переключение на статические ответы или контролируемый разрыв.

Логирование атак honeypot и маппинг на MITRE ATT&CK

Honeypot без аналитики - просто шум. Каждое взаимодействие записывается в JSON-лог с полями: timestamp, session_id, src_ip, src_port, original_dst_port, payload_hex, payload_decoded, llm_response, llm_latency_ms, tokens_used.

Для интеграции с SIEM логи отправляются через Filebeat в Elasticsearch. В Kibana создаются дашборды: топ атакующих IP, распределение подключений по портам, длина сессий, частота уникальных команд. Это превращает honeypot из пассивной приманки для хакеров в полноценный источник threat intelligence.

Маппинг обнаруженной активности на MITRE ATT&CK:

Наблюдаемое действиеТехника ATT&CKТактика
Подключение к диапазону портовNetwork Service Discovery (T1046)Discovery
Сканирование версий/баннеров на портуVulnerability Scanning (T1595.002)Reconnaissance
Exploit-payload на конкретный портExploit Public-Facing Application (T1190)Initial Access
Последовательный перебор IP-блокаScanning IP Blocks (T1595.001)Reconnaissance
Попытка подбора credentialsBrute Force (T1110)Credential Access
HTTP/DNS-туннелирование в сессииApplication Layer Protocol (T1071)Command and Control

По данным HoneyGPT, LLM honeypot обнаруживает тактики, которые классические ловушки пропускают - именно за счёт того, что атакующий продолжает сессию дольше и раскрывает больше TTPs. Грубо говоря, чем дольше бот думает, что ломает реальную машину - тем больше он показывает из своего арсенала.

Отдельное направление - детекция AI-агентов. Проект Palisade Research встраивает в сессию prompt injection: если «собеседник» на другом конце TCP-соединения - языковая модель, она реагирует на инъекцию иначе, чем человек. Temporal analysis (паттерны задержек между командами) добавляет второй слой верификации. Мы ловим ботов ботами - ирония ситуации не ускользает.

Попробуйте развернуть этот стек на дешёвом VPS, повесить на публичный IP и оставить на неделю. Гарантирую - количество и разнообразие того, что прилетит, вас удивит. А если среди сессий окажется что-то длиннее пяти команд - значит, кто-то действительно поверил, что перед ним живой сервер. И вот тут начинается самое интересное для threat intelligence.

Вопрос к читателям​

Коллеги, кто уже тестировал score-weighted pruning из HoneyGPT (arXiv:2406.01882) в production-сессиях с длинным контекстом - как вы калибруете веса для команд файловой навигации против разведочных команд типа uname -a или cat /proc/version? Конкретно: при каком пороге токенов (например, 4096 из 8192 у Llama 3 8B через Ollama) вы начинаете pruning, и какой decay-коэффициент используете для временного затухания? Второй вопрос по nftables-правилу: если атакующий шлёт SYN на порт 11434 (Ollama API), а вы забыли его исключить в tcp dport != { 22, 8443, 11434 } - какой nftables-счётчик (nft list ruleset) показывает утечку трафика до Ollama, и как вы это обнаружили в логах?
 
Последнее редактирование модератором:
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab