Wtyczka nie łączy się ze sklepem w Dockerze?Migracja i konfiguracja serwera
← Blog
WooCommerce

WooCommerce w Dockerze: cURL error 28 przy podłączaniu Furgonetki. NAT hairpin

WooCommerce Auth woła własną domenę z serwera, a kontener jej nie widzi. Jedno polecenie curl pokazuje, czy to hairpin, a po zmianie w Cloudflare trzeba jeszcze wyczyścić cache DNS na hoście.

Błąd cURL error 28: Connection timed out after 10002 milliseconds przy podłączaniu wtyczki Furgonetka do WooCommerce w Dockerze oznacza zwykle, że kontener nie może połączyć się z własną domeną. Winny jest NAT hairpin zablokowany przez politykę DROP na hoście, a nie wtyczka. Poniżej pokazujemy, jak to rozpoznać jednym poleceniem, dlaczego drugi sklep na tym samym serwerze działał przypadkiem i co naprawia flush DNS po zmianie w Cloudflare.

Skąd bierze się cURL error 28 przy autoryzacji WooCommerce?

Podłączanie wtyczki kończyło się na adresie /wc-auth/v1/access_granted/ błędem z timeoutem 10 sekund. WooCommerce Auth przy access_granted robi POST z serwera na przekazany callback_url. U nas adres zwrotny wtyczki leżał na domenie sklepu, więc potrzebna była działająca pętla zwrotna HTTP z kontenera z PHP.

Dlaczego kontener nie łączy się z własną domeną?

DNS w kontenerze zwracał publiczny adres hosta, bo rekord w Cloudflare był w trybie bez proxy. Pakiet z sieci bridge Dockera na publiczny adres własnego hosta wraca jako ruch przychodzący na łańcuch INPUT, gdzie policy DROP go odrzuca. Ruch z zewnątrz działa, bo wchodzi łańcuchem DOCKER w FORWARD i omija INPUT.

ŚcieżkaWynik
kontener do nginx po adresie wewnętrznym200, 0,16 ms
kontener do domeny sklepu (adres publiczny)timeout, połączenie nigdy nie startuje
host do własnego adresu publicznego200, 2 ms
kontener do Google200 (wyjście na świat sprawne)

W regułach zapory nie było akceptacji dla portów 80 i 443 w łańcuchu wejściowym (INPUT).

Dlaczego drugi sklep na tym serwerze działał bez problemu?

To fałszywy trop. Drugi sklep robił pętlę zwrotną bez błędu, ale tylko dlatego, że miał włączony tryb proxy w Cloudflare. Ruch szedł wtedy do Cloudflare i wracał z zewnątrz, omijając hairpin. Nie był poprawnie skonfigurowany, tylko przypadkiem omijał wadę. To też nie regresja po innych zmianach: wada sieci istniała od zawsze, tylko nic wcześniej nie potrzebowało pętli zwrotnej.

Jak szybko sprawdzić pętlę zwrotną z kontenera?

Pierwszy krok przy cURL error 28 to test z wnętrza kontenera, nie przeglądanie wtyczki:

docker exec <kontener-wp> curl -s -o /dev/null \
  -w 'code:%{http_code} connect:%{time_connect} ip:%{remote_ip}\n' \
  --max-time 10 https://<domena>/wp-json/

Kod 000 przy connect:0.000000 oznacza, że nie udało się nawiązać połączenia TCP, więc szukaj w sieci, DNS albo zaporze, a nie w PHP. Dodaj flagę -v, żeby zobaczyć komunikat błędu, i sprawdź, na jaki adres kontener naprawdę celuje:

docker exec <kontener-wp> getent ahostsv4 <domena>

Masz ten sam problem? Wtyczka nie łączy się z własną domeną w Dockerze? Sprawdzimy zaporę, DNS i sieć kontenerów. Opisz sytuację →

Jak naprawić pętlę zwrotną przez Cloudflare i flush DNS?

W jednym ze sklepów włączyliśmy tryb proxy w Cloudflare. Samo to nie wystarczyło, kontener nadal dostawał timeout, z dwóch powodów:

  • resolver zwracał świeży rekord AAAA, a kontener nie miał IPv6 (brak adresu i trasy), więc był bezużyteczny,
  • dla IPv4 zwracał stary, zakeszowany adres hosta, czyli wracaliśmy do hairpin.

W naszej konfiguracji (domyślny resolver Dockera przekazujący zapytania do systemd-resolved na hoście) stary rekord siedział w cache hosta. Naprawa to jedno polecenie, bez zmian w zaporze ani w compose:

resolvectl flush-caches

Po flushu kontener dostawał adresy Cloudflare, a pętla zwrotna odpowiadała 200 w 0,19 s. Callback wtyczki zwracał 401 po 0,26 s, a access_granted 401 po 0,22 s. Kod 401 jest tu poprawny: ścieżka jest drożna, a serwer odmawia bez tokenu. Wcześniej był timeout po 10 sekundach.

