LW IT Solutions logo LW IT Solutions logo LW IT Solutions
« Przegląd bloga /IT & Networks/Tutorials / Łańcuchy certyfikatów: dlaczego strona otwiera się w...
Ten artykuł w innych językach:

Łańcuchy certyfikatów: dlaczego strona otwiera się w przeglądarce, a zawodzi w curl

Łańcuchy certyfikatów: dlaczego strona otwiera się w przeglądarce, a zawodzi w curl
Spis treści
  1. Co jest przesyłane w uzgadnianiu
  2. Ogniwo, które ginie
  3. Dlaczego przeglądarka wybacza
  4. Co dwanaście witryn naprawdę wysyła
  5. Nazwy, a nie Common Name
  6. Odczyt bez przeglądarki
  7. Pytania i odpowiedzi
  8. Źródła

Uzgadnianie TLS wygląda jak pojedyncze tak albo nie, ale obejmuje sprawdzenie ścieżki zaufania. Serwer przedstawia certyfikat, a klient musi zbudować od niego ścieżkę do korzenia, któremu już ufa. Sprawdzenie kończy się powodzeniem albo nie, zależnie od tego, który klient je wykonuje.

Właśnie to zaskakuje. Ten sam serwer w tej samej sekundzie bywa uznany przez Chrome i odrzucony przez curl.

Niepełny łańcuch certyfikatów oceniony dwukrotnie: przeglądarka pobiera brakujący certyfikat pośredni i przechodzi, curl nie
Jeden niepełny łańcuch, dwa werdykty – różnicą jest pobranie, które wykonuje tylko jeden z dwóch.

Co jest przesyłane w uzgadnianiu

Serwer wysyła własny certyfikat, zwany końcowym, i zwykle jeden lub dwa powyżej. Certyfikat końcowy niesie nazwy hostów, dla których obowiązuje, klucz publiczny i podpis. Ten podpis nie pochodzi od korzenia, lecz od certyfikatu pośredniego, który z kolei został podpisany przez korzeń.

Sam korzeń nigdy nie jest wysyłany. Leży w magazynie zaufania systemu operacyjnego albo przeglądarki, kilkaset sztuk, i jest jedyną częścią, którą klient ma już u siebie.

Klient potrzebuje zatem wszystkiego między certyfikatem końcowym a tym korzeniem. Jeśli serwer nie wysyła certyfikatu pośredniego, powstaje luka, a luka oznacza brak dowodu.

Ogniwo, które ginie

Niemal każdy urząd certyfikacji dostarcza dwa pliki: sam certyfikat oraz pakiet złożony z certyfikatu i pośredniego. W Let’s Encrypt nazywają się cert.pem i fullchain.pem. Te nazwy nie są ozdobą.

Wpisanie cert.pem tam, gdzie należy fullchain.pem, to najczęstszy błąd konfiguracji TLS w ogóle, a powód jest oczywisty: strona otwiera się potem bez zarzutu. Nic nie ostrzega, nic nie trafia do dziennika, a certyfikat jest naprawdę ważny.

Luka istnieje wyłącznie dla klientów, którzy odmawiają samodzielnego jej domknięcia.

Dlaczego przeglądarka wybacza

W certyfikacie tkwi pole o nazwie Authority Information Access. Zapisany jest w nim między innymi adres: miejsce, z którego da się pobrać wystawiający certyfikat pośredni. Przeglądarki z niego korzystają. Gdy łańcuchowi brakuje ogniwa, pobierają brakujący certyfikat spod tego adresu, uzupełniają ścieżkę i pokazują kłódkę.

Niektóre przeglądarki przechowują dodatkowo w pamięci certyfikaty pośrednie widziane na innych stronach. Utrudnia to odtworzenie problemu: serwer z niepełnym łańcuchem certyfikatów może pozornie działać poprawnie na dwóch komputerach, ale na każdym z innego powodu.

curl, OpenSSL i większość bibliotek HTTP w Pythonie, PHP, Go i Javie tego nie robią. Odczytują to samo pole i je pomijają, ponieważ podążanie za nim zamienia jedno uzgadnianie w dwa obiegi sieciowe i wprowadza w środek połączenia, które ma być bezpośrednie, zależność od obcego hosta. Ta odmowa jest zamierzona.

Powstaje z tego obraz awarii o bardzo wyraźnym kształcie: witryna działa, a ruch między maszynami nie. Operator płatności wywołujący webhook, sonda monitorująca, aplikacja, partner odpytujący API – wszyscy zgłaszają unable to get local issuer certificate, podczas gdy przeglądarka nie pokazuje niczego.

Dwa łańcuchy obok siebie: górny zamknięty, dolny z otwartą luką w miejscu brakującego ogniwa

Co dwanaście witryn naprawdę wysyła

Dwanaście znanych adresów zmierzono 2 września 2026, odczytując wyłącznie to, co serwer zaoferował w uzgadnianiu.

Sześć wysłało trzy certyfikaty, sześć cztery. Ani jedna nie wysłała samego certyfikatu końcowego. Okres ważności był u wszystkich dwunastu taki sam: 90 dni, tyle przyznają wystawcy zautomatyzowani i na tyle ustaliła się branża. Pozostała ważność mieściła się między 31 a 88 dniami, mediana wyniosła 70 – taki rozrzut daje automatyczne odnowienie po dwóch trzecich okresu.

