8(800) 222 32 56
Панель управления
AI Инфраструктура Безопасность

NVMe/TCP TLS и DH-HMAC-CHAP: защищаем хранилище весов LLM

NVMe/TCP TLS и DH-HMAC-CHAP: защищаем хранилище весов LLM
Подберите идеальное решение для ваших задач:
в России, США и Нидерландах обеспечат максимальную скорость. Воспользуйтесь всеми преимуществами надежного оборудования. Базовая помощь и техническое обслуживание входят в пакет услуг.
После переноса весов LLM на удалённый NVMe/TCP-том модель загружается, но команда не может доказать, кто подключился к storage и не ушли ли shards по сети открытым текстом. Закрытый VLAN снижает риск, однако не заменяет identity, взаимную аутентификацию и шифрование. В этом production-runbook разберём TLS PSK, DH-HMAC-CHAP, kernel keyring, canary и отрицательные проверки — от первого connect до готовности vLLM. Результатом будет не просто доступный block device, а проверяемая цепочка доверия с понятным rollback.

Готовы перейти на современную серверную инфраструктуру?

В King Servers мы предлагаем серверы как на AMD EPYC, так и на Intel Xeon, с гибкими конфигурациями под любые задачи — от виртуализации и веб-хостинга до S3-хранилищ и кластеров хранения данных.

  • S3-совместимое хранилище для резервных копий
  • Панель управления, API, масштабируемость
  • Поддержку 24/7 и помощь в выборе конфигурации

Создайте аккаунт

Быстрая регистрация для доступа к инфраструктуре

Сначала threat model: что именно защищаем

Узел inference может загрузить модель без единой ошибки, а команда всё равно получит ложное чувство безопасности. Обычный NVMe/TCP переносит блочные команды через IP-сеть; доступный namespace и закрытый VLAN ещё не доказывают ни личность клиента, ни конфиденциальность трафика. Для весов LLM это особенно неприятно: один и тот же удалённый том часто читают несколько дорогих GPU-узлов, поэтому ошибка в trust boundary масштабируется вместе с кластером.

Разделите активы на четыре группы: сами shards модели, tokenizer и config, манифест с pinned revision и секреты подключения. Затем назовите противника. TLS полезен против пассивного перехвата и активной подмены на сетевом пути. DH-HMAC-CHAP проверяет host, а при двусторонней настройке — и controller. Но эти механизмы не спасают от root на inference-узле, скомпрометированного storage target, подменённого файла уже внутри смонтированной ФС или ошибочно опубликованного namespace.

Практический disqualifier простой: если риск находится только «на диске после доставки», начинайте с encryption at rest и контроля целостности, а не с TLS. Если сеть выделенная, но её администрируют несколько команд или трафик проходит через общую фабрику, secure NVMe/TCP уже имеет понятную ценность. Для общего контекста полезен наш материал о NVMe и распределённых файловых системах; здесь мы не повторяем обзор, а строим проверяемую границу доступа для AI workload.

Перед выбором механизма нарисуйте data flow: от model registry и staging host до NVMe target, IP-фабрики, initiator и локального page cache. Отметьте, где байты находятся в покое, где передаются и где исполняются. Веса Safetensors не становятся конфиденциальными только из-за формата, а read-only mount не защищает пакет на проводе. Зато TLS не проверит, что в разрешённом namespace лежит нужная ревизия. Такая карта быстро показывает, какие controls действительно нужны.

Зафиксируйте acceptance criteria до изменения: разрешённый Host NQN подключается только с TLS; неверный PSK и неизвестный host отвергаются; pinned manifest читается; model service проходит probe; после rollback те же проверки возвращаются к baseline. Не включайте в критерии «задержка стала лучше», если change посвящён защите. Производительность измеряется отдельно на одинаковом workload и не должна подменять security outcome.

Не смешивайте identity, authentication и encryption

