Traefik: заголовки безопасности, ограничение запросов и доступ через middleware

0
5
Обложка статьи: Traefik: заголовки безопасности, ограничение запросов и доступ через middleware

Если перед сервисами стоит Traefik, защитные настройки удобнее задавать в нём: одни и те же правила для всех приложений, без правки каждого. Заголовки безопасности, ограничение частоты запросов, закрытие административных путей по адресам и паролю описываются обработчиками (middleware) и подключаются к маршрутам. Ниже конфигурация, которую можно скопировать, и проверка результата командами curl с реальными ответами.

Статья опирается на логику направления «Сетевая безопасность» из методики зрелости Группы Сбер (источник); это методика для крупных компаний, мы используем её как ориентир и пересказываем своими словами. Конфигурация проверена на Traefik 3.7 в одноразовом контейнере с тестовым сервером nginx за ним, без доступа к рабочим службам. Синтаксис различается между мажорными версиями Traefik (например, ipAllowList появился в третьей версии вместо ipWhiteList): сверяйте с документацией вашей версии. Настройка заголовков на самом веб-сервере: безопасная настройка nginx.

Что должно получиться

Уровень Что это значит на практике
2. Гигиенический Публичные сервисы защищены от типовых атак, доступ к административным интерфейсам ограничен, правила пересматриваются

Критерии сформулированы нами по мотивам методики, это ориентир, а не оценка соответствия.

Статическая конфигурация

Файл traefik.yml: точка входа, провайдер из каталога файлов с отслеживанием изменений, журнал доступа.

# /etc/traefik/traefik.yml: статическая конфигурация (пример для проверки)
entryPoints:
  web:
    address: ":80"
providers:
  file:
    directory: /dynamic
    watch: true
api:
  dashboard: false
accessLog: {}
log:
  level: INFO

В рабочей установке добавляются точка входа websecure с TLS (сертификаты Let’s Encrypt), перенаправление с HTTP на HTTPS и отключённый или защищённый дашборд. Здесь для проверки используется открытый HTTP внутри тестовой сети.

Маршруты и middleware

Файл /dynamic/app.yml (динамическая конфигурация: Traefik перечитывает его без перезапуска). Адрес сервиса, разрешённую сеть и хэш пароля замените своими: хэш создаётся командой openssl passwd -apr1 'ПАРОЛЬ', при записи в Docker Compose символы $ нужно удваивать.

# /dynamic/app.yml: маршруты и промежуточные обработчики (middleware)
http:
  routers:
    app:
      rule: "Host(`example.com`)"
      entryPoints: [web]
      service: app
      middlewares: [secure-headers, rate-limit]
    admin:
      rule: "Host(`example.com`) && PathPrefix(`/admin`)"
      priority: 100
      entryPoints: [web]
      service: app
      middlewares: [admin-only, admin-auth, secure-headers]
  services:
    app:
      loadBalancer:
        servers:
          - url: "http://backend:80"
  middlewares:
    secure-headers:
      headers:
        contentTypeNosniff: true
        customFrameOptionsValue: "SAMEORIGIN"
        referrerPolicy: "strict-origin-when-cross-origin"
        permissionsPolicy: "geolocation=(), microphone=(), camera=()"
        stsSeconds: 31536000
        forceSTSHeader: true
        customResponseHeaders:
          X-Powered-By: ""
          Server: ""
    rate-limit:
      rateLimit:
        average: 5
        burst: 10
        period: 1s
    admin-only:
      ipAllowList:
        sourceRange:
          - "203.0.113.0/24"
    admin-auth:
      basicAuth:
        users:
          - "admin:$apr1$ХЭШ_ИЗ_openssl_passwd"
Элемент Что делает
Маршрут app Весь трафик для example.com с заголовками безопасности и ограничением частоты
Маршрут admin Путь /admin: только разрешённые адреса, затем пароль, затем заголовки; высокий priority, чтобы он сработал раньше общего маршрута
secure-headers Заголовки X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, Strict-Transport-Security; пустые значения Server и X-Powered-By удаляют эти заголовки из ответа
rate-limit В среднем 5 запросов в секунду с адреса, всплеск до 10
admin-only Разрешает доступ только из указанной сети (в Traefik 3 это ipAllowList)
admin-auth Пароль через basicAuth (подходит для небольшой команды; для серьёзного доступа используйте единый вход и MFA)

Порядок в списке middlewares важен: они выполняются слева направо. Ограничение по адресу ставьте раньше пароля, чтобы не давать постороннему возможность подбирать его.

Проверка

В тесте Traefik стоял по адресу контейнера, а запросы шли с заголовком Host: example.com.

Заголовки

curl -sI -H "Host: example.com" http://АДРЕС_TRAEFIK/

