Таймаут HTTP с сетью моста Docker, но порт 80 открыт в файрволе.

Вопрос или проблема

Я пытаюсь установить mailcow-dockerized на своем сервере, но у меня есть проблемы с сетью Docker. Я пробовал несколько способов, но у меня много таймаутов соединения в контейнерах.

Чтобы разобраться с проблемой, я решил оставить Mailcow и установил только Docker, чтобы попытаться выявить источник этих таймаутов соединения.

Итак, я установил свежий образ Ubuntu 20.04 от моего провайдера VPS и настроил брандмауэр ufw следующим образом:

sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw limit ssh
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw allow smtp
sudo ufw allow submission
sudo ufw allow submissions
sudo ufw allow pop3
sudo ufw allow pop3s
sudo ufw allow imap2
sudo ufw allow imaps
sudo ufw allow 4190/tcp
sudo ufw allow 8080/tcp
sudo systemctl enable ufw
sudo ufw enable

Я установил Docker с помощью скрипта get-docker.sh с https://get.docker.com

Затем я включил IPV6 в файле /etc/docker/daemon.json следующим образом:

{
  "ipv6": true,
  "fixed-cidr-v6": "2001:db8:1::/64"
}

Перезагрузил сервер и создал файл docker-compose.yaml:

version: '2.1'
services:
    S2:
      image: nginx:latest
      ports:
        - 80:80
      restart: always
      networks:
        n1:
          ipv4_address: 172.22.1.254
          aliases:
            - s2
    S3:
      image: nginx:latest
      ports:
        - 8080:80
      restart: always
      networks:
        n1:
          ipv4_address: 172.22.1.248
          aliases:
            - s3
networks:
  n1:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: n1
    enable_ipv6: true
    ipam:
      driver: default
      config:
        - subnet: 172.22.1.0/24
        - subnet: fd4d:6169:6c63:6f77::/64

Эту конфигурацию сети я взял из docker-compose.yaml в репозитории Mailcow и изменил ее, чтобы адаптировать к своему тесту.

И я запустил контейнеры с помощью docker-compose up -d.

Когда я выполняю curl localhost 80 на хост-сервере, он возвращает стандартное содержимое index.html от Nginx, но… соединение зависает на несколько минут, а затем в терминале появляется следующее сообщение в конце:

curl: (28) Failed to connect to 80 port 80: Connection timed out

Когда я запускаю curl <myservername.com> 80 на своем локальном компьютере, он также возвращает содержимое index.html от стандартного Nginx, но с сообщением в конце:

curl: (7) Failed to connect to 0.0.0.80 port 80 after 0 ms: Network unreachable

Есть ли какие-либо подсказки о том, почему я получаю эти ошибки?

PS: статус моего ufw:

# ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW IN    Anywhere
80/tcp                     ALLOW IN    Anywhere
443/tcp                    ALLOW IN    Anywhere
25/tcp                     ALLOW IN    Anywhere
587/tcp                    ALLOW IN    Anywhere
465/tcp                    ALLOW IN    Anywhere
110/tcp                    ALLOW IN    Anywhere
995/tcp                    ALLOW IN    Anywhere
143/tcp                    ALLOW IN    Anywhere
993/tcp                    ALLOW IN    Anywhere
4190/tcp                   ALLOW IN    Anywhere
8080/tcp                   ALLOW IN    Anywhere
22/tcp (v6)                ALLOW IN    Anywhere (v6)
80/tcp (v6)                ALLOW IN    Anywhere (v6)
443/tcp (v6)               ALLOW IN    Anywhere (v6)
25/tcp (v6)                ALLOW IN    Anywhere (v6)
587/tcp (v6)               ALLOW IN    Anywhere (v6)
465/tcp (v6)               ALLOW IN    Anywhere (v6)
110/tcp (v6)               ALLOW IN    Anywhere (v6)
995/tcp (v6)               ALLOW IN    Anywhere (v6)
143/tcp (v6)               ALLOW IN    Anywhere (v6)
993/tcp (v6)               ALLOW IN    Anywhere (v6)
4190/tcp (v6)              ALLOW IN    Anywhere (v6)
8080/tcp (v6)              ALLOW IN    Anywhere (v6)

