Определение того, когда следует попробовать соединение IPv6, а когда использовать IPv4. - PullRequest
9 голосов
/ 29 августа 2009

Я работаю над программой сетевого клиента, которая подключается к публичным серверам, указанным пользователем. Если пользователь дает мне имя хоста для подключения, которое имеет адреса как IPv4, так и IPv6 (обычно это DNS-имя с записями A и AAAA), я не уверен, как решить, к какому адресу следует подключаться .

Проблема в том, что машины довольно часто поддерживают как IPv4, так и IPv6, но имеют только глобальное подключение через IPv4. Наиболее распространенный случай этого - когда настроены только локальные адреса IPv6. На данный момент лучшими альтернативами, которые я могу придумать, являются:

  1. Сначала попробуйте адрес (а) IPv6 - в случае сбоя соединения попробуйте адрес (а) IPv4; или
  2. Просто позвольте пользователю указать его в качестве параметра конфигурации («предпочитать_ipv6» вместо «предпочитать_ipv4»).

Проблема, которую я вижу в варианте 1, заключается в том, что соединение может не разорваться сразу - для его истечения может потребоваться некоторое время.

Ответы [ 5 ]

9 голосов
/ 29 августа 2009

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

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

Есть, конечно, случаи, когда вещи могут сломаться, например, если настроен глобальный (или туннельный) адрес и что-то ложно отфильтровывает сообщения об ошибках ICMPv6. Вы не должны беспокоиться об этом случае - возможно, что соединение IPv4 как-то нарушено.

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

4 голосов
/ 23 апреля 2013

После ответа на вопрос IETF предложил ответ на этот вопрос с RFC6555 , a.k.a. Happy Eyeballs .

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

2 голосов
/ 10 ноября 2010

Вы должны позволить общесистемной конфигурации решить благодаря getaddrinfo(). Так же, как Java. Запрашивать каждое отдельное приложение для каждой возможной конфигурации (неправильной) IPv6 на самом деле нельзя масштабировать! В случае неверной конфигурации, для пользователя гораздо более интуитивно понятно, если все или ни одного приложения не работают.

С другой стороны, вы хотите попытаться записать досадных задержек и тайм-аутов, чтобы пользователи могли быстро определить, в чем виноват. Как и все другие задержки, в идеале, включая (очень распространенные) тайм-ауты DNS.

1 голос
/ 23 апреля 2013

Этот разговор имеет решение. Подводя итог;

  • Иногда возникают проблемы с поиском DNS или последующим подключением к разрешенному адресу
  • Вы не хотите ждать истечения времени ожидания подключения к IPv6-адресу до подключения к IPv4-адресу или наоборот
  • Вы не хотите ждать, пока поиск записи AAAA истечет, прежде чем искать запись A или наоборот
  • Вы не хотите останавливаться, ожидая записи AAAA и A, прежде чем пытаться соединиться с какой-либо записью, которую вы получите первым.

Решение состоит в том, чтобы искать записи AAAA и A одновременно и независимо и независимо подключаться к разрешенным адресам. Сначала используйте любое соединение.


Самый простой способ сделать это - позволить сетевому API сделать это за вас, используя сетевые интерфейсы с именем по имени. Например, в Java:

InetSocketAddress socketAddress = new InetSocketAddress("www.example.com", 80);
SocketChannel channel = SocketChannel.open(socketAddress);
channel.write(buffer);

В примечаниях к слайду сказано:

Здесь мы создаем непрозрачный объект с именем InetSocketAddress из хоста. и порт, а затем, когда мы открываем этот SocketChannel, который может завершить под одеялом, делать все необходимое, без приложение когда-либо видит IP-адрес.

Windows также имеет API-интерфейсы подключения по имени. У меня нет фрагментов кода для те, кто здесь.

Теперь я не говорю, что все реализации этих API обязательно делать правильные вещи сегодня, но если приложения используют эти API, тогда реализации могут быть улучшены с течением времени.

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

0 голосов
/ 29 августа 2009

Некоторые идеи:

  1. Разрешить пользователю указывать предпочтения для каждого сайта.
  2. Сначала попробуйте IPv4.
  3. Попытка параллельного IPv6 при первом подключении.
  4. При последующих подключениях используйте IPv6, если ранее подключение было успешным.

Я говорю сначала попробовать IPv4, потому что это протокол, который лучше установлен и протестирован.

...