# Безопасность регистратора доменов требует подтверждения каждого вызова

Если вы дали ИИ-агенту учётные данные API регистратора, это не даёт ему одну цельную возможность. Агент получает несколько несвязанных возможностей, которые оказались за одним секретом: перенаправлять домен, готовить его к переносу, менять людей, получающих уведомления о восстановлении, и изменять цепочку доверия DNSSEC. Безопасность регистратора доменов ломается, когда слой подтверждения считает все эти вызовы взаимозаменяемыми.

Каждый вызов регистратора, который меняет состояние, должен требовать решения, привязанного к точному действию, домену, старому и предлагаемому значению. Человек может одобрить замену nameserver при запланированной миграции, но отклонить снятие блокировки, смену email владельца или удаление DS, сделанные в том же запуске. Одно подтверждение сессии не способно выразить эту разницу.

## Одна учётная запись скрывает несколько границ безопасности

Учётные данные регистратора подтверждают личность, а не намерение человека. Даже когда провайдер предлагает детальные разрешения API, команды часто помещают несколько обязательных операций записи в одну роль, чтобы автоматизация могла завершить задачу. Другие провайдеры выдают широкий токен регистратора. В обоих случаях владение ключом отвечает лишь на вопрос, кто может запросить действие. Оно не отвечает, должно ли именно это изменение произойти сейчас.

Базовые протоколы и не делают вид, будто эти операции равнозначны. RFC 5731, сопоставление доменов EPP для обмена между регистраторами и реестрами, описывает привязки nameserver, контактов, статусы и данные авторизации как отдельные атрибуты домена. Его команда обновления может добавлять и удалять nameserver и контакты, менять владельца, данные авторизации и клиентские статусы. Удобный API может поместить эти операции за одни учётные данные, но состояние в реестре сохраняет различие между ними.

Публичный облачный регистратор показывает то же различие в списке команд. В API Route 53 Domains есть отдельные операции `UpdateDomainNameservers`, `UpdateDomainContact`, `DisableDomainTransferLock`, `AssociateDelegationSignerToDomain` и `DisassociateDelegationSignerFromDomain`. Этот список полезен, потому что называет решения, которые система подтверждения должна сохранить, а не свести к `registrar.write`.

Перед тем как дать агенту доступ к регистратору, я задаю четыре вопроса:

- Может ли этот вызов перенаправить разрешение имён для всего домена?
- Может ли он облегчить последующую кражу или восстановление доступа?
- Может ли он изменить получателей сообщений об управлении или проверке?
- Может ли он заставить валидирующие резолверы отклонять корректные DNS-ответы?

Если два вызова дают разные ответы, для подтверждения это разные действия. Общий API-ключ их не объединяет.

## Смена nameserver передаёт полномочия над всей зоной

Замена nameserver передаёт DNS-полномочия новому набору серверов, поэтому её радиус поражения гораздо больше, чем у редактирования одной записи. RFC 8499 определяет делегирование как добавление родительской зоной набора NS-записей для дочерней зоны. Когда кэши следуют этому делегированию, новые авторитетные серверы могут отвечать за веб-адреса зоны, почтовые обменники, записи обнаружения сервисов и проверочные TXT-записи.

Последняя категория позволяет недооценить риск. RFC 8555 говорит, что ACME-клиент может подтвердить контроль над доменом, разместив TXT-значение в `_acme-challenge`. Оператор, контролирующий делегированную зону, может ответить на эту проверку и запросить сертификаты для имён в домене, если выполняются проверки центра сертификации. Поэтому смена nameserver не сводится к настройке хостинга.

В подтверждении нужно показывать полный старый и новый наборы серверов, а не фразу вроде `update DNS`. Наборы важны, поскольку при миграции серверы часто добавляют до удаления старых, а некоторые API регистратора заменяют весь набор за один вызов. Проверяющий должен видеть, сохраняет ли запрос все нужные серверы, затронуты ли glue-адреса и отвечают ли целевые серверы за зону как авторитетные.

Перед подтверждением опросите каждый предлагаемый сервер напрямую, а не доверяйте рекурсивному кэшу:

