Я пишу сервер, который привязывается к нескольким локальным портам (включая 80
и 443
). Каждый раз, когда я запускаю его на Google Computer Engine (GCE), используя их оптимизированную для контейнеров ОС (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?
Следует отметить одну важную вещь (как указано в комментариях) - хотя он может быть привязан к интерфейсу, использующему как IPv4, так и IPv6, маршрутизация IPv6 не будет работать в Google Cloud (пока не поддерживается внутри).
Таким образом, оказывается, что это сбивающая с толку «функция» того, как Docker работает в сети, и он по-прежнему должен разрешать соединения IPv4, а также IPv6.
Видеть этот ответ StackOverflow Больше подробностей. Я процитировал ответ ниже для потомков:
... github.com/docker/docker/issues/2174 показывает привязку только к IPv6 в
netstat
, но это не проблема. Как говорится в этой проблеме на github:При настройке прокси 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
проверять.