Самая частая архитектурная ошибка — ставить знак равенства между Host NQN, DH-HMAC-CHAP и TLS. Host NQN — стабильное имя инициатора. Оно участвует в policy и привязке ключей, но само по себе не секрет и не доказательство личности. DH-HMAC-CHAP использует общий секрет, чтобы target проверил host; второй controller secret позволяет mutual authentication. TLS поверх NVMe/TCP шифрует transport и проверяет владение PSK.

Назначьте owner каждому слою. Platform team владеет Host NQN и жизненным циклом узла. Storage team разрешает этот NQN на конкретном subsystem и управляет target-side secrets. Security или secrets team задаёт процедуру выдачи, ротации и отзыва. Владелец model service отвечает за pinned model revision и application probe. Когда один человек «просто кладёт ключ на обе стороны», расследование первой же ошибки превращается в перебор догадок.

Мини-кейс: controller подключился, но vLLM не стартовал. Если evidence показывает корректный TLS identity, чтение namespace проходит, а hash manifest не совпадает, проблема находится выше transport. Если неверный Host NQN получает тот же namespace, наоборот, application logs здесь почти бесполезны: нарушена identity policy. Такое разделение похоже на паспорт, турникет и бронированный коридор — три разных функции, даже если пользователь проходит их подряд.

Какой слой закрывает риск

DH-HMAC-CHAP подтверждает, что к subsystem подключается ожидаемый host; двусторонний режим также проверяет controller.
TLS защищает NVMe/TCP-трафик от чтения и подмены на сетевом пути. Он не заменяет ACL, firewall и шифрование носителя.
LUKS, encryption at rest или защита самого массива нужны отдельно: TLS прекращает действовать после доставки блока на endpoint.
Схема трёх слоёв защиты NVMe/TCP: Host NQN, DH-HMAC-CHAP и TLS между GPU-узлом и хранилищем

Preflight: kernel, nvme-cli, tlshd и статус функций

Secure connect начинайте не с ключа, а с evidence bundle. На дату подготовки статьи latest stable nvme-cli — 2.16; ветка 3.0 доступна как pre-release. В master старые команды gen-tls-key, tls-key, gen-dhchap-key уже помечены deprecated в пользу семейства nvme keys. Поэтому автоматизация обязана проверять локальную версию и её --help, а не копировать синтаксис из случайного gist.

Для kTLS handshake нужен tlshd из ktls-utils. Официальный проект указывает kernel 6.5+ и опции CONFIG_TLS, CONFIG_KEYS, CONFIG_KEYS_REQUEST_CACHE; конкретный дистрибутив может добавлять свои зависимости. Отдельно проверьте CONFIG_NVME_TCP_TLS и host authentication в поставленном kernel. Наличие модуля nvme_tcp не подтверждает TLS.

Сохраните вывод рядом с change ticket. Это не формальность: обновление kernel без подходящего tlshd или смена nvme-cli между major versions способно сломать reconnect после перезагрузки, хотя текущая сессия продолжит жить.

Документируйте support status, а не только номер пакета. Репозиторий nvme-cli releases отделяет stable 2.16 от beta 3.0; документация master может описывать интерфейс, которого ещё нет в вашем дистрибутиве. Проект ktls-utils прямо перечисляет kernel prerequisites для handshake agent. Если один из компонентов vendor backport, просите подтверждение дистрибутива и тестируйте именно его пакет, а не upstream mainline.

bashnvme-secure-preflight.sh
set -eu
uname -r
nvme version
nvme connect --help | sed -n '/tls\|keyring\|chap\|kxchap/p'
nvme keys --help 2>/dev/null || true
modprobe nvme-tcp
systemctl is-active tlshd
nvme show-hostnqn
grep -E 'CONFIG_(TLS|KEYS|KEYS_REQUEST_CACHE|NVME_TCP_TLS|NVME_HOST_AUTH)=' \
  /boot/config-$(uname -r) || true
keyctl show

Preflight перед первым secure connect

Аппаратный preflight Linux GPU-сервера перед включением TLS для NVMe/TCP