```sh
for ns in ns1.new-dns.example ns2.new-dns.example; do
  dig +norecurse +short @"$ns" example.com SOA
  dig +norecurse +short @"$ns" example.com MX
done
```

Исправная проверка возвращает строку SOA от каждого сервера и ожидаемые цели MX. Пустой вывод, разные serial или ответы без авторитетности требуют расследования. Точный план миграции определяет, должны ли serial уже совпадать, но проверяющий не должен одобрять имя сервера, который ещё не ответил за зону.

Запись о подтверждении должна обозначать действие как `nameserver.replace`, включать упорядоченный запрос и нормализованную разницу наборов, а также указывать, меняет ли вызов glue. Не прячьте его внутри общего обновления домена: правдоподобная ошибка агента здесь способна сразу перенаправить все сервисы.

## Снятие блокировки переноса открывает окно

Отключение transfer lock не переносит домен, но убирает один из контролей, который предотвращает перенос. ICANN называет привычную блокировку регистратора `clientTransferProhibited` или похожий статус. RFC 5731 требует отклонить запрос на перенос, пока действует `clientTransferProhibited` или `serverTransferProhibited`.

Это различие важно при проверке. Агенту может действительно понадобиться снять блокировку домена перед плановым переносом, однако неожиданное снятие остаётся опасным, поскольку создаёт полезное предварительное условие для другого участника. Считайте `transfer_lock.disable` отдельным действием и требуйте, чтобы в запросе были указаны целевой регистратор, тикет изменения и ожидаемое время повторной блокировки или завершения. Эти поля не заставляют регистратора выполнить план, но дают проверяющему достаточно контекста, чтобы отклонить необъяснённое снятие блокировки.

Код авторизации - отдельный секрет и отдельное решение. Его получение не должно скрываться внутри подтверждения снятия блокировки. Полезная плоскость управления спрашивает один раз о снятии блокировки и ещё раз о получении или использовании кода авторизации переноса. Если процесс также меняет владельца, порядок важен: Transfer Policy ICANN требует 60-дневную межрегистраторную блокировку после Change of Registrant в предусмотренных случаях, если регистратор не предложил отказаться от неё до изменения и владелец не выбрал этот вариант.

Часто советуют оставить домен заблокированным и поэтому считать автоматизацию регистратора безопасной. Блокировка помогает, но этот совет останавливается слишком рано. Учётные данные, способные снять блокировку, способны убрать и саму защиту. Подтверждение каждого вызова показывает снятие в момент, когда оно важно, тогда как постоянное правило, проверяющее лишь текущий статус блокировки, следующий API-запрос может сделать недействительным.

Включение блокировки обычно менее рискованно и помогает восстановить защиту, но это всё равно запись с рабочими последствиями. Она может остановить законный перенос, который уже идёт. Покажите состояние ожидающего переноса и дайте человеку подтвердить действие, если только процедура реагирования на инцидент явно не разрешает экстренную повторную блокировку.

## Изменение контактов меняет путь восстановления

Обновление контакта владельца или администратора меняет получателя важных уведомлений и может повлиять на возможность переноса. Оно не перенаправляет трафик сразу, поэтому команды нередко ставят его ниже работ с nameserver. Такая оценка игнорирует то, как на практике восстанавливают контроль над доменом.

ICANN советует владельцам поддерживать контактные данные в актуальном состоянии, поскольку регистраторы отправляют письма о защите и управлении. Transfer Policy также связывает Change of Registrant с 60-дневной блокировкой переноса в определённых обстоятельствах. Агент, который меняет email владельца прямо перед запланированным переносом, может задержать работу. Злоумышленник, изменивший доступный контакт, может мешать уведомлениям или будущему восстановлению, в зависимости от процесса регистратора и реестра.

Карточке подтверждения нужна разница по полям. `contact.update` слишком расплывчато, когда запрос одновременно меняет email, телефон, организацию, настройку приватности и личность владельца. Покажите каждое старое и новое значение, отметьте изменяемые роли контактов и укажите, сообщает ли регистратор о возникающем ограничении переноса. Маскирование защищает персональные данные в обычных журналах, но человек, одобряющий чувствительную смену личности, должен видеть достаточно, чтобы узнать предполагаемого получателя.

