SystemdDoctor
мешает работе сокеты сеть

Сокет слушает только IPv6 или только IPv4 неожиданно

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

Вероятные причины

По порядку: сверху то, что встречается чаще.

  1. Включён режим только одного протокола

    При включённом режиме сокет принимает соединения только по IPv6, и клиенты по IPv4 получают отказ.

  2. Настройка ядра меняет поведение по умолчанию

    Значение по умолчанию наследует системную настройку. Она различается между дистрибутивами и может быть изменена локально.

  3. Два слушателя конфликтуют за один порт

    Отдельные слушатели на IPv4 и IPv6 при включённом двойном стеке конфликтуют: второй не может занять порт.

Диагностика

Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.

На каких адресах и протоколах открыт порт.

sudo ss -tlnp | grep :8080

Объявленные слушатели и режим двойного стека.

systemctl show myapp.socket -p BindIPv6Only -p ListenStream

Проверка со стороны клиента по IPv4.

timeout 3 bash -c "</dev/tcp/127.0.0.1/8080" && echo IPv4 открыт || echo IPv4 закрыт

Решение

Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.

1. Включён режим только одного протокола
Почему происходит
При включённом режиме сокет принимает соединения только по IPv6, и клиенты по IPv4 получают отказ.
Как проверить
Посмотрите параметр и слушателей.
systemctl show myapp.socket -p BindIPv6Only
sudo ss -tlnp | grep :8080
Как исправить
Выберите поведение осознанно. Значение по умолчанию берёт настройку ядра, из-за чего одна и та же конфигурация ведёт себя по-разному на разных машинах.
[Socket]
ListenStream=8080
BindIPv6Only=both
2. Настройка ядра меняет поведение по умолчанию
Почему происходит
Значение по умолчанию наследует системную настройку. Она различается между дистрибутивами и может быть изменена локально.
Как проверить
Посмотрите настройку ядра.
sysctl net.ipv6.bindv6only
Как исправить
Задавайте параметр в описании сокета явно, не полагаясь на системное значение. Иначе перенос службы на другую машину меняет поведение.
3. Два слушателя конфликтуют за один порт
Почему происходит
Отдельные слушатели на IPv4 и IPv6 при включённом двойном стеке конфликтуют: второй не может занять порт.
Как проверить
Посмотрите объявленные слушатели.
systemctl cat myapp.socket | grep -E "^Listen"
sudo ss -tlnp | grep :8080
Как исправить
Оставьте один слушатель с нужным режимом двойного стека вместо двух явных.

Пример вывода

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

$ sudo ss -tlnp | grep :8080
LISTEN 0 4096 [::]:8080 [::]:* users:(("systemd",pid=1,fd=42))

$ timeout 3 bash -c "</dev/tcp/127.0.0.1/8080" || echo отказ
отказ
$ systemctl show myapp.socket -p BindIPv6Only
BindIPv6Only=ipv6-only

Связанные ошибки

Источники

  • systemd.socket(5)
    BindIPv6Only= и поведение двойного стека.
    официальная документация, systemd 255
    сверено 15 сентября 2026
  • Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
    Проверено на systemd 255: режим только IPv6 отвергает соединения по IPv4.
    собственная проверка, systemd 255
    сверено 15 сентября 2026