А вот результаты lsof:

# lsof -i -P -n | grep LISTEN
sshd       967 root    3u  IPv4  35459      0t0  TCP *:22 (LISTEN)
sshd       967 root    4u  IPv6  35461      0t0  TCP *:22 (LISTEN)
docker-pr 1290 root    4u  IPv4  39102      0t0  TCP *:80 (LISTEN)
docker-pr 1308 root    4u  IPv6  38124      0t0  TCP *:80 (LISTEN)
docker-pr 1322 root    4u  IPv4  38165      0t0  TCP *:8080 (LISTEN)
docker-pr 1328 root    4u  IPv6  38172      0t0  TCP *:8080 (LISTEN)

Мониторинг Termshark при выполнении curl localhost 80 на хосте:

 No. -  Time -   Source -       Destination -  Protocol -   Length - Info -                                      
 1      0.000000 fd4d:6169:6c63 fd4d:6169:6c63 TCP          94       39946 → 80 [SYN] Seq=0 Win=64800 Len=0 MSS= 
 2      0.000047 fd4d:6169:6c63 fd4d:6169:6c63 TCP          94       80 → 39946 [SYN, ACK] Seq=0 Ack=1 Win=64260
 3      0.000088 fd4d:6169:6c63 fd4d:6169:6c63 TCP          86       39946 → 80 [ACK] Seq=1 Ack=1 Win=64896 Len=
 4      0.000516 fd4d:6169:6c63 fd4d:6169:6c63 HTTP         159      GET / HTTP/1.1
 5      0.000544 fd4d:6169:6c63 fd4d:6169:6c63 TCP          86       80 → 39946 [ACK] Seq=1 Ack=74 Win=64256 Len
 6      0.000765 fd4d:6169:6c63 fd4d:6169:6c63 TCP          324      HTTP/1.1 200 OK  [TCP segment of a reassemb
 7      0.000791 fd4d:6169:6c63 fd4d:6169:6c63 TCP          86       39946 → 80 [ACK] Seq=74 Ack=239 Win=64768 L
 8      0.000821 fd4d:6169:6c63 fd4d:6169:6c63 HTTP         701      HTTP/1.1 200 OK  (text/html)
 9      0.000829 fd4d:6169:6c63 fd4d:6169:6c63 TCP          86       39946 → 80 [ACK] Seq=74 Ack=854 Win=64256 L 
 10     65.01291 fd4d:6169:6c63 fd4d:6169:6c63 TCP          86       80 → 39946 [FIN, ACK] Seq=854 Ack=74 Win=64
 11     65.05677 fd4d:6169:6c63 fd4d:6169:6c63 TCP          86       39946 → 80 [ACK] Seq=74 Ack=855 Win=64256 L
 12     130.8576 fd4d:6169:6c63 fd4d:6169:6c63 TCP          86       39946 → 80 [FIN, ACK] Seq=74 Ack=855 Win=64
 13     130.8577 fd4d:6169:6c63 fd4d:6169:6c63 TCP          74       80 → 39946 [RST] Seq=855 Win=0 Len=0
 14     131.0647 fd4d:6169:6c63 fd4d:6169:6c63 TCP          86       [TCP Retransmission] 39946 → 80 [FIN, ACK]
 15     131.0648 fd4d:6169:6c63 fd4d:6169:6c63 TCP          74       80 → 39946 [RST] Seq=855 Win=0 Len=0        
 16     131.2727 fd4d:6169:6c63 fd4d:6169:6c63 TCP          86       [TCP Retransmission] 39946 → 80 [FIN, ACK]
 17     131.2728 fd4d:6169:6c63 fd4d:6169:6c63 TCP          74       80 → 39946 [RST] Seq=855 Win=0 Len=0
 18     131.6888 fd4d:6169:6c63 fd4d:6169:6c63 TCP          86       [TCP Retransmission] 39946 → 80 [FIN, ACK]  
 19     131.6888 fd4d:6169:6c63 fd4d:6169:6c63 TCP          74       80 → 39946 [RST] Seq=855 Win=0 Len=0
 20     132.5208 fd4d:6169:6c63 fd4d:6169:6c63 TCP          86       [TCP Retransmission] 39946 → 80 [FIN, ACK]
 21     132.5209 fd4d:6169:6c63 fd4d:6169:6c63 TCP          74       80 → 39946 [RST] Seq=855 Win=0 Len=0
 22     134.1847 fd4d:6169:6c63 fd4d:6169:6c63 TCP          86       [TCP Retransmission] 39946 → 80 [FIN, ACK]
 23     134.1850 fd4d:6169:6c63 fd4d:6169:6c63 TCP          74       80 → 39946 [RST] Seq=855 Win=0 Len=0
 24     137.5129 fd4d:6169:6c63 fd4d:6169:6c63 TCP          86       [TCP Retransmission] 39946 → 80 [FIN, ACK]  
 25     137.5131 fd4d:6169:6c63 fd4d:6169:6c63 TCP          74       80 → 39946 [RST] Seq=855 Win=0 Len=0        

Результаты Termshark при выполнении curl <myserver.com> 80 на моем компьютере:

 No. -  Time -   Source -       Destination -  Protocol -   Length - Info -                                      
 1      0.000000 170.78.36.7    172.22.1.254   TCP          66       62787 → 80 [SYN] Seq=0 Win=64240 Len=0 MSS= 
 2      0.000063 172.22.1.254   170.78.36.7    TCP          66       80 → 62787 [SYN, ACK] Seq=0 Ack=1 Win=64240
 3      0.007119 170.78.36.7    172.22.1.254   TCP          54       62787 → 80 [ACK] Seq=1 Ack=1 Win=131840 Len
 4      0.009563 170.78.36.7    172.22.1.254   HTTP         133      GET / HTTP/1.1
 5      0.009628 172.22.1.254   170.78.36.7    TCP          54       80 → 62787 [ACK] Seq=1 Ack=80 Win=64256 Len
 6      0.009884 172.22.1.254   170.78.36.7    TCP          292      HTTP/1.1 200 OK  [TCP segment of a reassemb
 7      0.010001 172.22.1.254   170.78.36.7    HTTP         669      HTTP/1.1 200 OK  (text/html)
 8      0.019889 170.78.36.7    172.22.1.254   TCP          54       62787 → 80 [ACK] Seq=80 Ack=854 Win=130816
 9      0.039001 170.78.36.7    172.22.1.254   TCP          54       62787 → 80 [FIN, ACK] Seq=80 Ack=854 Win=13 
 10     0.039211 172.22.1.254   170.78.36.7    TCP          54       80 → 62787 [FIN, ACK] Seq=854 Ack=81 Win=64 
 11     0.046453 170.78.36.7    172.22.1.254   TCP          54       62787 → 80 [ACK] Seq=81 Ack=855 Win=130816  

Будьте осторожны, что с некоторыми брандмауэрами Docker добавляет специфические правила для правильной работы. Я не уверен, связано ли это также с UFW, но может быть.

Когда это произошло со мной с Iptables, мне пришлось добавить некоторые правила для перенаправления входящего соединения на конкретном порту к конкретному порту моего сервиса в сети Docker. Так что если я получаю соединение на порту 80, но мой контейнеризованный сервис открывает порт 8080, в некоторых случаях, даже если вы указываете отображение: “80:8080”, все равно необходимо добавить некоторые правила перенаправления к вашему брандмауэру.

Еще одна вещь, которую вы можете проверить дважды, это сможет ли хост-сервер “позвонить” самому себе.

Одна команда, которая может помочь вам в диагностике,:

curl -Ivvv host port

Я изменил область моего теста на простой VPS-сервер с установленным NGinx, без Docker, и проблема таймаута http сохранялась, так что… я выяснил, что проблема была вызвана инфраструктурой моего локального провайдера VPS…

Я сменил своего провайдера на другого, и все заработало отлично…

Ответ или решение

Решение проблем с тайм-аутами HTTP в Docker при использовании сетевого моста

Введение

Отказ в соединениях и тайм-ауты HTTP в контейнерах Docker на сервере могут возникать по различным причинам, даже если порты в брандмауэре открыты. В данном анализе мы рассмотрим ситуацию, когда вы пытаетесь установить Mailcow на чистый образ Ubuntu 20.04 и сталкиваетесь с тайм-аутами, несмотря на открытые порты в UFW. Вы будете наглядно изучать все шаги, от настройки Docker до изучения вариантов возникновения проблемы.

Конфигурация системы

Ваша конфигурация системы включает следующие элементы:

  1. Установка и настройка UFW:

    sudo ufw default allow outgoing
    sudo ufw default deny incoming
    sudo ufw limit ssh
    sudo ufw allow ssh
    sudo ufw allow http
    sudo ufw allow https
    sudo ufw allow smtp
    sudo ufw allow submission
    sudo ufw allow pop3
    sudo ufw allow pop3s
    sudo ufw allow imap2
    sudo ufw allow imaps
    sudo ufw allow 4190/tcp
    sudo ufw allow 8080/tcp
    sudo systemctl enable ufw
    sudo ufw enable
  2. Настройка Docker с поддержкой IPv6:

    {
     "ipv6": true,
     "fixed-cidr-v6": "2001:db8:1::/64"
    }
  3. Создание docker-compose файла:

    version: '2.1'
    services:
       S2:
         image: nginx:latest
         ports:
           - 80:80
         restart: always
         networks:
           n1:
             ipv4_address: 172.22.1.254
             aliases:
               - s2
       S3:
         image: nginx:latest
         ports:
           - 8080:80
         restart: always
         networks:
           n1:
             ipv4_address: 172.22.1.248
             aliases:
               - s3
    networks:
     n1:
       driver: bridge
       driver_opts:
         com.docker.network.bridge.name: n1
       enable_ipv6: true
       ipam:
         driver: default
         config:
           - subnet: 172.22.1.0/24
           - subnet: fd4d:6169:6c63:6f77::/64

Проблемы с подключением и их диагностика

При попытке подключения к Nginx, запущенному в контейнере Docker, вы столкнулись со следующими проблемами:

  • Локальный хост:

    curl localhost 80
    curl: (28) Failed to connect to 80 port 80: Connection timed out
  • С удаленного компьютера:

    curl <myservername.com> 80
    curl: (7) Failed to connect to 0.0.0.80 port 80 after 0 ms: Network unreachable

Варианты решения:

  1. Проблемы с маршрутизацией или сетевыми настройками:
    Иногда конфигурация сети Docker может мешать установлению соединений. Убедитесь, что пакеты направляются должным образом в соответствии с правилами маршрутизации.

  2. Проблемы с конфигурацией iptables:
    Docker автоматически добавляет правила в iptables для управления трафиком. Ваша конфигурация UFW может конфликтовать с этими правилами. Проверьте с помощью команды:

    sudo iptables -L -n -v

    Возможно, вам потребуется добавить правила для пересылки трафика.

  3. Проверка состояния UFW:
    Убедитесь, что UFW действительно позволяет входящие соединения на порты 80 и 8080. Проверьте это командой:

    sudo ufw status verbose
  4. Использование инструментов диагностики:
    Для более детальной диагностики используйте команды:

    curl -Ivvv localhost:80
    curl -Ivvv <myservername.com>:80
  5. Проверка работы на другом VPS:
    Вы упомянули, что проблема исчезла при смене хостинг-провайдера. Это могло быть связано с сетевой инфраструктурой вашего предыдущего провайдера. Всегда полезно проверить ваше приложение на другом сервере, чтобы исключить влияние оборудования или сетевой конфигурации.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...