Продвинутый

Coldframe: ханипот под видом контроллера холода

Алексей Кузнецов
Алексей Кузнецов
Системный администратор9 ноября 2026 г.12 мин чтения

Что такое ханипот Coldframe, как он имитирует контроллер холодильника супермаркета и какие попытки взлома на него регистрируются.

Coldframe: ханипот под видом контроллера холода

Что такое ханипот Coldframe, как он имитирует контроллер холодильника супермаркета и какие попытки взлома на него регистрируются.

Что такое Coldframe и зачем он нужен

Что такое Coldframe и зачем он нужен

Ханипот — это уязвимый сервис, который выглядит как реальная цель, но существует только для фиксации попыток взлома. Coldframe делает это под видом контроллера холодильной витрины супермаркета.

Идея и вдохновение

Контроллеры холодильных витрин — классические OT-устройства. Они висят в торговом зале, подключены к локальной сети магазина, а часто и к интернету для удалённого мониторинга. Прошивки обновляют редко, пароли оставляют заводские, а веб-интерфейс открыт для «удобства». Я встречал подобные инциденты ещё на предыдущем месте работы — атакующие проникали через слабо защищённые терминалы и кассы, а не через основной периметр.

Coldframe повторяет эту модель. Внешне он ведёт себя как настоящий контроллер: отвечает на HTTP-запросы, отдаёт температуру в камере, показывает статус компрессора и принимает команды на изменение режима охлаждения. На самом деле за всем этим стоит Python-приложение за nginx, которое ничего реального не охлаждает, но записывает каждое действие атакующего.

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

Стек простой: nginx на фронтенде, TLS для шифрования, Python на бэкенде. Ничего лишнего. Если хотите посмотреть, как собирать метрики с такого nginx, есть отдельный материал — Интеграция Nginx с Prometheus для мониторинга.

Что имитирует ханипот

Coldframe имитирует три вещи: веб-интерфейс управления, API для телеметрии и TLS-сертификат, который выглядит легитимно.

Веб-интерфейс — это стандартная панель с графиками температуры и кнопками управления режимом. Атакующий видит форму логина, список датчиков и переключатель компрессора. Все запросы проходят через nginx, который отдаёт статику и проксирует API на Python-бэкенд.

Конфиги пишу руками, даже если есть GUI. GUI для тех, кто не знает, где лежит конфиг. Пример минимального конфига nginx для такого ханипота:

