Русский · English
Готовые примеры работы с DNS Lookup API на шести языках: Python, TypeScript (Node.js), Go, Java, C#, PHP. Проверка DNS-записей домена одним HTTP-запросом: A, AAAA, MX, TXT, CNAME, NS — плюс проверка распространения записей по публичным резолверам.
Прикладной сценарий в комплекте: проверка домена на спуфинг — читаем MX, SPF и DMARC и выносим вердикт, может ли посторонний слать письма от имени домена.
Каждый пример запускается сразу — без регистрации, без ключа, без карты. В коде зашит публичный демо-ключ.
git clone https://github.com/atlorium-api/dns-lookup-api-client
cd dns-lookup-api-client/python && pip install -r requirements.txt && python main.pyДемо-ключ: ответы сгенерированы (моки), не реальные записи DNS.
DNS-записи atlorium.com (резолвер 1.1.1.1 (sandbox)):
A 189.99.124.40 (TTL 300)
A 148.24.116.247 (TTL 300)
AAAA eed8:7c4f:92b:1734:74be:4695:fad0:6339 (TTL 300)
MX 30 mail2.atlorium.com (TTL 3600)
MX 20 mail2.atlorium.com (TTL 3600)
TXT v=spf1 include:_spf.atlorium.com ~all (TTL 3600)
NS ns1.atlorium.com (TTL 86400)
NS ns2.atlorium.com (TTL 86400)
АУДИТ ЗАЩИТЫ ОТ СПУФИНГА — atlorium.com
MX: mail2.atlorium.com (приоритет 30), mail2.atlorium.com (приоритет 20)
SPF: v=spf1 include:_spf.atlorium.com ~all
DMARC: не найден (_dmarc.atlorium.com)
ВЕРДИКТ: УЯЗВИМ — от имени домена можно слать поддельные письма
ПРОБЛЕМЫ:
[~] SPF ~all (softfail): подделку помечают, но письмо всё равно доставляют. Строгая политика — -all
[!] DMARC не найден (_dmarc.atlorium.com): почтовый сервер получателя не знает, что делать с письмом, не прошедшим SPF/DKIM, — и обычно его доставляет
Это моки, а не настоящий DNS. Демо-ключ отдаёт сгенерированные записи: IP-адреса выдуманы,
mail2.atlorium.comиns1.atlorium.comне существуют, а реальные записи домена atlorium.com выглядят иначе. Подставьте боевой ключ — тот же код начнёт резолвить настоящий DNS.
Это важно понимать до того, как вы начнёте сверять вывод примера с dig:
| Тип | Что отдаёт демо-ключ |
|---|---|
A / AAAA |
Два выдуманных IPv4 и один IPv6 |
MX |
Две записи вида mailN.<домен> со случайными приоритетами. Хосты могут совпасть, а приоритеты — идти не по возрастанию: в выводе выше mail2 стоит дважды. В настоящем DNS так не бывает — это артефакт генератора, а не поведение сервиса |
TXT |
Ровно одна запись — v=spf1 include:_spf.<домен> ~all, для любого домена |
NS |
Два хоста nsN.<домен> |
CNAME |
В песочнице не отдаётся (боевой ключ — отдаёт) |
Отсюда два следствия, которые видно в выводе выше:
- SPF в песочнице всегда есть и всегда
~all— то есть softfail. Ветку «SPF не найден» на демо-ключе не увидеть. - DMARC в песочнице не существует. На запрос
_dmarc.<домен>мок отдаёт такую же SPF-запись, а не DMARC — поэтому пример честно печатает «DMARC не найден» и ставит вердикт УЯЗВИМ. Это не баг примера: он корректно показывает отсутствие записи вместо того, чтобы её выдумать.
Мок намеренно не подстраивается под красивый вывод. Хотите увидеть вердикт «ЗАЩИЩЁН» — нужен боевой ключ и домен с p=reject.
Мониторинг доменов, проверка миграции на новый хостинг, инвентаризация DNS в инфраструктуре, антифрод и e-mail-безопасность. Вместо dig, накрученного на bash, — структурированный JSON, который сразу ложится в код.
Примеры не просто печатают записи, а применяют их: в каждом есть функция auditMailSecurity() — проверка домена на спуфинг:
- MX — принимает ли домен входящую почту.
- SPF — TXT-запись
v=spf1 .... Разбирается политика:-all(hard fail — строго),~all(softfail — подделку помечают, но доставляют),?all/+all(политики фактически нет — дыра). - DMARC — TXT-запись на поддомене
_dmarc.<домен>. Это отдельная зона, поэтому нужен второй запрос к API. Разбирается тегp=:none(только мониторинг),quarantine(в спам),reject(максимальная защита).
Вердикт выносится по слабейшему звену: дыра в любом из механизмов делает домен пригодным для подделки писем. Один прогон = ровно два запроса к API.
Почему это важно: SPF сам по себе проверяет технического отправителя (конверт), а адрес в поле «От кого», который видит человек, им не защищён. Инструкцию «что делать с письмом, не прошедшим проверку» даёт только DMARC. Без DMARC принимающий сервер, как правило, доставляет подделку.
Проверить API вообще без клонирования:
curl -H "Authorization: Bearer ak_sandbox_demo_mockdata_v1" \
"https://atlorium.com/api/dns/lookup?domain=example.com"| Язык | Запуск | Требуется |
|---|---|---|
| Python | pip install -r requirements.txt && python main.py |
Python 3.10+ |
| TypeScript / Node.js | npm install && npm start |
Node.js 20+ |
| Go | go run . |
Go 1.22+ |
| Java | java Main.java |
JDK 17+ (без зависимостей) |
| C# | dotnet run |
.NET 8+ |
| PHP | php main.php |
PHP 8.1+ |
Передать свой домен аргументом: python main.py example.com
Ключ передаётся в заголовке Authorization:
Authorization: Bearer ВАШ_КЛЮЧ
| Ключ | Что делает |
|---|---|
ak_sandbox_demo_mockdata_v1 |
Демо-ключ. Публичный, один на всех. Возвращает моки, денег не списывает, регистрации не требует. Ответы детерминированы — на них можно писать стабильные тесты. |
| Боевой ключ | Настоящие DNS-запросы к резолверам. Получить в личном кабинете: atlorium.com |
Переход на боевой ключ не требует правок в коде — все примеры читают переменную окружения:
export ATLORIUM_API_KEY="ak_ваш_боевой_ключ"Каждый ответ песочницы помечен заголовком X-Atlorium-Sandbox: true — перепутать мок с реальными данными невозможно.
Базовый адрес: https://atlorium.com
| Метод | Путь | Назначение |
|---|---|---|
GET |
/api/dns/lookup |
Записи домена: A, AAAA, MX, TXT, CNAME, NS — за один запрос |
GET |
/api/dns/propagation |
Как видят домен разные публичные резолверы (проверка распространения) |
| Параметр | Где | Тип | Описание |
|---|---|---|---|
domain |
query | string | Обязательный. Чистое доменное имя: example.com, sub.example.com. Без https://, не IP-адрес. Поддомены — тоже домены: _dmarc.example.com валиден |
resolver |
query | string | IP-адрес резолвера. По умолчанию Cloudflare 1.1.1.1. Можно указать 8.8.8.8, 9.9.9.9 или корпоративный DNS |
| Параметр | Где | Тип | Описание |
|---|---|---|---|
domain |
query | string | Обязательный. Чистое доменное имя |
resolvers |
query | string | Список IP резолверов через запятую: 8.8.8.8,1.1.1.1. По умолчанию — Google, Cloudflare, OpenDNS, Quad9 |
Пропагация нужна после смены DNS: пока резолверы отдают разные ответы, часть пользователей продолжает ходить на старый адрес. В примерах функция checkPropagation() объявлена, но не вызывается — чтобы один прогон не тратил лишний запрос из квоты.
| Поле | Тип | Что содержит |
|---|---|---|
domain |
string | Запрошенный домен |
resolver |
string | Резолвер, который отвечал |
requestedAtUtc |
date-time | Время запроса, UTC |
records |
array | Группы записей по типу (см. ниже) |
errors |
array | Ошибки резолвинга по отдельным типам записей. Пустой массив — всё в порядке |
Записи приходят сгруппированными по типу, а не плоским списком:
| Поле группы | Тип | Что содержит |
|---|---|---|
type |
string | A, AAAA, MX, TXT, CNAME, NS |
records |
array | Записи этого типа |
| Поле записи | Тип | Что содержит |
|---|---|---|
name |
string | Имя, к которому относится запись |
value |
string | Значение: IP для A/AAAA, хост для MX/NS/CNAME, строка для TXT |
ttl |
int | Время жизни в кэше, секунды |
preference |
int | Только у MX. Приоритет: чем меньше число, тем выше приоритет сервера. У остальных типов null |
details |
string | Дополнительные сведения, если есть. Обычно null |
| Поле | Тип | Что содержит |
|---|---|---|
domain |
string | Проверяемый домен |
requestedAtUtc |
date-time | Время запроса, UTC |
snapshots |
array | Срез по каждому резолверу |
| Поле снимка | Тип | Что содержит |
|---|---|---|
label |
string | Имя резолвера: Cloudflare, Google, Quad9 |
resolver |
string | Его IP-адрес |
durationMs |
int | Сколько миллисекунд отвечал |
success |
bool | Ответил ли резолвер |
error |
string | Причина, если не ответил. Иначе null |
records |
array | Что он вернул — те же группы записей |
Записи разошлись между резолверами — пропагация ещё не завершилась.
| Код | Причина | Что делать |
|---|---|---|
400 |
Домен не передан или задан неверно | Нужно чистое имя: example.com. Не URL с протоколом и не IP |
401 |
Ключ отсутствует, просрочен или недействителен | Проверьте заголовок Authorization |
402 |
Недостаточно кредитов на балансе | Пополнить на atlorium.com |
429 |
Превышен rate-limit | Повторить с задержкой. Не доверяйте Retry-After слепо — см. ниже |
500 |
Резолвер не ответил или таймаут | Повторить позже, можно с другим resolver |
503 |
Сервис временно недоступен | Повторить позже. За сбой на нашей стороне деньги не списываются |
Во всех шести примерах коды разложены в человекочитаемые причины — смотрите класс AtloriumError.
Отдельно про 429: исчерпав часовую квоту, сервер честно просит подождать 40+ минут. Клиент, который слепо спит столько, сколько написано в Retry-After, зависает на все 40 минут (а в CI просто съедает бюджет джоба). Поэтому в примерах есть потолок ожидания MAX_RETRY_DELAY = 120 секунд: дольше не ждём, а честно сообщаем, что квота исчерпана.
Обратите внимание: кода 404 у этого API нет. На домен, у которого записей не нашлось, приходит 200 с пустым records и пояснением в errors («DNS-записи для домена не найдены»). Проверять надо не код ответа, а содержимое records.
И ещё одна деталь, на которой легко ошибиться: группа с нулём записей в ответ не попадает вовсе. Если у домена нет MX-записей, группы type: "MX" в массиве не будет — не будет и пустого массива внутри неё. Поэтому «нет MX» определяется отсутствием группы, а не её пустотой; во всех примерах за это отвечает хелпер recordsOf().
Оплата pay-as-you-go, без подписки: платите только за выполненные запросы. Актуальные тарифы и лимиты — на atlorium.com/pricing.
DNS — дешёвая операция, и лимиты у неё заметно свободнее, чем у большинства других сервисов. Точные значения и цены: atlorium.com/pricing
Как через API получить MX-записи домена? Один запрос GET /api/dns/lookup?domain=example.com возвращает все типы сразу, включая MX. Отдельного «MX lookup»-эндпоинта нет и не нужно: в ответе найдите группу с type: "MX". У MX-записей заполнено поле preference — приоритет почтового сервера.
Почему проверка DMARC — это отдельный запрос? Потому что DMARC-запись лежит не на домене, а на его поддомене _dmarc.example.com. Это другая зона DNS, и достать её тем же запросом физически нельзя. SPF при этом живёт в TXT-записи самого домена — он приходит первым же запросом.
Чем -all отличается от ~all в SPF? -all (hard fail) — «письмо не от нас, отклоняйте». ~all (softfail) — «скорее всего не от нас, но доставьте, пометив». ?all и +all — политики фактически нет: разрешено кому угодно. Строгая настройка — -all, но переходить на неё стоит после того, как DMARC-отчёты покажут, что все легитимные отправители учтены.
DMARC p=none — это защита? Нет. Это режим наблюдения: нарушения только логируются в отчётах, письма не блокируются. С него правильно начинать, но останавливаться на нём — значит собирать статистику о подделках вместо того, чтобы их прекращать. Защиту дают p=quarantine (в спам) и p=reject (отбросить).
Чем это лучше dig или системного резолвера? Тем, что ответ — сразу JSON, а не текст, который надо парсить регулярками; тем, что резолвер задаётся параметром (полезно, когда локальный DNS кэширует или подменяет ответы); и тем, что из CI/serverless-окружения, где dig не установлен, работает обычный HTTP-запрос.
Можно ли проверять этим API чужие домены? Да. DNS — публичные данные, никаких особых прав для их чтения не нужно. Именно поэтому проверка чужого домена на спуфинг вообще возможна — и именно поэтому свой домен стоит закрыть DMARC-политикой раньше, чем это заметит кто-то другой.
Обязательна ли регистрация, чтобы попробовать? Нет. Демо-ключ публичный и работает без аккаунта — но возвращает моки, а не реальные DNS-записи.
DNS редко проверяют в одиночку. Из того же аккаунта и тем же ключом доступны:
- Проверка SSL-сертификата — срок действия, SAN, цепочка доверия
- CIDR-калькулятор — разбиение сети на подсети и проверка вхождения IP
- Разбор cron-выражений — валидация расписания и ближайшие запуски с учётом таймзоны
- Профиль IP — гео, ASN, детект VPN, прокси и Tor
- Погодные данные — текущие условия по координатам
- AML-скоринг криптокошелька — риск-балл, санкции, PEP
Полный каталог — atlorium.com
- Документация API (Swagger): atlorium.com/dnsAPI
- Описание сервиса: atlorium.com/dnsDescription
- Веб-интерфейс: atlorium.com/dnsGUI
- OpenAPI-спецификация: dns_ru.json
- Поддержка: support@atlorium.com
MIT — берите код и используйте как хотите, в том числе в коммерческих проектах.