DNS-поиск иногда занимает 5 секунд

11

У меня есть виртуальная машина, на которой запущен Debian Wheezy, и поиск некоторых имен хостов занимает несколько секунд, хотя распознаватель отвечает немедленно. Странно, но поиск с getaddrinfo()влияет, но gethostbyname()это не так.

Я переключился на распознаватели Google, чтобы исключить возможность поломки локальных преобразователей, поэтому мой /etc/resolv.confвнешний вид выглядит следующим образом:

search my-domain.com
nameserver 8.8.4.4
nameserver 8.8.8.8

У меня nsswitch.confесть строка:

hosts: files dns

и мой /etc/hostsне содержит ничего необычного.

Если я попытаюсь telnet webserver 80, он зависнет на несколько секунд, прежде чем получить разрешение имени. ltraceВыход [1] показано , что зависание находится в getaddrinfo()вызове:

getaddrinfo("ifconfig.me", "telnet", { AI_CANONNAME, 0, SOCK_STREAM, 0, 0, NULL, '\000', NULL }, 0x7fffb4ffc160) = 0 <5.020621>

Тем не менее, tcpdumpобнаруживается, что сервер имен ответил немедленно, и только во втором ответе был telnetразблокирован. Ответы выглядят одинаково:

05:52:58.609731 IP 192.168.1.75.43017 > 8.8.4.4.53: 54755+ A? ifconfig.me. (29)
05:52:58.609786 IP 192.168.1.75.43017 > 8.8.4.4.53: 26090+ AAAA? ifconfig.me. (29)
05:52:58.612188 IP 8.8.4.4.53 > 192.168.1.75.43017: 54755 4/0/0 A 219.94.235.40, A 133.242.129.236, A 49.212.149.105, A 49.212.202.172 (93)

[...five second pause...]

05:53:03.613811 IP 192.168.1.75.43017 > 8.8.4.4.53: 54755+ A? ifconfig.me. (29)
05:53:03.616424 IP 8.8.4.4.53 > 192.168.1.75.43017: 54755 4/0/0 A 219.94.235.40, A 133.242.129.236, A 49.212.149.105, A 49.212.202.172 (93)
05:53:03.616547 IP 192.168.1.75.43017 > 8.8.4.4.53: 26090+ AAAA? ifconfig.me. (29)
05:53:03.618907 IP 8.8.4.4.53 > 192.168.1.75.43017: 26090 0/1/0 (76)

Я проверил журналы брандмауэра хоста, и на порту 53 ничего не блокируется.

Что вызывает игнорирование первого ответа DNS?

[1] Я добавил пару строк, чтобы ltrace.confвидеть внутри addrinfoструктуры.

Flup
источник
Как настроена сетевая карта виртуальной машины? Мостовой? NAT?
СЛМ
Это NATT. Я не уверен, где именно применяется NAT (будь то ESX или более поздняя версия); Я могу узнать, думаете ли вы, что это может иметь значение.
Флюп
Я подозреваю, что на это влияет NAT + VM.
СЛМ
Вполне возможно - см. Мои комментарии к ответу Кемпню ниже.
Флюп
Это был сетевой, но не специально NAT, вызывающий это - см. Мой ответ ниже.
Флюп

Ответы:

13

Первый ответ DNS не игнорируется. getaddrinfo()не возвращался, пока не получил ответ на первый запрос AAAA (ID: 26090). Таким образом, реальная проблема здесь заключается в том, что ваша машина не сразу получила ответ на запрос AAAA, в то время как она получила ответ на запрос A (ID: 54755).

Одно из различий между getaddrinfo()и gethostbyname()заключается в том, что первый поддерживает как IPv4, так и IPv6, а второй поддерживает только IPv4. Поэтому , когда вы звоните getaddrinfo()с ai_familyмножеством 0 ( AF_UNSPEC), он не будет возвращаться до тех пор , пока не получит ответ (или попадает тайм - аут) для обоих запросов A и AAAA для имени домена при условии. gethostbyname()только запросы для записи.

Трудно определить, что может быть причиной вашей проблемы, особенно если вы отключили tcpdumpвывод. Что-то может быть выборочно фильтровать / отбрасывать трафик DNS между вашей виртуальной машиной и Google Public DNS resolvers. Я попытался воспроизвести вашу проблему, используя виртуальную машину Debian Wheezy KVM, но telnet ifconfig.meпочти сразу напечатал Trying <IP_address_here>...строку (то есть к тому времени она уже разрешила имя).

Kempniu
источник
Спасибо за ваш подробный ответ. Я ничего не вырезал из tcpdump, я только вставил строку, чтобы прояснить, где была пауза. Вы определенно дали мне кое-что продолжить; Я не осознавал существенную разницу между двумя вызовами библиотеки.
Флюп
Если на вашем компьютере больше нет пакетов, связанных с DNS, вероятно, что-то фильтрует его трафик (не обязательно специально). В любом случае, если вы найдете решение, поделитесь им здесь?
Кемпню
1
Я действительно буду. Установив тестовый распознаватель, я могу окончательно увидеть, что один ответный пакет - один из моего вопроса - каждый раз отбрасывается. Я подозреваю, что что-то в или около инфраструктуры VMware делает это, поэтому я связался с моим коллегой, который заботится об этой стороне вещей. Когда я доберусь до сути, я вернусь и добавлю детали. Еще раз спасибо!
Флюп
Решение добавлено в моем собственном ответе. Большое спасибо еще раз за вашу помощь.
Флюп
9

Это было вызвано чрезмерно ограниченным набором правил на брандмауэре Juniper, который находится перед инфраструктурой VMware.

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

Мой коллега, который управляет сетью, отметил, что

Поведение по умолчанию на брандмауэре Juniper - закрывать связанный с DNS сеанс, как только получен ответ DNS, соответствующий этому сеансу.

Таким образом, брандмауэр просматривал ответ IPv4, замечая, что он ответил на запрос виртуальной машины, и закрывал входящий путь для этого порта. Поэтому следующий пакет ответа IPv6 был отброшен. Я не знаю, почему оба пакета прошли через второй раз, но отключение этой функции на брандмауэре устранило проблему.

Это связанная выдержка из Juniper KB:

Вот сценарий, в котором отбрасываются пакеты ответа DNS:

  1. Сеанс для трафика DNS создается, когда первый пакет запроса DNS попадает на брандмауэр и настроена политика разрешений. Время ожидания по умолчанию составляет 60 секунд.
  2. Непосредственно перед закрытием сеанса передается новый DNS-запрос, и, поскольку он соответствует существующему сеансу (поскольку пара порт / IP-адрес источника и назначения всегда одинакова), он пересылается межсетевым экраном. Обратите внимание, что время ожидания сеанса не обновляется в соответствии с любым вновь поступающим пакетом.
  3. Созданный сеанс DNS устаревает, когда первый ответ (ответ) DNS-запроса попадает на устройство, независимо от того, сколько времени осталось.
  4. Когда DNS-ответ передается через брандмауэр, сеанс устаревает.
  5. Все последующие ответы DNS отбрасываются брандмауэром, поскольку сеанс не существует.

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

Flup
источник
1
У нас были те же симптомы на Debian 8.2. У нас была другая причина, и «решение» было другим (на стороне клиента). Я написал в блоге о нашей конкретной проблеме и более общей проблеме: philippecloutier.com/… Я хочу поблагодарить Flup и Kempniu, так как ваш вопрос и ответы поставили меня на правильный путь.
Филипп Клотье