Зафиксируйте Host NQN и границы выдачи ключа

Host NQN должен переживать reboot и не зависеть от имени /dev/nvme0. Проверьте /etc/nvme/hostnqn и /etc/nvme/hostid, занесите значения в inventory, а на target разрешите только нужную пару host–subsystem. Копирование образа VM вместе с Host NQN создаёт клон личности: новый inference-узел может получить доступ, предназначенный старому.

Перед изменением соберите baseline: список fabrics controllers, topology, разрешённые subsystem NQN, keyring и revision модели. Номера controller могут измениться после reconnect, поэтому связывайте наблюдения с NQN, transport address и namespace identifier. Owner должен уметь ответить на два вопроса: какой host сейчас предъявляет этот NQN и какой model service имеет право читать этот namespace?

Для dedicated GPU-сервера удобно выдавать отдельную identity на физический узел и отдельный subsystem для production-моделей. Для временного canary используйте другую identity и read-only копию или тестовый namespace. Не расширяйте ACL production namespace только ради проверки. Это тот самый negative control: соседний, неразрешённый Host NQN обязан получить отказ.

Такая дисциплина поддерживает и LLMOps: pinned model revision остаётся прикладной идентичностью, а Host NQN — инфраструктурной. Подробнее о версиях и rollback модели мы писали в руководстве по жизненному циклу LLM в production.

Где хранить секрет

Выделенный inference-сервер со стабильной Host NQN identity и отдельным защищённым storage subsystem

TLS PSK: keyring вместо секрета в командной строке

NVMe/TCP TLS использует pre-shared key, связанный с Host NQN и Subsystem NQN. В Linux key material должен жить в kernel keyring, а tlshd получает его во время handshake. Конфигурация хранит ссылку или identity, а не должна превращаться в склад PSK. Это важнее эстетики: секрет в аргументах виден через process inspection, попадает в shell history и нередко в CI logs.

Генерацию выполняйте командой именно вашей версии. Для stable 2.16 доступны legacy-команды, тогда как 3.0 pre-release переводит управление в nvme keys. Сначала откройте локальный man page, сгенерируйте PSK на доверенном owner-host, импортируйте его в выделенный keyring и только затем добавляйте connection config. Не вставляйте реальное значение в ticket или unit file.

После загрузки проверьте не содержимое ключа, а его presence, type, description/identity и permissions. Доступ к keyring должен иметь процесс handshake, но не model service. Это уменьшает blast radius: vLLM читает блоки модели, однако не получает право экспортировать transport credential.

Официальный design document linux-nvme предупреждает ещё об одной границе: TLS key умеет ссылаться на keyring, а DH-CHAP secret в новом INI-дизайне пока остаётся literal. Поэтому не переносите один и тот же storage credential между hosts и заранее определите срок жизни. Ключ без владельца и даты отзыва — уже технический долг, даже если шифрование работает.

Официальный design document libnvme разделяет authentication и encryption и описывает default keyring .nvme. Используйте этот источник для модели данных, но не считайте незавершённый INI-интерфейс обещанием вашего stable package. Надёжная автоматизация сначала валидирует capabilities, затем импортирует key и лишь после этого меняет connection profile. При сбое она должна остановиться до disconnect старой рабочей сессии.

В inventory храните не secret, а fingerprint или key identity, серийный номер, Host NQN, Subsystem NQN, владельца, дату выдачи и deadline отзыва. Для incident response этого достаточно, чтобы понять, какой credential затронут. Payload остаётся в secrets channel и kernel keyring. Ротация без такого реестра почти неизбежно оставляет старые PSK на части inference-узлов.

bashinspect-nvme-keyring.sh
# Синтаксис генерации зависит от nvme-cli; сначала смотрим локальную справку.
nvme version
nvme gen-tls-key --help 2>/dev/null || true
nvme keys gen-tls --help 2>/dev/null || true