Не позволяйте агенту решать неудачное обновление контакта повторными изменениями полей, пока API не примет запрос. У реестров разные правила проверки, а для некоторых национальных доменов действуют дополнительные требования. Безопаснее проверить полезную нагрузку, запросить подтверждение окончательной разницы, отправить её один раз и сохранить идентификатор операции провайдера. Если провайдер обрабатывает изменение асинхронно, действие остаётся ожидающим, пока чтение не подтвердит нужное состояние.

Приватность контакта - ещё одно отдельное действие. Изменение видимости приватных данных не равнозначно изменению самого владельца. Проверяющий может принять переключение приватности и отклонить смену владельца, поэтому система подтверждения не должна объединять их лишь потому, что у поставщика одна конечная точка.

## Изменения DNSSEC могут сделать корректные ответы недействительными

Изменение делегирования DNSSEC меняет цепочку, по которой валидирующие резолверы подтверждают подлинность дочерней зоны. RFC 4034 точен: запись DS ссылается на DNSKEY через key tag, algorithm и digest, а DS находится на родительской стороне делегирования. Соответствующий DNSKEY находится в дочерней зоне. API регистратора часто передаёт данные DS в реестр, потому что владелец не может редактировать родительскую зону напрямую.

Неверный nameserver может перенаправить ответы. Неверная DS-запись может заставить резолверы пометить подлинные ответы как bogus. Это другой режим отказа, и проверка ему нужна другая. Удаление DS после обновления кэшей может превратить безопасно делегированную зону в небезопасную. Добавление DS, не совпадающего с опубликованным DNSKEY, может сломать валидацию. Преждевременное удаление старого DS при rollover ключа может оставить без корректной цепочки валидаторы, которые ещё опираются на кэшированные данные.

Подтверждение для `dnssec.ds.add`, `dnssec.ds.replace` и `dnssec.ds.remove` должно показывать key tag, algorithm, digest type, отпечаток digest и подтверждения DNSKEY, полученные от всех авторитетных серверов. Проверяющий также должен видеть, добавляет ли запрос перекрытие на время rollover или за один раз заменяет единственный DS.

Эти команды показывают обе стороны цепочки:

```sh
dig +short example.com DS
dig +short example.com DNSKEY
dig +dnssec example.com A
```

Первый запрос получает DS-данные родительской стороны по обычному пути разрешения. Второй получает набор DNSKEY дочерней зоны. Третий показывает ответ и DNSSEC-записи, используемые для валидации. На пути с валидирующим резолвером во флагах ответа может появиться `ad`, когда резолвер подтвердил данные. Не сводите проверку к совпадению одного числового key tag. Digest и algorithm должны соответствовать нужному DNSKEY, а последовательность развёртывания должна учитывать кэши.

Однокнопочный процесс `enable DNSSEC` у DNS-хостинга может координировать эти детали для человека. Агент, который отдельно использует API регистратора и DNS, не получает эту защиту автоматически. Требуйте предлагаемую последовательность, подтверждение публикации нового ключа и явное подтверждение каждого изменения на стороне родительской зоны.

## Подтверждение должно быть привязано к нормализованному действию

Объект подтверждения должен описывать смысл, а не показывать только сырой HTTP-запрос. URL, названия операций провайдера и формы JSON различаются. Стабильное внутреннее имя действия позволяет проверяющему узнавать одно и то же событие безопасности у разных регистраторов, не делая вид, что провайдеры работают одинаково.

Вот практичная оболочка действия для границы инструментов агента:

```json
{
  "action": "nameserver.replace",
  "domain": "example.com",
  "before": {
    "nameservers": ["ns1.old-dns.example", "ns2.old-dns.example"]
  },
  "after": {
    "nameservers": ["ns1.new-dns.example", "ns2.new-dns.example"]
  },
  "reason": "CHG-1842 registrar migration",
  "evidence": {
    "authoritative_checks": "passed",
    "checked_at": "2026-07-24T14:25:00Z"
  },
  "request_hash": "sha256:..."
}
```

