Files
shop-server/docs/superpowers/specs/2026-05-23-ip-gate-access-control-design.md
T
2026-05-23 10:56:08 +05:00

4.1 KiB
Raw Blame History

IP-gate: ограничение доступа на время разработки

Задача

Сайт доступен на реальном домене (через VPS + NPM + Netbird), но находится в активной разработке/тестировании. Нужно ограничить доступ, не мешая разработке и полному тестированию функционала (включая OAuth и webhook-и).

Решение

IP-whitelist на уровне Fastify (onRequest хук). Только запросы с разрешённых IP проходят. Внешние webhook-и и OAuth callback-и исключены из проверки.

Конфигурация

.env

SITE_ACCESS_IPS=1.2.3.4,5.6.7.8
  • Не задана или пуста — защита отключена
  • IP через запятую, пробелы игнорируются (трим)
  • request.ip возвращает реальный IP клиента благодаря trustProxy: true

Архитектура

Новый плагин: server/src/plugins/ip-gate.js

Регистрируется в server/src/index.js перед всеми маршрутами.

fastify.register(async function ipGate(fastify, opts) {
  fastify.addHook('onRequest', async (request, reply) => {
    // защита выключена
    // путь в исключениях
    // ip в списке
    // иначе 403
  })
})

Логика onRequest

  1. SITE_ACCESS_IPS пуст → return (пропустить)
  2. Путь запроса в списке исключений → return
  3. request.ip есть в SITE_ACCESS_IPSreturn
  4. Иначе → reply.code(403).type('text/html').send(htmlPage)

Исключения

Маршруты, которые должны работать всегда (их вызывают внешние сервисы, а не браузер тестировщика):

Путь Причина
/api/auth/oauth/vk/callback VK OAuth callback
/api/auth/oauth/yandex/callback Yandex OAuth callback
/api/webhooks/yookassa YooKassa payment webhook
/api/admin/notifications/telegram/webhook Telegram webhook

Статика (загружается браузером тестировщика, поэтому тоже проверяется):

  • /uploads/* и /uploads-resized/*не исключаем, блокируются вместе со всем остальным

403-страница

HTML-страница с информацией о магазине и статусе разработки:

  • Название: «Любимый Креатив»
  • Подзаголовок: «Изделия ручной работы: вещи с характером и вниманием к деталям»
  • Сообщение: «Сайт находится в разработке и скоро будет доступен»
  • Показывает IP посетителя (чтобы можно было сообщить для добавления в whitelist)
  • Минимальная стилизация (чистый HTML + inline CSS, без внешних ресурсов)

Точки регистрации

В server/src/index.js:

// после trustProxy, перед маршрутами
await fastify.register(require('./plugins/ip-gate'))

Тестирование

  • Юнит-тесты: server/src/plugins/__tests__/ip-gate.test.js
    • IP в списке → запрос проходит
    • IP не в списке → 403
    • Путь-исключение → проходит с любым IP
    • SITE_ACCESS_IPS не задан → защита выключена
    • Пробелы в списке IP → корректная работа

Включение/выключение

  • Включить: задать SITE_ACCESS_IPS в .env
  • Выключить: удалить SITE_ACCESS_IPS или оставить пустым
  • Перезапуск сервера не требуется если используется node --watch