# После импорта проверяем метаданные, не печатая payload секрета.
keyctl show
keyctl list @s | sed -n '/NVMe/p'
systemctl status tlshd --no-pager
Жизненный цикл TLS PSK: генерация, kernel keyring, handshake, ротация и отзыв

DH-HMAC-CHAP: включайте mutual auth осознанно

Односторонний DH-HMAC-CHAP доказывает target, что подключается host с нужным секретом. Это блокирует случайный или чужой initiator, даже если он знает адрес и NQN subsystem. Двусторонний режим добавляет controller secret и позволяет host проверить storage endpoint. Для фабрики, где маршруты или DNS могут меняться, mutual auth закрывает важную дыру в доверии.

Не путайте название протокола и текущий CLI. В исходниках nvme-cli master legacy gen-dhchap-key переименовывается в nvme keys gen-kxchap; прежние connection options также получают kxchap-* spelling. На stable-системе может быть только старое имя. Помечайте эту развилку в runbook и проверяйте доступные flags на каждом образе.

Production-ограничение здесь жёсткое: если ваша конфигурация требует literal DH-CHAP secret в world-readable файле, gate должен завершиться FAIL. Исправьте permissions и способ provisioning либо ограничьтесь TLS PSK, пока secrets story не станет приемлемой. «Функция поддерживается» не означает «её безопасно включать в данном дистрибутиве».

Начните с canary host и тестового subsystem. Положительный тест: правильный host secret подключается. Отрицательные: неверный secret не подключается; разрешённый host не принимает controller с неверным mutual secret; подключение без TLS отвергается policy. Каждый отказ должен быть виден в host journal и target audit, иначе on-call не отличит атаку от опечатки.

Какое доказательство считать достаточным

Controller connected означает только наличие транспортной сессии. Это ещё не доказывает нужный key identity и не гарантирует чтение модели.
Чтение контрольного файла доказывает доступ к namespace и файловой системе, но не корректность model revision.
Успешный deterministic probe к vLLM с ожидаемым model identity завершает gate. Сравнивайте его с тем же probe до изменения.
Двусторонняя DH-HMAC-CHAP-аутентификация между GPU-хостом и NVMe/TCP-контроллером

Secure connect и effective-state gate

Connection config должен описывать stable identities, transport address и security policy. Не привязывайте секрет к конкретному номеру controller. В свежем INI-дизайне linux-nvme параметры безопасности задаются на уровне Host или Subsystem, а отдельные controller = строки описывают пути. Но эта конфигурация относится к развивающейся ветке: для stable distribution используйте поддерживаемый им формат и nvme-stas/systemd integration.

После connect соберите три вида доказательств. Static state: нужный subsystem и namespace появились у ожидаемого Host NQN. Transport state: kernel и tlshd не сообщают fallback или handshake error. Data-path test: чтение контрольного immutable-файла проходит через агрегированное устройство. Само наличие /dev/nvmeXnY недостаточно.

Не запускайте destructive benchmark на production weights. Для canary достаточно заранее подготовленного файла с manifest hash и ограниченного read. Если storage team предоставляет два пути, TLS и authentication должны быть включены на каждом; один незашифрованный путь обнуляет смысл change.

Проверьте сетевую границу отдельно. Firewall должен разрешать target port только от storage interfaces, routing не должен неожиданно уводить трафик через management-сеть, а MTU и offload меняются независимо от TLS rollout. Packet capture допустим на лабораторном стенде как отрицательное доказательство: после secure connect в захвате не должно быть читаемого payload блоков. Но отсутствие читаемой строки не заменяет проверку negotiated security state и target policy.

Если используется multipath, сначала докажите безопасность одного пути, затем второго и только после этого тестируйте failover. Иначе ошибка соединяет сразу две переменные. У каждого пути должны совпадать Host NQN, Subsystem NQN и security requirement; различаться могут адрес и интерфейс. После отказа пути повторите application probe, а не ограничивайтесь восстановлением controller.