Шлюз должен выводить действие из метода, конечной точки и проверенного тела. Агент не должен выбирать удобную метку действия и при этом отправлять другой запрос. Привяжите подтверждение к каноническому хешу запроса, чтобы агент не получил согласие на один набор nameserver, а не отправил другой. Если асинхронному провайдеру нужен второй вызов для подтверждения операции, классифицируйте и подтверждайте его по тому эффекту, который он закрепляет.

Нормализация также показывает смешанные изменения. RFC 5731 позволяет одной команде обновления домена затронуть nameserver, контакты, статусы и данные авторизации. Если конечная точка регистратора принимает несколько категорий в одной полезной нагрузке, разделите процесс до подтверждения, когда API это позволяет. Когда это невозможно, покажите все действия при подтверждении и примените самое строгое решение. Метка вроде `domain.update` почти ничего не говорит проверяющему.

Отклоняйте запросы без текущего состояния. Без свежего чтения разница может основываться на устаревших предположениях и перезаписать чужое изменение. Используйте токен версии провайдера или условный запрос, если они доступны. Если их нет, прочитайте состояние прямо перед отправкой, сравните нормализованное состояние с одобренным значением `before` и остановитесь при любом расхождении.

## Для чтения и записи нужен разный уровень контроля

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

Публичные DNS-запросы без аутентификации не требуют учётных данных регистратора. С аутентифицированным чтением инвентаря доменов, закрытых контактных данных, кодов переноса, платёжных данных или ожидающих операций нужно обращаться иначе. Чтение сведений о домене может раскрыть персональные контактные данные. Получение кода авторизации сразу создаёт возможность переноса, хотя каталог API может называть его чтением.

Используйте небольшую и понятную таблицу классификации.

Список управляемых доменов и чтение замаскированного статуса обычно можно выполнять с подтверждением сессии, поскольку они раскрывают инвентарь, но не меняют его. Получение кода авторизации переноса требует подтверждения каждого вызова, потому что создаёт секрет, который может сделать перенос возможным.

Замена nameserver, снятие блокировки переноса, изменение контакта владельца или администратора, а также каждое добавление, замена или удаление DS-данных требуют подтверждения каждого вызова, потому что каждое из них меняет контроль или валидацию. Продление зависит от политики: оно стоит денег, но обычно сохраняет контроль, поэтому команда может заранее разрешить его в пределах установленного лимита расходов.

Последний случай намеренно не сводится к одному ответу. Продление имеет финансовые последствия и влияет на жизненный цикл, но его риск отличается от перенаправления или переноса домена. Команды могут заранее разрешать продление в пределах лимита расходов и по-прежнему требовать человека для каждого изменения делегирования. В этом смысл ясных названий действий.

Не используйте только HTTP-метод для классификации. Некоторые API применяют общий POST и для чтения, и для записи. Не используйте и широкую категорию провайдера, например `Write`. Справочник авторизации Route 53 Domains верно указывает замену nameserver, обновление контакта и снятие блокировки переноса как отдельные разрешения, но слою подтверждения всё равно нужны конкретный домен и разница значений.

## Проверяющему нужны доказательства, а не текст агента

Объяснение, сгенерированное агентом, даёт контекст, но не служит доказательством. Подтверждение должно начинаться с независимо собранных фактов: аутентифицированного процесса, точного домена, нормализованного действия, значений до и после и результатов проверок. Причину, указанную агентом, разместите после этих полей.

Для запроса на nameserver соберите авторитетные SOA и проверки важных записей с каждого предлагаемого сервера. Для запроса DS соберите текущие наборы DS родительской стороны и DNSKEY дочерней стороны. Для снятия блокировки соберите текущий статус и сведения об ожидающем переносе. Для изменения контакта покажите изменённые роли и последствия блокировки, заявленные регистратором. Код, собирающий эти доказательства, должен находиться на доверенной стороне границы, потому что агент может случайно пересказать устаревший вывод или не указать неудобное различие.