nginx
server {
    listen 443 ssl;
    server_name coldframe.local;

    ssl_certificate /etc/nginx/ssl/coldframe.crt;
    ssl_certificate_key /etc/nginx/ssl/coldframe.key;

    location / {
        root /var/www/coldframe;
        index index.html;
    }

    location /api/ {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    access_log /var/log/nginx/coldframe_access.log;
    error_log /var/log/nginx/coldframe_error.log;
}

Python-бэкенд отдаёт JSON с текущей температурой и статусом:

python
from flask import Flask, jsonify

app = Flask(__name__)

@app.route("/api/temperature")
def temperature():
    return jsonify({"sensor": "chamber_1", "value": 2.4, "unit": "celsius"})

@app.route("/api/compressor/status")
def compressor_status():
    return jsonify({"state": "running", "cycle": 3})

Важный момент — сертификат. Coldframe генерирует самоподписанный TLS-сертификат с именем, похожим на реальное оборудование (coldframe-store-01.local, refr-controller.local). Атакующий, который уже находится внутри сети, видит валидный с точки зрения браузера замок и не подозревает подвоха. Если нужно настроить экспорт метрик с такого nginx в Prometheus, можно использовать нативную поддержку — Интеграция Nginx с Prometheus: нативная поддержка.

Что регистрирует ханипот:

  • сканирование портов и поиск открытых веб-интерфейсов;
  • попытки подбора паролей к админке;
  • запросы к несуществующим эндпоинтам (/admin, /setup, /config);
  • эксплуатацию известных уязвимостей в прошивках контроллеров;
  • попытки изменения температуры или отключения компрессора.

Каждое событие пишется в лог nginx и в отдельный файл событий Python. Это даёт представление не только о том, что ищут атакующие, но и о том, как они ведут себя после первого контакта с устройством.

Как устроен Coldframe внутри

Как устроен Coldframe внутри

Coldframe — ханипот, который маскируется под контроллер холодильной витрины супермаркета. Снаружи это обычная веб-панель с температурой и режимами работы, а внутри — изолированная среда, где каждое действие посетителя фиксируется. Для меня главное здесь не сам «обман», а предсказуемость конфигурации: злоумышленник думает, что попал на промышленное оборудование, а на самом деле оказывается в ловушке, где каждый его шаг пишется в лог.

Стек технологий

Coldframe состоит из трёх частей. Nginx терминирует TLS и отдаёт фиктивный веб-интерфейс. Серверный сертификат можно сгенерировать самоподписанным или взять от внутреннего центра сертификации — для атакующего разницы нет, он видит значок замка в адресной строке и успокаивается.

Пример конфига nginx:

nginx
server {
    listen 443 ssl;
    server_name coldframe.local;

    ssl_certificate     /etc/nginx/ssl/coldframe.crt;
    ssl_certificate_key /etc/nginx/ssl/coldframe.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

За бэкендом стоит простой скрипт на Python. Он эмулирует API контроллера холода: отдаёт текущую температуру, принимает «команды» на изменение режима, но ничего реального не меняет. Python выбран потому, что быстро пишется и легко читается — как конструктор, только для серверной логики.

Во-первых, стек минимален: нет лишних зависимостей, в которых можно найти уязвимость. Во-вторых, всё работает на одном хосте, что упрощает выделение под изолированный VLAN. Если нужно мониторить сам ханипот, можно прикрутить экспорт метрик nginx — я уже описывал интеграцию с Prometheus (Интеграция Nginx с Prometheus для мониторинга).

Логирование и сбор данных

Логи — единственная ценность ханипота. Если не фиксировать, кто и что пытался сделать, Coldframe превращается в дорогой бесполезный сервер.

Nginx пишет access- и error-логи в стандартном виде. Я рекомендую включить формат с временем запроса и User-Agent, чтобы сразу видеть, сканирует ли хост автоматизированный бот или живой человек.

nginx
log_format coldframe '$remote_addr - $remote_user [$time_local] '
                     '"$request" $status $body_bytes_sent '
                     '"$http_referer" "$http_user_agent"';

access_log /var/log/nginx/coldframe_access.log coldframe;
error_log  /var/log/nginx/coldframe_error.log;

Python-бэкенд ведёт отдельный лог — там фиксируются попытки «управления» температурой, ввод неверных паролей, запросы к несуществующим endpoints. Каждая запись содержит IP, временную метку и тело запроса. Я предпочитаю journald для системных служб, но для приложения на Python удобнее писать в файл с ротацией через logrotate, чтобы диск не забился за ночь.

Пример записи из лога Python:

2024-01-15 03:12:47 [INFO] 10.0.0.45 POST /api/set_temperature {"temperature": -999}
2024-01-15 03:12:48 [WARNING] 10.0.0.45 GET /admin/login attempt with default credentials

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

Если хотите посмотреть, как настраиваю экспорт метрик nginx, читайте связанные материалы: Интеграция Nginx с Prometheus: нативная настройка или Настройка экспорта метрик Nginx в Prometheus.

Coldframe не ломается сам — он ждёт, пока его попытаются сломать. И в этом его главное отличие от обычного сервера: здесь любая активность — уже инцидент, который стоит разобрать.

Какие атаки фиксирует ханипот

Какие атаки фиксирует ханипот

Coldframe прикидывается контроллером холодильной витрины супермаркета. Снаружи это выглядит как маленькое устройство с веб-интерфейсом на 443-м порту: спереди nginx, завершающий TLS, сзади python-скрипт, эмулирующий протокол контроллера. Атакующие не знают, что это ловушка, и ведут себя так, как будто нашли реальное оборудование на периметре.

Для терминации TLS я использую простой конфиг nginx. Сертификат самоподписанный, с CN, похожим на бренд реального холодильного оборудования — этого достаточно, чтобы автоматизированные сканеры заинтересовались хостом.

nginx
server {
    listen 443 ssl;
    server_name coldframe.local;

    ssl_certificate /etc/nginx/ssl/coldframe.crt;
    ssl_certificate_key /etc/nginx/ssl/coldframe.key;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Python-бэкенд отвечает на типичные для таких контроллеров пути и пишет свои логи отдельно от nginx.

Типы попыток подключения

Логи показывают три повторяющихся паттерна.

Во-первых, сканирование портов и проверка TLS. Большинство запросов приходит на 443/TCP. Атакующие пытаются установить TLS-соединение, предлагают свои наборы шифров и смотрят, какой сертификат отдаст сервер. Coldframe отдаёт самоподписанный сертификат, и некоторые сканеры сразу помечают хост как «интересный».

Во-вторых, HTTP-запросы к типичным путям. После успешного рукопожатия TLS атакующие пытаются открыть /login, /admin, /setup, /firmware, /api/v1/status. Часто идут сразу с базовой аутентификацией: admin/admin, root/password, user/user.

В-третьих, попытки эксплуатации известных уязвимостей. В логах nginx я вижу запросы с путями вроде /cgi-bin/, /.env, /actuator/env, а также попытки отправки вредоносных тел запросов, рассчитанных на уязвимости в популярных прошивках промышленного оборудования.

Пример фрагмента access.log nginx:

nginx
203.0.113.45 - - [10/Mar/2024:14:22:10 +0300] "GET /login HTTP/1.1" 200 1234 "-" "Mozilla/5.0"
203.0.113.45 - - [10/Mar/2024:14:22:11 +0300] "POST /login HTTP/1.1" 401 567 "-" "curl/7.88.1"
203.0.113.45 - - [10/Mar/2024:14:22:12 +0300] "GET /.env HTTP/1.1" 404 153 "-" "python-requests/2.31.0"

Python-часть Coldframe фиксирует попытки отправки нестандартных команд в эмулируемый протокол. Например, атакующий может прислать JSON с полем command: reboot или попробовать выгрузить конфигурацию через недокументированный эндпоинт.

Что делают атакующие

Когда соединение установлено, поведение делится на два сценария.

В первом сценарии атакующий просто проверяет, живо ли устройство. Он делает один GET-запрос, получает ответ от python-бэкенда и уходит. Это типично для автоматизированных сканеров, которые собирают баннеры и отпечатки TLS-сертификатов. Такие попытки не несут прямого вреда, но показывают, что ханипот попал в выборку сканирования.

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

На практике я видел, как один и тот же IP возвращался через несколько часов с новым набором паролей — это уже не сканер, а человек или цепочка скриптов, которая отрабатывает ответы ханипота.

Для мониторинга таких попыток удобно экспортировать метрики nginx в Prometheus. Если ещё не настроили, можно посмотреть материалы: Интеграция Nginx с Prometheus для мониторинга, Интеграция Nginx с Prometheus: нативная настройка или Настройка экспорта метрик Nginx в Prometheus. Это поможет увидеть всплеск активности ещё до того, как кто-то проникнет в реальную сеть.

Важное наблюдение: атакующие редко обращают внимание на самоподписанный сертификат. Они не проверяют цепочку доверия, им достаточно, что порт открыт и отвечает что-то похожее на веб-интерфейс. Это говорит о том, что для автоматизированных атак важен не сертификат, а доступность сервиса.

Если мы посмотрим на логи с практической точки зрения, то большинство попыток подключения — это шум. Реальная угроза начинается, когда сканирование сменяется подбором паролей или попытками эксплуатации. Именно на такие события стоит настраивать алерты.

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

Как развернуть свой ханипот

Как развернуть свой ханипот

Холодильные контроллеры в супермаркетах редко обновляются. Они работают годами на встроенном веб-интерфейсе с самоподписанным сертификатом, паролем по умолчанию и без какого-либо мониторинга со стороны службы безопасности. Именно это делает их привлекательной мишенью. Coldframe воспроизводит такое устройство: Python-приложение эмулирует веб-интерфейс контроллера холода, а Nginx терминирует TLS и раздаёт сертификат, который выглядит достаточно правдоподобно, чтобы сканер или человек задержался на странице.

Самоподписанный сертификат на таком оборудовании — как замок на двери кладовой, который открывается от любого ключа из подсобки. Для атакующего это сигнал, что устройство слабо защищено и стоит потратить на него несколько минут.

Требования к серверу

Для Coldframe не нужен мощный сервер. Я запускаю свой экземпляр на виртуалке с одним ядром и 512 МБ оперативной памяти — этого хватает с запасом. С практической точки зрения, это потолок, а не минимум. Главное, чтобы машина была доступна из интернета и находилась в изолированном сегменте. Во-первых, ханипот по определению притягивает атакующий трафик. Во-вторых, не стоит размещать его в той же VLAN, где лежат рабочие станции или настоящие контроллеры.

Минимальный набор:

  • ОС Linux — Debian 12 или Ubuntu 22.04 LTS. Я использую Debian, потому что пакеты стабильнее, а systemd ведёт себя предсказуемо.
  • Python 3.11 или новее.
  • Nginx для терминации TLS и проксирования запросов на бэкенд.
  • Публичный IPv4-адрес и открытые порты 80 и 443.
  • Доменное имя и TLS-сертификат. Можно взять бесплатный в Let's Encrypt, а можно сгенерировать самоподписанный — в контексте ханипота это даже ближе к реальности, потому что дешёвое промышленное оборудование часто работает именно с такими сертификатами.

Если планируете собирать метрики о попытках подключения, настройте экспорт логов Nginx в Prometheus. Я описывал настройку нативного экспорта метрик в отдельной статье — она пригодится, если хотите видеть не только сырые логи, но и графики активности сканеров.

Запуск и проверка

Сначала разворачиваем бэкенд на Python. Предположим, код Coldframe лежит в /opt/coldframe. Установите зависимости и создайте системного пользователя, от которого будет работать приложение:

bash
sudo useradd --system --no-create-home --shell /usr/sbin/nologin coldframe
sudo mkdir -p /opt/coldframe
sudo chown coldframe:coldframe /opt/coldframe

Клонируем репозиторий (или копируем файлы вручную, если собираете образ сами):

bash
sudo -u coldframe git clone https://example.com/coldframe.git /opt/coldframe
cd /opt/coldframe
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Далее конфигурируем Nginx. Он будет принимать TLS-соединения на 443-м порту и передавать запросы на локальный порт Python-приложения, например 8080. Сертификат и ключ кладем в /etc/nginx/ssl/.

nginx
server {
    listen 80;
    server_name coldframe.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name coldframe.example.com;

    ssl_certificate     /etc/nginx/ssl/coldframe.example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/coldframe.example.com.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Проверяем конфиг и перезагружаем Nginx:

bash
sudo nginx -t
sudo systemctl reload nginx

Теперь поднимаем сам Coldframe. Я предпочитаю systemd — это даёт предсказуемость: если процесс упадёт, systemd перезапустит его, а в журнале будет видно, почему. Создаём файл сервиса:

ini
[Unit]
Description=Coldframe honeypot
After=network.target

[Service]
Type=simple
User=coldframe
Group=coldframe
WorkingDirectory=/opt/coldframe
ExecStart=/opt/coldframe/.venv/bin/python app.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
bash
sudo cp coldframe.service /etc/systemd/system/coldframe.service
sudo systemctl daemon-reload
sudo systemctl enable --now coldframe

Проверяем, что всё работает. Сначала локально:

bash
curl -sk https://127.0.0.1/

Ключ -k отключает проверку сертификата — полезно при самоподписанном сертификате, но не используйте его в продакшене вне ханипота. Если в ответе пришла HTML-страница с формой авторизации или данными о температуре камер, значит бэкенд отвечает.

Затем проверяем извне. Откройте https://coldframe.example.com в браузере или выполните:

bash
curl -I https://coldframe.example.com

Посмотрите логи Nginx и самого приложения, чтобы убедиться, что запросы доходят:

bash
sudo tail -f /var/log/nginx/coldframe.access.log
sudo journalctl -u coldframe -f

Первые попытки подключения обычно появляются в течение нескольких часов после того, как запись A попала в DNS. Это будут автоматические сканеры — они пробуют стандартные пароли, ищут известные уязвимости в прошивках холодильных контроллеров и пытаются скачать конфигурационные файлы. Все такие события фиксируются в логах, и именно их мы будем разбирать в следующей части статьи. Если мы посмотрим на логи через неделю, там будут сотни запросов к несуществующим страницам.

Если нужно собрать метрики о количестве попыток взлома, подключите экспорт логов Nginx в Prometheus — в связанных материалах ниже есть три варианта настройки, от нативной до интеграции через сторонние экспортеры.

Поделиться:TelegramX / TwitterVK

Читайте также