Na przyszłość. Jeśli kontenery używają resolvera hosta z systemd-resolved, po zmianie trybu rekordu w Cloudflare (bez proxy lub z proxy) wykonaj resolvectl flush-caches na hoście. Inaczej kontenery przez wiele minut trzymają stary rekord.

Jak naprawić hairpin na stałe na wszystkich sklepach serwera?

Drugi sklep na serwerze, bez proxy, miał ten sam problem i ujawniłby się przy WooCommerce Auth, WP-Cron po HTTP albo webhookach zwrotnych. Są dwie drogi:

  • Tryb proxy w Cloudflare dla domeny, zero zmian na serwerze, najprostsze.
  • Reguła zapory dla mostów tworzonych przez docker compose (br-*), obejmująca wszystkie takie stacki na serwerze:
iptables -I INPUT -i br-+ -p tcp -m multiport --dports 80,443 -j ACCEPT

Reguła obejmuje mosty br-*, a nie interfejs zewnętrzny, więc nic nie wystawia na zewnątrz. Domyślny most docker0 ma inną nazwę, więc ścieżkę pakietu i interfejs sprawdź na swoim serwerze, na przykład licznikami reguł. Wymaga utrwalenia (na przykład iptables-persistent), bo inaczej ginie po restarcie serwera.

Kiedy zlecić to specjalistom?

Gdy wtyczki, które wołają własną domenę (Furgonetka, WooCommerce Auth, webhooki, WP-Cron), zgłaszają timeouty, a w logach PHP nie ma błędu. W ASAPDevs sprawdzamy sieć kontenerów, zaporę i DNS w ramach migracji i konfiguracji serwera oraz stałej opieki nad WordPressem. O innych awariach środowiska Docker piszemy w artykule o sklepie offline przez pełny dysk.

Źródła: dokumentacja Docker, Packet filtering and firewalls (łańcuchy iptables, DOCKER-USER).

Kamil Perzowski
Kamil Perzowski
CEO i co-founder ASAPDevs. Programuje i utrzymuje sklepy, aplikacje webowe i serwery klientów. LinkedIn · Migracja i konfiguracja serwera
Masz ten sam problem?

Wtyczka nie łączy się ze sklepem w Dockerze?

Kamil Perzowski, ASAPDevs
Kamil Perzowski
CEO & Co-founder, ASAPDevs
Sprawdzamy sieć kontenerów, zaporę i DNS, naprawiamy pętlę zwrotną i testujemy wtyczki, które wołają własną domenę.
★★★★★
Rekomenduję. Jestem zadowolona ze współpracy. Firma jest terminowa, rzetelnie wywiązuje się ze zobowiązań. Pełen profesjonalizm i rzadka cecha u informatyków – empatia, życzliwe i cierpliwe wsparcie.
Beata M., opinia w Google
  1. Czytam zgłoszenie i odpisuję z pytaniami albo propozycją terminu rozmowy.
  2. Krótka rozmowa o zakresie, dostępach i terminie.
  3. Dostajesz plan i wycenę. Decydujesz, bez zobowiązań.

Wolisz od razu porozmawiać? +48 884 220 764 · [email protected]

Wysyłając formularz, przekazujesz nam dane, żebyśmy mogli odpowiedzieć. Szczegóły w polityce prywatności.

FAQ

Pytania i odpowiedzi

Co oznacza cURL error 28 przy łączeniu wtyczki Furgonetka z WooCommerce?

+
Połączenie z serwera sklepu wygasło po 10 sekundach. WooCommerce Auth przy zatwierdzaniu dostępu wysyła żądanie POST z serwera na adres zwrotny wtyczki. Gdy ten adres leży na domenie sklepu, potrzebna jest działająca pętla zwrotna HTTP.

Dlaczego sklep w Dockerze nie może połączyć się sam ze sobą po domenie?

+
DNS w kontenerze może zwracać publiczny adres hosta. Pakiet z sieci bridge na publiczny adres własnego hosta wraca jako ruch przychodzący, gdzie domyślna polityka DROP go odrzuca. Ruch z zewnątrz działa, bo wchodzi łańcuchem DOCKER i omija INPUT.

Dlaczego drugi sklep na tym samym serwerze działa bez problemu?

+
Prawdopodobnie ma włączony tryb proxy w Cloudflare, więc ruch idzie do Cloudflare i wraca z zewnątrz, omijając hairpin. Nie jest poprawnie skonfigurowany, tylko przypadkiem omija wadę sieci.

Po włączeniu proxy w Cloudflare kontener nadal ma timeout. Dlaczego?

+
U nas stary rekord siedział w cache resolvera hosta (systemd-resolved), z którego korzystał kontener. Po zmianie trybu rekordu w Cloudflare wykonaj na hoście resolvectl flush-caches.

Jak szybko sprawdzić pętlę zwrotną z kontenera?

+
Wywołaj curl z wnętrza kontenera na własną domenę i odczytaj kod, czas połączenia oraz adres IP. Kod 000 i czas połączenia 0 oznaczają, że połączenie TCP się nie nawiązało: to problem sieci, DNS lub zapory, a nie PHP.

Przeczytaj też