У подтверждения должен быть срок действия. Разница nameserver, собранная пять часов назад, может уже не описывать текущее состояние. Срок должен быть достаточно коротким, чтобы ограничить расхождение, и достаточно долгим для изучения доказательств. Не копируйте единое число во все процессы: задавайте его по модели конкурентного доступа регистратора и времени реакции команды, а затем отклоняйте запрос, если состояние `before` изменилось.

Пакетное подтверждение безопасно лишь тогда, когда виден каждый элемент и все они однородны. Можно обоснованно подтвердить одну и ту же миграцию nameserver для двадцати припаркованных доменов, если карточка перечисляет каждый домен и проверка прошла для каждого. Объединение смены nameserver, снятия блокировки и обновления контакта в одну кнопку «одобрить миграцию» уничтожает различия, которые нужны проверяющему.

Отказ в подтверждении должен останавливать вызов, а не предлагать агенту перефразировать запрос и повторять его, пока кто-то не нажмёт «да». Сохраняйте отказ вместе с хешем запроса. Существенно изменённый запрос можно направить повторно, но система должна явно показать разницу.

## Проверка входит в состав действия

Успешный HTTP-ответ часто означает, что регистратор принял задачу, а не то, что реестр и DNS уже показывают нужное состояние. Несколько доменных API возвращают идентификатор операции для последующего опроса. Считайте отправку, завершение у провайдера и публичную проверку отдельными состояниями в журнале.

Компактная последовательность проверок ловит большинство неожиданностей после чувствительного изменения:

1. Сохраните идентификатор операции провайдера и опрашивайте его документированный статус, пока он не достигнет конечного состояния.
2. Снова прочитайте состояние регистратора и сравните его с одобренным объектом `after`.
3. Запросите NS- и DS-данные родительской стороны через несколько рекурсивных путей, затем опросите авторитетные серверы напрямую.
4. Проверьте небольшой набор сервисов, зависящих от зоны, включая маршрутизацию почты и записи проверки сертификатов, если такие сервисы есть.
5. Закрывайте изменение лишь после совпадения доказательств или запускайте подготовленный путь восстановления.

Это один из немногих случаев, когда для повторов нужны жёсткие ограничения. Повторить чтение после тайм-аута обычно нормально. Повтор состояния после неизвестного ответа может создать перекрывающиеся задачи или дважды переключить значение. Перед повтором найдите запрос по токену идемпотентности либо прочитайте текущую операцию и состояние домена. Если провайдер не предлагает механизма идемпотентности, передайте неоднозначный результат на рассмотрение, а не гадайте.

Откат тоже зависит от действия. Возврат старых nameserver может восстановить делегирование, но кэши задержат сходимость. Повторное включение transfer lock может закрыть окно, если перенос не продвинулся. Восстановление контакта может вызвать ещё одно подтверждение или блокировку. Восстановление старого DS может не сработать, если соответствующий приватный ключ подписи уже не активен. В записи о восстановлении до подтверждения должны быть указаны обратное действие для конкретного случая и его предварительные условия.

Окно обслуживания не заменяет проверку. Изменения DNS распространяются по кэшам согласно существующим TTL, а операции регистратора могут быть асинхронными. Продолжайте мониторинг, пока старое и новое состояния не будут вести себя так, как предполагает план миграции.

## Раздельные учётные данные не заменяют подтверждение каждого вызова

Минимальные права всё равно важны. Давайте агенту доступ только к нужной учётной записи регистратора, доменам и операциям, а доступ к платежам и несвязанному портфелю исключайте, когда это позволяет провайдер. Краткоживущие учётные данные и изоляция процессов ещё сильнее сокращают риск.

Но разделение одного широкого токена на четыре учётные данные не доказывает намерение. Агент всё ещё может неправильно использовать ключ nameserver в разрешённых ему пределах, а скомпрометированный процесс может дождаться появления нужного токена. Раздельные учётные данные уменьшают максимальный радиус поражения. Подтверждение каждого вызова решает, должен ли произойти конкретный ущерб.

