Как запросить у “dig” возврат только IP-адреса из записи CNAME?

Вопрос или проблема

Команда dig +short (например, описанная в “dig show only answer“) отлично подходит для пакетной обработки имен в IP-адреса. Она выполняет простую задачу и делает это хорошо.

К сожалению, когда есть CNAME, даже +short недостаточно коротка. Например:

$ dig +short docs.sbonds.org
ghs.google.com.
173.194.69.121

Я пробовал +noall, но это не похоже на то, что изменяет поведение +short. Я также пробовал указать -t a, чтобы убедиться, что он не считает, что я имел в виду запись A или CNAME, но это (неудивительно) ничего не меняет.

$ dig +noall +short docs.sbonds.org
ghs.google.com.
173.194.69.121

Я использую dig на RedHat 7:

# dig -v
DiG 9.9.4-RedHat-9.9.4-73.el7_6

Я могу отфильтровать CNAME с помощью надежного grep, но кажется, что dig должен иметь какой-то способ выдавать “Только IP, мэм”.

Какой это способ?

dig — это инструмент для устранения неполадок, поэтому он отправляет DNS-запросы и получает DNS-ответы, и, как сказал Андреас, ответом являются как записи CNAME, так и A, как это было задумано. Ваше желание — получить “Только IP, мэм”, так что это не диагностика DNS, это “просто” разрешение, для которого dig избыточен.

nslookup

nslookup уступает dig, но все равно даст вам слишком много информации:

$ nslookup docs.sbonds.org
Server:     192.0.2.254
Address:    192.0.2.254#53

Non-authoritative answer:
docs.sbonds.org canonical name = ghs.google.com.
Name:   ghs.google.com
Address: 172.217.4.179

host

host проще, но все равно вернет вам “слишком много” (но обратите внимание, что он также возвращает адрес IPv6, что хорошо):

$ host docs.sbonds.org
docs.sbonds.org is an alias for ghs.google.com.
ghs.google.com has address 172.217.15.83
ghs.google.com has IPv6 address 2607:f8b0:4004:815::2013

getent

В зависимости от вашей системы Unix, getent может быть использован. Однако обратите внимание, что это может или не может делать DNS-запрос, так как вы настраиваете в /etc/nsswitch.conf источник данных для каждой службы, и для hosts это, вероятно, будет смесь files (что есть venerable /etc/hosts) и DNS.

$ getent hosts docs.sbonds.org
2607:f8b0:4007:801::2013 ghs.google.com docs.sbonds.org

Обратите внимание также, что в правильной настройке Unix предпочтение будет отдаваться IPv6 перед IPv4, так что это может быть для вас проблемой (это должно зависеть от конфигурации в /etc/gai.conf)

На самом деле hosts не учитывает /etc/gai.conf, вам нужно использовать ahosts вместо этого, который использует getaddrinfo и, следовательно, gai.conf. Обратите внимание, что вы получаете список (чей порядок зависит от настройки gai.conf):

$ getent ahosts docs.sbonds.org
172.217.4.179   STREAM ghs.google.com
172.217.4.179   DGRAM
172.217.4.179   RAW
2607:f8b0:4007:801::2013 STREAM
2607:f8b0:4007:801::2013 DGRAM
2607:f8b0:4007:801::2013 RAW

Perl

Если вам разрешено написать простой скрипт, у вас есть много решений, например:

$ perl -MSocket -E 'say inet_ntoa(inet_aton("docs.sbonds.org"))'
172.217.4.179

DOH

Или используйте любой DOH (DNS поверх HTTPS) endpoint (или подобное) с любым HTTP-клиентом. Примеры:

$ curl --silent 'https://dns.google.com/resolve?name=docs.sbonds.org&type=A' | jq -cr '.Answer[] | select(.type == 1) | .data'
172.217.3.83


$ curl --silent -H 'accept: application/dns-json' 'https://cloudflare-dns.com/dns-query?name=docs.sbonds.org&type=A' | jq -cr '.Answer[] | select(.type == 1) | .data'
172.217.12.147

Systemd

Systemd имеет собственное приложение для резолвера:

