Локальная модель — это крепость. Зачем открывать ворота?
Ты запустил Llama 3.2 на своем сервере. Настроил, поигрался, всё работает. И тут возникает мысль: "А что если подключиться с телефона? Или дать доступ коллеге?" Звучит логично. Пока не понимаешь, что твой сервер теперь видят все желающие из интернета.
Открыть порт Ollama (11434) напрямую в интернет — это как оставить ключи от квартиры в двери. Первый же сканер портов найдет твою модель за 5 минут.
В 2025 году исследователи из Stanford обнаружили 47 тысяч открытых экземпляров Ollama в интернете. Большинство — без пароля. Представь, что кто-то может:
- Использовать твои GPU-ресурсы для майнинга (да, такое бывает)
- Тренировать свои модели на твоём железе
- Через твою модель атаковать другие системы
- Просто сломать сервер DDoS-ом
Но есть способ сделать это безопасно. Не идеально — идеальной безопасности не существует. Но достаточно, чтобы спать спокойно.
План: как не стать жертвой собственной гениальности
Мы пойдем по пути максимальной паранойи. Потому что в безопасности лучше перебдеть. Наша архитектура будет выглядеть так:
| Слой | Что делает | Зачем нужно |
|---|---|---|
| VPN (WireGuard) | Шифрованный туннель | Скрыть сервер от интернета |
| Nginx (reverse proxy) | Проксирование и фильтрация | Аутентификация, rate limiting |
| Ollama с TLS | Локальная модель | Шифрование трафика между серверами |
1 WireGuard: стройм туннель, а не дыру в стене
WireGuard — это не просто VPN. Это современный протокол, который проще настраивать, чем OpenVPN, и работает быстрее. Особенно важно для LLM, где каждый миллисекунд на счету.
Первая ошибка: ставить WireGuard на тот же сервер, где работает Ollama. Нет. Ставим на отдельную виртуалку или контейнер. Если атакующий пробьет VPN, он упрется в следующий слой защиты.
# Устанавливаем WireGuard на Ubuntu 24.04 (актуально на 2026 год)
sudo apt update
sudo apt install wireguard wireguard-tools
# Генерируем ключи
wg genkey | tee privatekey | wg pubkey > publickey
Конфиг сервера выглядит так:
# /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <ваш_приватный_ключ>
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# Разрешаем доступ только к порту Ollama (11434)
PostUp = iptables -A FORWARD -i wg0 -d 192.168.1.100 -p tcp --dport 11434 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -d 192.168.1.100 -p tcp --dport 11434 -j ACCEPT
[Peer]
PublicKey = <публичный_ключ_клиента>
AllowedIPs = 10.0.0.2/32
2 Nginx как телохранитель: не просто прокси
Многие ставят nginx как простой прокси. Ошибка. Nginx должен быть полноценным шлюзом безопасности.
Вот как НЕ надо делать:
# ПЛОХОЙ пример - дыра вместо защиты
server {
listen 443 ssl;
location / {
proxy_pass http://localhost:11434;
}
}
А вот правильная конфигурация:
# /etc/nginx/sites-available/ollama-secure
# Базовые настройки безопасности
server_tokens off;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
# Rate limiting - критически важно для LLM!
limit_req_zone $binary_remote_addr zone=ollama_limit:10m rate=10r/m;
limit_req_status 429;
server {
listen 443 ssl;
server_name your-domain.com;
# TLS 1.3 только
ssl_protocols TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# Сертификаты от Let's Encrypt (актуально в 2026)
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
# Базовая аутентификация
auth_basic "Ollama API";
auth_basic_user_file /etc/nginx/.htpasswd;
location /api/ {
# Ограничение запросов: 10 в минуту с одного IP
limit_req zone=ollama_limit burst=20 nodelay;
# Таймауты для долгих ответов LLM
proxy_read_timeout 300s;
proxy_connect_timeout 75s;
# Заголовки безопасности
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;
# Только POST запросы к API
limit_except POST {
deny all;
}
proxy_pass http://localhost:11434;
}
# Блокируем всё остальное
location / {
return 403;
}
}
Создаем файл с паролями:
# Устанавливаем утилиту для генерации паролей
sudo apt install apache2-utils
# Создаем пользователя
sudo htpasswd -c /etc/nginx/.htpasswd username
Rate limiting (10 запросов в минуту) — это не прихоть. Без него один скрипт может положить твой сервер за 5 секунд. Особенно с большими моделями типа Llama 3.2 70B.
3 Ollama: настраиваем, а не просто запускаем
Ollama по умолчанию слушает на всех интерфейсах. Это опасно. Меняем конфигурацию:
# Создаем конфиг для systemd
sudo nano /etc/systemd/system/ollama.service.d/override.conf
[Service]
# Запускаем только на localhost
ExecStart=
ExecStart=/usr/local/bin/ollama serve --host 127.0.0.1
# Ограничиваем ресурсы
MemoryMax=32G
CPUQuota=200%
# Перезагружаем конфигурацию
sudo systemctl daemon-reload
sudo systemctl restart ollama
Проверяем, что Ollama слушает только локально:
sudo netstat -tlnp | grep 11434
# Должно быть: 127.0.0.1:11434
Аутентификация: не только логин и пароль
Базовая аутентификация в nginx — это хорошо, но недостаточно. Добавляем OAuth2 через oauth2-proxy:
# docker-compose.yml для oauth2-proxy
oauth2-proxy:
image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0
container_name: oauth2-proxy
restart: unless-stopped
ports:
- "4180:4180"
environment:
- OAUTH2_PROXY_PROVIDER=github # или google, microsoft
- OAUTH2_PROXY_CLIENT_ID=ваш_client_id
- OAUTH2_PROXY_CLIENT_SECRET=ваш_client_secret
- OAUTH2_PROXY_COOKIE_SECRET=секрет_для_cookie
- OAUTH2_PROXY_EMAIL_DOMAINS="your-domain.com"
- OAUTH2_PROXY_UPSTREAMS=http://nginx:443
- OAUTH2_PROXY_SKIP_PROVIDER_BUTTON=true
volumes:
- ./oauth2-proxy.cfg:/etc/oauth2-proxy.cfg:ro
Теперь nginx перенаправляет все запросы на oauth2-proxy, который проверяет авторизацию через GitHub/Google. Только после успешной аутентификации запрос попадает к Ollama.
Мониторинг и логи: знать, кто и что делает
Без логов ты слеп. Настраиваем централизованный сбор логов:
# Устанавливаем Loki и Promtail
curl -fsSL https://raw.githubusercontent.com/grafana/loki/main/production/docker-compose.yaml -o docker-compose-loki.yaml
docker-compose -f docker-compose-loki.yaml up -d
# Конфиг Promtail для nginx
sudo nano /etc/promtail/config.yaml
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://localhost:3100/loki/api/v1/push
scrape_configs:
- job_name: nginx
static_configs:
- targets:
- localhost
labels:
job: nginx
__path__: /var/log/nginx/access.log
pipeline_stages:
- regex:
expression: '^(?P\S+) \S+ \S+ \[(?P[^\]]+)\] "(?P\S+) (?P\S+) (?P\S+)" (?P\S+) (?P\S+) "(?P[^"]*)" "(?P[^"]*)"'
- labels:
method:
status:
path:
- timestamp:
format: "02/Jan/2006:15:04:05 -0700"
source: timestamp
Теперь все запросы к твоей LLM логируются и доступны в Grafana. Видишь подозрительную активность? Блокируешь IP сразу.
Чего делать категорически нельзя
- Не открывай порт 11434 напрямую в интернет. Даже с паролем. Даже "на пару минут".
- Не используй простые пароли. "admin123" — это приглашение для ботов.
- Не забывай про обновления. Уязвимости в nginx или WireGuard находят регулярно.
- Не давай доступ всем подряд. Каждый новый пользователь — новый вектор атаки.
- Не отключай логирование. Без логов ты не узнаешь об атаке, пока не станет поздно.
Что делать, если всё сломалось
Такое бывает. Настройка сложная, что-то пошло не так. Вот чеклист:
- Проверь, что WireGuard запущен:
sudo wg show - Проверь подключение к VPN с клиента
- Посмотри логи nginx:
sudo tail -f /var/log/nginx/error.log - Убедись, что Ollama отвечает локально:
curl http://localhost:11434/api/tags - Проверь firewall:
sudo ufw status
Если ничего не помогает — откати всё и начни с чистого листа. Иногда это быстрее.
А если хочется проще?
Есть варианты попроще, но менее безопасные:
| Метод | Безопасность | Сложность | Когда использовать |
|---|---|---|---|
| Cloudflare Tunnel | Высокая | Низкая | Для быстрого доступа без настройки VPN |
| Tailscale | Высокая | Очень низкая | Для команды до 5 человек |
| SSH Port Forwarding | Средняя | Средняя | Для временного доступа |
Cloudflare Tunnel — хороший вариант, если не хочешь возиться с VPN. Но помни: твой трафик идет через Cloudflare. Для несекретных моделей подойдет.
Итог: безопасность — это процесс, а не состояние
Ты настроил WireGuard, nginx с аутентификацией, rate limiting, логирование. Отлично. Но это только начало. Раз в месяц проверяй логи на подозрительную активность. Раз в квартал обновляй всё ПО. Раз в полгода меняй пароли.
И помни главное: если ты не можешь объяснить, как работает твоя система безопасности, значит, ты её не понимаешь. А если не понимаешь — рано или поздно её взломают.
Хочешь узнать больше о защите локальных LLM? Почитай наш гайд "Когда ваш ИИ становится утечкой". Там разбираем ещё больше сценариев атак и способов защиты.
И да — если всё это кажется слишком сложным, возможно, твоя модель и не должна быть в интернете. Иногда локальное значит локальное.