Авторизация сессии и подтверждение каждого вызова решают разные задачи. Авторизация сессии отвечает, может ли этот процесс агента действовать через шлюз во время запуска. Подтверждение каждого вызова прерывает немногие операции, где человек должен сопоставить намерение с точными последствиями. Чтение и обычные вызовы с низким влиянием могут продолжаться в рамках сессии, а ключ регистратора, помеченный для подтверждения, останавливается при каждом использовании.

Sallyport реализует это разделение через vault gate, авторизацию каждого нового процесса агента и настройку для каждого ключа, которая требует подтверждения при каждом использовании и при этом не отдаёт секрет регистратора агенту. Для широких учётных данных регистратора пометьте ключ как требующий подтверждения каждого вызова и передавайте в описании запроса нормализованное действие и разницу, описанные выше.

Не учите агента временно держать API-токен, чтобы он смог завершить пакет. Как только токен попадает в процесс модели, подтверждение становится рекомендательным, потому что последующие вызовы могут обойти шлюз. Компонент, хранящий учётные данные, должен сам выполнять одобренный запрос и возвращать только результат.

## Журнал аудита должен позволять восстановить решение

Запись аудита «агент вызвал регистратора» не поможет разобраться в инциденте. В ней должно быть видно, что видел человек, что он одобрил, какие байты были отправлены, что вернул провайдер и что позже показала проверка. Иначе команда сможет доказать активность, но не авторизацию.

Для каждого чувствительного вызова сохраняйте личность процесса, идентификатор сессии, проверяющего, время решения, нормализованное действие, домен, объекты до и после, хеш запроса, идентификатор операции провайдера, статус ответа и результат проверки. Защищайте персональные значения контактов согласно правилам обработки данных, но оставляйте стабильный дайджест или контролируемую зашифрованную копию, чтобы расследующие могли отличить два изменения.

Храните также события отказа и отзыва прав. Если оператор отзывает сессию агента, увидев неожиданный запрос на снятие блокировки, эта последовательность объясняет, почему последующие вызовы остановились. Журнал, доступный только для добавления и связанный хеш-цепочкой, делает незаметное редактирование обнаружимым, а независимый экспорт или проверка не позволяют полагаться на тот же интерфейс, который выполнял действие.

Sallyport записывает сессии агентов и отдельные вызовы в единый зашифрованный журнал аудита с хеш-цепочкой. `sp audit verify` проверяет цепочку офлайн по шифротексту без ключа от хранилища. Проверка доказывает, что записанная цепочка не была изменена, а оболочка действия даёт расследованию смысл, специфичный для домена.

Запись о подтверждении должна пережить и абстракцию провайдера. Храните название операции провайдера рядом с нормализованным действием, а не вместо него. Тогда расследующий сможет сопоставить переносимую метку вроде `dnssec.ds.remove` с точным вызовом API, не заставляя каждого проверяющего изучать словарь каждого поставщика. Сохраняйте канонические байты запроса или их криптографический дайджест и фиксируйте версию нормализации, которая создала действие. Если позже классификатор изменится, расследующие смогут воспроизвести решение, которое действительно видел оператор, а не применить новую логику к старым событиям.

Проверьте эту запись до того, как начнёте ей доверять. Проведите безобидное изменение в тестовом домене через подтверждение, отклоните изменённый запрос с той же указанной причиной, отзовите сессию агента и убедитесь, что журнал сохраняет все три события по порядку. Затем смоделируйте неоднозначный тайм-аут провайдера и подтвердите, что процесс читает состояние вместо слепой повторной отправки. Схема аудита, работающая лишь для успешных вызовов, подведёт именно во время инцидента, который должна была объяснить.

Первое полезное изменение - перестать называть инструмент регистратора «обновить домен». Дайте отдельные имена замене nameserver, снятию блокировки переноса, изменению контакта, получению кода авторизации и изменению DS. Затем разместите согласие человека на вызове, который несёт каждое из этих последствий. Учётные данные могут оставаться широкими, потому что так их спроектировал провайдер, но решение больше не обязано быть широким.