$ systemd-resolve docs.sbonds.org
docs.sbonds.org: 172.217.9.51
                 2607:f8b0:4009:801::2013
                 (ghs.google.com)

-- Information acquired via protocol DNS in 239.1ms.
-- Data is authenticated: no

Вам все равно нужно как-то его обработать, но он дает конечные IP-адреса напрямую (есть флаг при его вызове, чтобы он не следовал записям CNAME для случаев использования, которым это требуется)

Как CNAME, так и соответствующая A-запись (или любой тип, который вы запросили) принадлежат к секции ответа. Таким образом, нет опции dig (по крайней мере, в RHEL7’s dig), которая могла бы отфильтровать ответ CNAME.

Я думаю, что вам придется полагаться на dig +short [...] | grep -v '\.$', чтобы удалить ответы CNAME.

Ответ или решение

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

Теория

Утилита DNS (Domain Name System) под названием dig используется для диагностики сетевых проблем и проверки различных аспектов настройки DNS. Когда запрашивается информация о домене, у которого есть CNAME-запись, dig возвращает как саму CNAME, так и связанный с ней записанный IP-адрес. Такая структура ответа является стандартом для работы с DNS и позволяет получить полную картину возможных маршрутов до конечного адреса.

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

Пример

Предположим, пользователь хочет получить только IP-адрес домена docs.sbonds.org, используя следующую команду:

$ dig +short docs.sbonds.org

Ответ будет следующим:

ghs.google.com.
173.194.69.121

Ответ включает как CNAME, так и IP-адрес, что избыточно для целей получения исключительно IP-адреса.

Применение

Прямого способа выполнить эту задачу с помощью только dig версии, доступной в RHEL 7, не существует, но есть несколько обходных маневров и альтернативных инструментов, которые могут помочь:

  1. Использование фильтрации в команде grep:

    Используйте команду grep для сокрытия строк, содержащих финальную точку, которая обычно характерна для CNAME записей:

    $ dig +short docs.sbonds.org | grep -v '\.$'

    Это отфильтрует CNAME из вывода, оставив только IP-адреса.

  2. Применение утилиты nslookup:

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

    $ nslookup -type=A docs.sbonds.org | grep "Address:" | tail -n1

    Здесь идет акцент на поиск строки, начинающейся с Address:, и выводе последней такой строки.

  3. Использование host:

    Утилита host предоставляет более упрощенный формат ответа:

    $ host docs.sbonds.org | grep "has address" | awk '{print $4}'

    Эта команда извлечет только часть с IP-адресом.

  4. Программирование с помощью Perl или Python:

    Если разрешено использование скриптов, Perl или Python могут стать мощным инструментом:

    На Perl:

    $ perl -MSocket -e 'print inet_ntoa(inet_aton("docs.sbonds.org")), "\n"'

    На Python:

    import socket
    print(socket.gethostbyname('docs.sbonds.org'))

    Эти скрипты напрямую возвращают только IP-адрес домена.

  5. Использование DNS через HTTPS (DOH):

    Эта методика позволяет обращаться к DNS-серверам через HTTPS, используя curl и jq для фильтрации данных:

    $ curl --silent 'https://dns.google.com/resolve?name=docs.sbonds.org&type=A' | jq -r '.Answer[] | select(.type == 1) | .data'

    Инструмент jq здесь выступает как мощный синтаксический анализатор JSON, позволяющий извлечь исключительно интересующие данные.

  6. Системные решения с использованием getent:

    В зависимости от настроек системы, getent может предоставить необходимую информацию:

    $ getent ahosts docs.sbonds.org | grep STREAM | awk '{print $1}' | head -n 1

    При правильной настройке это будет предпочтение IPv4-адресов.

  7. Решения с использованием systemd-resolve:

    Решатель от systemd вновь предоставляет возможность работы с DNS, где вы можете выбрать подходящий уровень детализации:

    $ systemd-resolve --no-pager --status docs.sbonds.org | grep "Address" | head -n 1

    Чтобы избежать домен-названия, используйте комбинацию с фильтрацией вывода.

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

Оцените материал
Добавить комментарий

Капча загружается...