Jedenaście z dwunastu wynegocjowało TLS 1.3, jedna została przy 1.2. Żadna nie przyjęła TLS 1.0. Dziewięć użyło klucza ECDSA zamiast RSA. Osiem certyfikatów pochodziło od Let’s Encrypt, trzy od Google Trust Services, jeden od Sectigo.

Znacznie mocniej niż cokolwiek innego wahała się liczba nazw w certyfikacie: jedna na dolnym końcu, 41 przy wikipedia.org. Ta liczba nie jest znakiem jakości, a jedynie wskazówką, jak zorganizowany jest cały zasób.

Nazwy, a nie Common Name

Druga usterka wygląda z zewnątrz podobnie. Certyfikat jest kompletny i ważny, tylko nie ma w nim danego hosta.

Aktualne przeglądarki całkowicie ignorują Common Name i porównują wyłącznie Subject Alternative Names. Certyfikat dla example.com, w którym brakuje www.example.com, obejmuje dokładnie jeden z dwóch adresów, a przekierowanie między nimi zawodzi, zanim się zacznie.

Symbole wieloznaczne obejmują jeden poziom i ani jednego więcej. *.example.com pasuje do www.example.com, ale ani do example.com, ani do a.b.example.com. Obie połowy tego zdania regularnie kosztują kogoś awarię.

Odczyt bez przeglądarki

Różnicy, o którą chodzi, nie da się zobaczyć w przeglądarce właśnie dlatego, że przeglądarka ją naprawia. Potrzebny jest klient, który tego nie robi.

openssl s_client -connect example.com:443 -servername example.com < /dev/null
curl -vI https://example.com/

W wyniku OpenSSL blok dotyczący łańcucha certyfikatów wypisuje to, co wysłał serwer. Pojedynczy wpis oznacza brak certyfikatu pośredniego, niezależnie od tego, czy wiersz weryfikacji poniżej melduje ok – lokalnie zapamiętany certyfikat pośredni potrafi i jego uczynić mylącym. Wiarygodne jest policzenie tego, co dotarło.

Ten sam odczyt bez wiersza poleceń daje Inspektor certyfikatu i uzgadniania TLS w sekcji Toolbox: otwiera uzgadnianie, weryfikuje raz z magazynem zaufania i raz bez, wypisuje łańcuch dokładnie tak, jak wysłał go serwer, a następnie próbuje osobno każdej wersji TLS. Luka pojawia się jako łańcuch o długości jeden, obok weryfikacji, która zawiodła z powodu wartego przeczytania.

Pytania i odpowiedzi

Czy korzeń powinien być częścią łańcucha, który wysyła serwer?

Nie. Klient i tak musi już ufać korzeniowi, więc dołączony korzeń niczego nie dowodzi i jedynie dokłada bajtów do każdego uzgadniania; RFC 8446 wprost pozwala go pominąć. Liczy się wyłącznie to, żeby obecny był każdy certyfikat pośredni między certyfikatem końcowym a korzeniem, a właśnie to zawiera fullchain.pem.

Łańcuch działał miesiącami, a teraz nadawca webhooka nagle zgłasza unable to get local issuer certificate. Co może być przyczyną?

Jeśli na serwerze nic nie zmieniano, w grę wchodzą przede wszystkim dwie przyczyny, po jednej z każdej strony połączenia:

  1. Zmienił się certyfikat pośredni. Urzędy certyfikacji od czasu do czasu przechodzą na nowe certyfikaty pośrednie. Konfiguracja łącząca cert.pem z plikiem pośrednim zapisanym raz ręcznie wysyła po kolejnym odnowieniu ogniwo, które nie pasuje już do certyfikatu końcowego, a ścieżka ma wtedy tę samą lukę co zupełnie bez certyfikatu pośredniego. fullchain.pem jest przy każdym odnowieniu zapisywany na nowo z pasującym certyfikatem pośrednim i tego problemu nie ma.
  2. Magazyn zaufania klienta jest przestarzały. Jeśli po odnowieniu łańcuch kończy się na innym korzeniu, może go brakować w starych systemach operacyjnych albo w obrazach kontenerów, których dawno nie przebudowano. Komunikat jest ten sam, choć serwer wysyła wszystko poprawnie.

Która z tych przyczyn zachodzi, rozstrzyga ponowne liczenie: jeśli openssl s_client pokazuje, że docierają certyfikat końcowy i pośredni, a aktualny system weryfikuje łańcuch, problem leży w magazynie zaufania nadawcy i pomoże tylko aktualizacja jego listy urzędów certyfikacji.

Źródła

Lukas Wójcik

Lukas Wójcik

Systems architect and technology enthusiast specializing in scalable tracking solutions, GMP Stack (GA4 & GTM), and robust backend architectures. Advocate for clean code and privacy-first design.

Kontakt

Masz pytanie lub pomysł na projekt internetowy? Napisz krótko, o co chodzi. Formularz korzysta z reCAPTCHA do ochrony przed spamem.

Napisanie komentarza

Doświadczenia z innym sprzętem lub inną wersją oprogramowania oraz pytania o konfigurację są tu mile widziane.

Adres e-mail nie jest publikowany. Pola obowiązkowe oznaczono gwiazdką.