Локальный сервер не равен закрытому серверу
«Модель работает у нас, значит доступ к ней уже безопасен» — удобная, но неверная короткая дорога. Локальное размещение отвечает на вопрос, где выполняются вычисления. Оно само по себе не отвечает, кто может отправить запрос, какие методы доступны, сколько GPU-времени разрешено одному клиенту и куда уйдут данные из промпта. Внутрик с радостью протянет сетевой кабель до любого кабинета; кабель не умеет проверять полномочия.
У Ollama локальный API, согласно официальной документации, не требует аутентификации. По умолчанию сервер привязан к 127.0.0.1:11434, поэтому доступен только с самой машины. Переменная OLLAMA_HOST меняет адрес привязки. Перевести сервис на 0.0.0.0 ради доступа из локальной сети технически просто, но именно тогда контроль доступа становится отдельной задачей. Документация Ollama описывает и вариант с обратным прокси; приведённый там пример показывает маршрутизацию, а не готовую политику защиты.
С vLLM картина другая, но вывод тот же. В актуальном разделе Security разработчики прямо предупреждают: параметр --api-key защищает только указанные префиксы API, в частности /v1, /v2, /inference и /cohere. Другие маршруты на том же HTTP-сервере могут оставаться без этой проверки. В документации среди примеров назван /invocations, который также выполняет инференс. Это не повод объявлять любое развёртывание vLLM уязвимым: решают версия, конфигурация и реальная сетевая доступность. Но считать один ключ полной защитой всех функций нельзя.
Что может пойти не так
Первая неприятность — чужой или просто неучтённый клиент занимает очередь. Даже если на сервере нет документов компании, генерация тратит вычисления и задерживает рабочие запросы. OWASP относит отсутствие разумных лимитов к риску неконтролируемого потребления ресурсов API. Для маленькой команды с одной видеокартой это выражается не только в счёте, но и в очереди для сотрудников.
Вторая — смешение полномочий. Сервис, который должен лишь отвечать на запросы приложения, может предоставлять дополнительные технические маршруты: просмотр моделей, операции управления или интеграционные функции. Их состав меняется с версией. Закрывать только известный сегодня путь к чату недостаточно: следующий путь или расширение может пройти мимо проверки. Отсюда правило «разрешённые маршруты по списку», а не «запретим пару опасных».
Третья — неверное ощущение изоляции данных. Сам по себе API модели не равен базе знаний: доступ к закрытым документам появляется через приложение, RAG или инструменты вокруг него. Но если браузер и произвольный внутренний сервис могут напрямую обращаться к модели или к этому приложению, компания теряет единое место проверки пользователя, прав на документы и учёта расхода. CORS ограничивает поведение браузеров, но не подменяет серверную аутентификацию и авторизацию.
Минимальная схема для малого бизнеса
Не обязательно разворачивать новый тяжёлый компонент ради одной модели. Если в инфраструктуре уже есть подходящий шлюз или обратный прокси, используйте его как единственную разрешённую точку входа. Сервер модели оставьте на loopback либо в изолированном внутреннем сегменте; межсетевой экран должен исключить обход шлюза. Когда приложение и модель находятся на разных узлах, защитите транспорт TLS или внутренним защищённым каналом и ограничьте список адресов, которым разрешено соединение.
На шлюзе нужны четыре независимых решения:
- кто вызывает сервис: идентификатор приложения или пользователя, а не один общий ключ в исходном коде всех клиентов;
- что разрешено: только конкретные методы и пути, нужные бизнес-сценарию; остальное запрещено по умолчанию;
- сколько разрешено: размер запроса, максимальный вывод, параллельные запросы, очередь, тайм-аут и лимит на клиента;
- что видно в журнале: время, клиент, модель, длительность, объём и результат без автоматического сохранения всего содержимого промптов.
Например, внутреннему помощнику поддержки может быть нужен только запрос генерации. Ему не требуется маршрут загрузки новых моделей, изменение конфигурации или служебная панель. Если позднее понадобится ещё одна функция, её добавляют отдельно с тестом доступа. У vLLM сама документация рекомендует минимизировать открытые маршруты, применять обратный прокси и ограничивать сетевую поверхность. Это проверяемая настройка, а не обещание модели «вести себя хорошо».
Шлюз не решает вопросы авторизации данных внутри RAG. Там права на документы следует применять до поиска и повторно проверять перед выдачей ответа. Здесь рассматривается более ранняя граница: кто вообще может попасть к вычислительному API. Не смешивайте эти два уровня защиты.
Экономика без выдуманной окупаемости
Нельзя честно назвать универсальную цену «незащищённого порта»: она зависит от GPU, длины контекста, параллелизма и стоимости простоя. Но полезен модельный расчёт. Допустим, нежелательный запрос занимает одну минуту занятого вычислительного ресурса. Тридцать таких запросов означают до 30 минут суммарной работы; при параллельной обработке календарное время и расход памяти будут иными. Это не наблюдение конкретной компании, а способ увидеть, почему лимиты нужны даже в приватной сети.
При выборе контроля считайте не только стоимость шлюза. Учитывайте время администратора на ключи и правила, задержку прокси, журналирование, обновления и тест обхода. Учитывайте также обратную сторону: при слишком строгом лимите сотрудники будут ждать или начнут искать обходной путь. Сначала измерьте обычную нагрузку и её пики, затем задавайте квоты с запасом. Встроенные очереди движка помогают при перегрузке, но не различают авторизованного клиента и случайного соседа по сети.
Проверка за один рабочий день
Инвентаризируйте все адреса и порты модели, контейнерные публикации, прокси и туннели. Убедитесь, что сотрудники обращаются к шлюзу, а прямой адрес модели из их сегмента недоступен. Затем проверьте без секретов и без полноценной генерации: неавторизованный запрос к каждому опубликованному маршруту должен быть отклонён; авторизованный клиент должен видеть только разрешённые операции. Отдельно протестируйте запасной путь и обновление версии, потому что новый маршрут может появиться незаметно.
После этого задайте небольшой лимит на одного клиента и проведите контролируемый тест нагрузки в непроизводственное время. Зафиксируйте задержку нормального запроса, поведение при переполнении очереди и то, какие поля попадают в журнал. Если проверка обнаружила обход шлюза, сначала закройте сетевой путь и только потом расширяйте использование модели. Внутрик может оставаться самым старательным стажёром отдела — просто кабель ему выдаёт человек.