Результат: статус 200, заголовки Permissions-Policy, Referrer-Policy, Strict-Transport-Security: max-age=31536000, X-Content-Type-Options: nosniff, X-Frame-Options: SAMEORIGIN. Заголовков Server и X-Powered-By в ответе нет, хотя тестовый сервер nginx их отправляет. Параметр forceSTSHeader заставляет отправлять HSTS и по HTTP: в рабочей среде при TLS он не нужен.

Неизвестное имя

curl -s -o /dev/null -w "%{http_code}\n" -H "Host: other.example" http://АДРЕС_TRAEFIK/

Результат: 404. Traefik не отдаёт сервис по чужому имени: такой ответ удобен как «глухой» ответ на запросы по адресу без имени.

Ограничение частоты

for i in $(seq 1 40); do curl -s -o /dev/null -w "%{http_code}\n" -H "Host: example.com" http://АДРЕС_TRAEFIK/; done | sort | uniq -c

Результат из 40 быстрых запросов: 12 ответов 200 и 28 ответов 429. Первые запросы уместились во всплеск (10) и среднюю скорость, остальные получили 429 Too Many Requests. Для обычных посетителей лимит в 5 запросов в секунду достаточен, для страниц с большим числом ресурсов поднимите значения. Источником адреса считается адрес соединения; за внешним прокси или CDN настройте определение настоящего адреса клиента (параметры ipStrategy и доверенные адреса), иначе лимит распространится на всех посетителей сразу.

Административный путь

Условие Результат
Адрес клиента не входит в разрешённую сеть 403 (даже с правильным паролем)
Сеть разрешена (изменили sourceRange), пароль не передан 401
Сеть разрешена, пароль неверный 401
Сеть разрешена, пароль верный Запрос дошёл до сервиса (в тесте ответ 404, так как на тестовом сервере страницы /admin/ нет: это ответ сервиса, а не защиты)

Изменение файла динамической конфигурации применилось без перезапуска Traefik за несколько секунд (провайдер файлов с watch: true).

Применение на рабочем Traefik

  1. Добавьте файл middleware в каталог динамической конфигурации; подключайте их к существующим маршрутам постепенно, начиная с заголовков.
  2. Для маршрутов, заданных метками контейнеров Docker, подключение выглядит как traefik.http.routers.ИМЯ.middlewares=secure-headers@file: middleware из файла доступны под суффиксом @file.
  3. Включайте rateLimit и ipAllowList осторожно: ошибка может отрезать вас или пользователей. Держите запасной доступ и проверяйте правила изнутри и снаружи.
  4. Следите за журналом доступа Traefik: он должен попадать в систему сбора: сбор логов, Fail2ban по журналам.
  5. Изменения оформляйте через карточку: управление изменениями.

Заголовки безопасности можно задавать и в Traefik, и в самом приложении, но не в двух местах с разными значениями: определите, где источник истины.

Диагностика

Симптом Причина и что делать
Ответ 404 на нужный адрес Не совпало правило маршрута (имя, путь, точка входа). Проверьте rule и entryPoints
Middleware не применяется Не указан в middlewares маршрута или неверное имя. Для файлового провайдера в метках используйте имя@file
Для всех посетителей ответ 429 За прокси виден один адрес. Настройте ipStrategy и доверенные источники заголовка с настоящим адресом
Административный путь открыт всем Маршрут общий перехватывает путь. Задайте priority выше у маршрута admin
Ошибка в журнале Traefik при чтении файла Синтаксис YAML или устаревшее имя параметра для вашей версии (ipWhiteList и ipAllowList). Смотрите журнал запуска и документацию версии
Хэш пароля не работает в Compose Знак $ нужно удваивать ($$) в файлах Compose

Где это в модели зрелости

Материал относится к направлению «Сетевая безопасность» (материалы направления, карта зрелости). Уровень 2 требует управляемого периметра и защиты публичных сервисов; централизованные middleware на входе дают единый набор правил для всех приложений.

Как проверить

  1. В ответах всех публичных маршрутов есть заголовки безопасности, заголовки Server и X-Powered-By отсутствуют.
  2. Ограничение частоты срабатывает при быстрой серии запросов и не блокирует обычного посетителя.
  3. Административные пути недоступны вне разрешённых адресов и требуют пароля или единого входа.
  4. Журнал доступа Traefik собирается и разбирается; изменения конфигурации идут через карточки изменений.

Источники

  • Методика оценки уровня зрелости кибербезопасности компании, Группа Сбер: sberbank.ru.
  • Документация Traefik: HTTP middlewares (headers, rateLimit, ipAllowList, basicAuth), файловый провайдер: doc.traefik.io.
  • OWASP Secure Headers Project: owasp.org. Международная практика, не российский норматив.

Оставьте свой ответ