bashverify-secure-nvme.sh
set -eu
nvme list
nvme list-subsys
journalctl -u tlshd -b --no-pager | tail -n 100
journalctl -k -b --no-pager | grep -E 'nvme|TLS|auth' | tail -n 150

# MODEL_MOUNT и MANIFEST задаются в окружении canary.
test -r "$MODEL_MOUNT/$MANIFEST"
sha256sum -c "$MODEL_MOUNT/$MANIFEST"
findmnt -no SOURCE,TARGET,OPTIONS "$MODEL_MOUNT"

От блока к модели: immutable mount и vLLM probe

Storage gate заканчивается не на sha256sum. Model service должен прочитать pinned revision, загрузить tokenizer и weights и ответить на известный probe. Актуальная документация vLLM принимает в --model имя либо локальный путь; именно локальный путь на защищённом mount делает связь со storage gate явной. Не включайте --trust-remote-code без отдельного review: transport encryption не делает чужой Python-код безопасным.

Смонтируйте model volume read-only для service account, запретите старт до secure connect и проверки manifest. Не полагайтесь только на network-online.target: он сообщает о готовности менеджера сети, а не о наличии конкретного NVMe namespace, mount или корректного ключа. В unit chain нужен отдельный oneshot gate, после которого стартует vLLM.

Application probe должен быть одинаковым до и после change: тот же model revision, tokenizer, короткий deterministic request и критерий готовности API. Мы не обещаем, что TLS ускорит inference — он может добавить CPU cost на I/O path. Задача canary состоит в том, чтобы подтвердить отсутствие неприемлемой регрессии на вашей сети и CPU, не выдумывая универсальный benchmark.

Если строите полный private AI endpoint, сопоставьте этот storage gate с gateway, auth и quotas из статьи про Private AI API на своих серверах. Защищённые weights — только один слой сервиса.

Официальная CLI-документация vLLM называет --model именем или путём и отдельно предупреждает о рисках локального media access и remote code. Pinning требуется на двух уровнях: файловый manifest фиксирует байты, а deployment config фиксирует путь и параметры loader. Если symlink current может переключиться без change record, storage transport остаётся защищённым, но воспроизводимость релиза теряется.

inivllm-secure-storage.service
[Unit]
Description=vLLM with verified remote model storage
After=network-online.target nvme-model-storage.service
Requires=nvme-model-storage.service
ConditionPathIsReadWrite=!/srv/models

[Service]
User=vllm
ExecStartPre=/usr/local/sbin/verify-model-manifest /srv/models/revision
ExecStart=/opt/vllm/bin/vllm serve /srv/models/revision --load-format safetensors
Restart=on-failure
NoNewPrivileges=yes
ProtectSystem=strict
ReadOnlyPaths=/srv/models

[Install]
WantedBy=multi-user.target
Цепочка проверок от TLS-сессии и чтения блока до manifest и готовности vLLM

Canary, negative controls и ротация без слепого окна

Правильный rollout начинается с нового key identity, а не с удаления старого. Загрузите новый TLS PSK на canary host и target, установите secure connection, пройдите static, data-path и application gates. Только после этого переносите небольшую долю inference workload. Старый ключ остаётся на короткое, заранее ограниченное окно rollback.

Отрицательные тесты обязательны и безопасны, если выполняются на тестовом subsystem: неверный PSK должен сломать handshake; неизвестный Host NQN — получить отказ; отсутствие TLS — не давать тихого plaintext fallback; неправильный pinned revision — останавливать model service до bind порта. Такой набор доказывает границы лучше, чем ещё один успешный connect.

Rollback симметричен rollout. Остановите model service, верните прежний connection profile и key identity, восстановите namespace, повторите manifest и application probe. Не делайте disconnect устройства, пока с него читают процессы: сначала drain, затем unmount, и лишь потом transport changes. Owner каждого шага и stop condition должны быть в runbook.

