Назад | Перейти на главную страницу

Семантика :: и 0.0.0.0 в двухстековых ОС

Во времена, когда использовался только IPv4, соединение LISTEN отображалось в netstat как слушать 0.0.0.0 будет отвечать на соединения на любом интерфейсе IPv4 в системе.

Насколько я понимаю, новая идиома IPv6 :: слушает на всех доступных IPv6 и Интерфейсы IPv4. Это правильно для всех ОС (Unix, Windows, Mac)? Есть ли идиома для прослушивания только интерфейсов IPv6?

К сожалению, это зависит от того, какую операционную систему вы используете.

В Microsoft Windows привязка сокета к :: связывается только с портами IPv6. Таким образом, чтобы прослушивать все адреса как на IPv4, так и на IPv6, вам необходимо выполнить привязку к 0.0.0.0 так же как ::. Следующий отрывок взят из коробки Vista:

C:\>netstat -an | find "445"
  TCP    0.0.0.0:445            0.0.0.0:0              LISTENING
  TCP    [::]:445               [::]:0                 LISTENING

В качестве примера я привожу порт 445, используемый для трафика SMB, когда NetBIOS не используется. Как видите, он привязан к обоим 0.0.0.0 и :: чтобы заставить работать, соответственно, и IPv4 и IPv6 клиенты.

В Linux :: включает IPv4-совместимые адреса, как вы правильно догадались, поэтому привязка к 0.0.0.0 также не нужно. Я написал простую программу на Python, которая привязывается только к AF_INET6 розетка на ::. Хотя я также не привязывался к AF_INET (IPv4), он по-прежнему принимает соединения от клиентов IPv4. Если, скажем, 10.1.1.3 подключается к нему, он будет отображаться как подключение от ::ffff:10.1.1.3.

Кроме что это становится волосатым. Вышеуказанное не применяется в Linux, если /proc/sys/net/ipv6/bindv6only установлен на 1, и в этом случае поведение точно такое же, как в Windows - привязка к :: будет слушать только запросы IPv6. Если вы хотите также прослушивать запросы IPv4, вам нужно будет создать AF_INET сокет и слушай 0.0.0.0 также. К счастью, по умолчанию для bindv6only является 0, поэтому очень маловероятно, что вам когда-нибудь придется иметь дело с этим (кроме случаев, когда вы используете Debian, который по умолчанию bindv6only = 1).

Все это полезно знать при проверке, поддерживает ли служба IPv6 и поддерживает ли она также IPv4. Вот мой SSH-сервер:

$ netstat -64ln | grep 22
tcp6    0    0 :::22    :::*    LISTEN

Как видите, SSH прослушивает только :: порт 22. Однако он не просто прослушивает клиентов IPv6 - он отлично работает с клиентами IPv4 благодаря привязке, совместимой с IPv4. Чтобы доказать это, посмотрите на это:

$ cat /proc/sys/net/ipv6/bindv6only 
0

bindv6only отключено (по умолчанию). Если бы это было установлено на 1, тогда мне пришлось бы поощрять SSH прослушивать 0.0.0.0 также (или вместо этого).

Приносим извинения за отсутствие информации о Mac OS X. Я использовал его в прошлом, но предпочитаю эстетику GNOME, поэтому я не использовал его очень давно. Однако я предполагаю, что поведение такое же, как у Linux.

Надеюсь это поможет.

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

Изменить: Ах, немного ниже он говорит:

Некоторые распространенные стеки IPv6 не поддерживают функцию сопоставления адресов IPv4 либо потому, что стеки IPv6 и IPv4 являются отдельными реализациями (Microsoft Windows до Vista / Longhorn: например, XP / 2003), либо из-за проблем безопасности (OpenBSD). В этих операционных системах необходимо открыть отдельный сокет для каждого поддерживаемого IP-протокола. В некоторых системах (например, Linux, NetBSD, FreeBSD) эта функция управляется параметром сокета IPV6_V6ONLY, как указано в RFC 3493

Вероятно, вы могли бы сделать это со своим сетевым идентификатором AAAA: BBBB: CCCC: DDDD :: или как-то иначе. Это гарантировало бы, что только интерфейсы IPv6 воспримут его. Думаю. Я не мастер IPv6.