
Я пишу сервер, который привязывается к нескольким локальным портам (включая 80
и 443
). Всякий раз, когда я запускаю его на Google Computer Engine (GCE), используя их Container-Optimized OS (COS) и контейнер Docker, порты привязываются к IPv6, а не к IPv4.
$ netstat -tuln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:36265 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp6 0 0 :::80 :::* LISTEN
tcp6 0 0 :::443 :::* LISTEN
udp 0 0 10.128.0.33:68 0.0.0.0:*
Это важное различие, поскольку в моей программе есть логика, которая пытается подключиться напрямую к локальному интерфейсу, используя адрес IPv4 127.0.0.1
.
Как указать экземпляру GCE использовать порт IPv4?
решение1
Редактировать
Следует отметить одну важную вещь (как указано в комментариях):- хотя маршрутизация IPv6 может быть привязана к интерфейсу, использующему как IPv4, так и IPv6, она не будет работать в Google Cloud (пока не поддерживается внутренне).
Итак, оказывается, что это сбивающая с толку «функция» того, как Docker работает в сети, и она по-прежнему должна разрешать соединения IPv4 наряду с IPv6.
Видетьэтот ответ StackOverflowдля более подробной информации. Я процитировал ответ ниже для потомков:
...github.com/docker/docker/issues/2174это о том, чтобы показать привязку только к IPv6 в
netstat
, но это не проблема. Как гласит этот github issues:При настройке прокси Docker запрашивает адрес обратной связи '127.0.0.1', Linux понимает, что это адрес, который существует в IPv6 (как ::0) и открывается на обоих (но формально это сокет IPv6). Когда вы запускаете netstat, он видит это и сообщает вам, что это IPv6, но он все еще слушает на IPv4. Если вы немного поигрались с настройками, вы могли отключить этот трюк, который делает Linux, установив net.ipv6.bindv6only = 1.
Другими словами, просто потому, что вы видите его как IPv6 только, он все равно может общаться по IPv4, если только вы не настроили IPv6 только на привязку к IPv6 с помощью настройки net.ipv6.bindv6only. Для ясности, net.ipv6.bindv6only должен быть 0 — вы можете запустить
sysctl net.ipv6.bindv6only
для проверки.