Ротацию планируйте отдельно для TLS PSK, host authentication secret и controller secret. Одновременная смена всех трёх усложняет attribution. Если canary не подключился, вы должны сразу понимать, сломана identity policy, authentication или TLS handshake.

Canary готов к ротации

Canary-ротация ключа NVMe/TCP с новым и старым путём rollback для inference-сервера

Наблюдаемость: алерт не на шум, а на потерю гарантий

Собирайте события из kernel journal, tlshd, nvme-stas или выбранного orchestrator, target audit и model service. Полезные симптомы: повторяющиеся reconnect, authentication failure, TLS handshake error, исчезновение controller, рост model cold-start time, manifest mismatch и restart loop vLLM. Один счётчик не объяснит инцидент, поэтому связывайте их по Host NQN, Subsystem NQN и deployment revision.

Алерт должен отвечать на вопрос о гарантии. «Controller reconnect» может быть ожидаем во время maintenance. «После reconnect secure application probe не восстановился за принятый SLO» уже требует реакции. Отдельный критический сигнал — успешный plaintext connect там, где policy требует TLS. Его лучше ловить target-side и подтверждать регулярным negative test.

Не отправляйте secrets, key payload или полную командную строку в telemetry. Достаточны key identity, serial, owner, срок действия и результат операции. Для общей архитектуры метрик, логов и алертов пригодится руководство Observability vs Monitoring, но security events NVMe/TCP должны остаться самостоятельным runbook.

После каждого обновления kernel, nvme-cli или ktls-utils повторяйте capability gate на canary. Версионная совместимость здесь — часть availability. Зелёный health model API на старой сессии не доказывает, что следующий reboot сможет заново выполнить TLS handshake.

Итог: защищайте путь модели проверяемыми слоями

Безопасный NVMe/TCP для LLM — это не флаг --tls, а цепочка доказательств. Стабильный Host NQN задаёт identity, DH-HMAC-CHAP ограничивает initiator и при необходимости проверяет controller, TLS защищает сетевой путь, manifest фиксирует model revision, а vLLM probe подтверждает реальную готовность приложения. Каждый слой закрывает свой риск и имеет отдельного owner.

Начните с малого: инвентаризируйте версии и kernel configs, заведите тестовый subsystem, загрузите короткоживущий PSK в keyring и добейтесь предсказуемого отказа с неверным ключом. Затем подключите read-only model revision, пройдите тот же application probe до и после change и отработайте rollback. Если результат воспроизводится, переносите один production canary, а не весь GPU-парк.

Для workloads, где модель читается локально один раз и сеть полностью изолирована, сложность может не окупиться — это нормальный вывод. Но когда несколько выделенных inference-серверов получают ценные weights по общей IP-фабрике, сочетание сильной identity, transport encryption и negative controls превращает скрытое доверие в управляемую инфраструктурную гарантию. Подходящий выделенный сервер и сетевую схему стоит выбирать вместе с threat model; обзор критериев есть в материале о GPU-серверах для машинного обучения.

Memory pressure в LLM-инференсе: cgroup v2, PSI и systemd-oomd
AI

Memory pressure в LLM-инференсе: cgroup v2, PSI и systemd-oomd

Практический runbook для защиты LLM-инференса от дефицита host RAM: PSI, cgroup v2, systemd-oomd, лимиты vLLM, алерты и аварийное восстановление.

NVIDIA CDI для rootless GPU-контейнеров: безопасный запуск LLM inference
AI

NVIDIA CDI для rootless GPU-контейнеров: безопасный запуск LLM inference

Практический runbook: NVIDIA Container Toolkit CDI, rootless Podman и Docker, выбор GPU/MIG, запуск vLLM, hardening, обновления и rollback.

Power cap для GPU в LLM inference: production-runbook без гадания по ваттам
AI

Power cap для GPU в LLM inference: production-runbook без гадания по ваттам

Практический runbook для безопасного ограничения мощности GPU: baseline, canary, DCGM и vLLM-метрики, energy-per-token, rollout и rollback.