Repository navigation
08 Security
| Ресурс | Как защищён |
|---|---|
| Ключ API Fornex | хранится в файле настроек вне корня сайта; не возвращается ни одним маршрутом; не пишется в журнал |
| Пароль панели | только хэш password_hash(); пустой хэш означает «вход запрещён» |
| Токены API | в базе лежат префикс и хэш; полный токен показывается один раз при выпуске |
| Запись в зону | только по id, только через план, снимок перед каждым изменением |
| Журнал | каждая попытка, сухой прогон и отказ с причиной |
-
Сессия. Логин и пароль, cookie
HttpOnly,SameSite=Lax,Secureпри HTTPS. Ограничение попыток: 10 неудач с адреса за 15 минут →429. - Bearer-токен. Для скриптов. По умолчанию «только чтение»; запись — только если токен выпущен с этим правом. Токен проверяется по хэшу, отзыв действует сразу.
CSRF-токен нужен для пишущих запросов из браузера. Скрипту он не нужен: у него нет сессии, которую можно угнать.
AUTO_LOGIN_IP выдаёт сессию без пароля с одного адреса — те же права, что у обычного входа,
включая запись. Механизм существует для рабочего места внутри своей сети.
- Оставляйте пустым, если сеть и адрес не ваши целиком.
- Вход пишется в журнал событием
auth.autologinс авторомpanel:autologin, чтобы «кто вошёл без пароля» не было тайной. - Адрес клиента берётся из соединения;
X-Forwarded-Forучитывается только когда запрос приходит с loopback (nginx на том же хосте), поэтому подделать адрес заголовком нельзя.
Панель — административная поверхность с ключом DNS за ней. Рекомендуется закрыть её списком разрешённых адресов на веб-сервере:
allow 192.0.2.0/24;
allow 2001:db8::/32;
deny all;Ограничения частоты на самом API нет — его ставит веб-сервер.
Правило проекта: имя, тип, место, маска. Значение — никогда.
-
GET /api/metaотдаёт адрес API, таймауты, типовой IP и список типов записей — не ключ. -
GET /api/tokensпоказывает префикс, дату, право записи — не значение. - Журнал хранит действие, объект и итог; ключ и пароль в него не попадают.
- Сообщение об ошибке от Fornex передаётся как есть, но ключ в нём не появляется: он уходит только в заголовке запроса.
Снимок — BIND-файл и JSON с идентификаторами записей. Он не содержит секретов, но содержит
полную зону: поддомены, адреса, TXT-записи подтверждений. Поэтому SNAPSHOT_DIR — вне корня
сайта и не отдаётся по HTTP.
- Перевыпустить ключ в кабинете Fornex (старый отозвать).
- Заменить
FORNEX_API_KEYв файле настроек, перезагрузить PHP-FPM. - Проверить журнал:
php backend/bin/fornex audit --limit=100— искать неожиданные действия. - Проверить выпущенные токены и отозвать лишние:
GET /api/tokens,DELETE /api/tokens/{id}. - Сменить пароль панели: новый
password_hash(), перезапуск PHP-FPM.
| Задача | Право |
|---|---|
| Мониторинг зоны, чтение записей | только чтение |
| Скрипт, который правит записи по расписанию | запись, отдельным токеном |
| Одноразовая проверка | токен с записью, отозванный после |
Токен удобнее держать в файле с правами 600 и передавать в заголовке Authorization.
Приватно, через GitHub → Security → Advisories. Не в issue: публичный отчёт до исправления — это подсказка тому, кто ищет цель. Полные правила — в SECURITY.md.
репозиторий · релизы · Fornex Control · MIT · панель для DNS-зон Fornex