ბრაუზერის ყველა სერტიფიკატის გაფრთხილება დაახლოებით ექვსი პრობლემიდან ერთ-ერთია და შეცდომის კოდი გეუბნება, რომელი. NET::ERR_CERT_DATE_INVALID ნიშნავს, რომ სერტიფიკატს ვადა გაუვიდა ან დამთვალიერებლის საათი არასწორია. NET::ERR_CERT_COMMON_NAME_INVALID ნიშნავს, რომ სერტიფიკატი სხვა სახელზეა გაცემული. NET::ERR_CERT_AUTHORITY_INVALID ნიშნავს, რომ ბრაუზერი ვერ აღწევს იმ ორგანიზაციამდე, რომელსაც ენდობა - ეს ან self-signed სერტიფიკატია, ან სერვერმა თავისი შუალედური სერტიფიკატი არ გამოგზავნა. ERR_SSL_PROTOCOL_ERROR ნიშნავს, რომ ორი მხარე სერტიფიკატის დათვალიერებამდე საერთოდ ვერ მივიდა. ხოლო საკეტი წარწერით "Not secure" სრულიად ვალიდური სერტიფიკატის გვერდით mixed content-ია. წაიკითხე კოდი, გაუშვი ერთი openssl ბრძანება შენი ქსელის გარეთ მდებარე მანქანიდან და გამოსწორება, როგორც წესი, კონფიგურაციის ერთი ხაზია.
ეს პოსტი თემის პრობლემების მოგვარების ნაწილია. როგორ გაიცემა და როგორ ახლდება სერტიფიკატები, წერია პოსტში HTTPS და Let's Encrypt მარტივად, ხოლო დომენის სერვერზე მიმართვა, რომ სერტიფიკატი საერთოდ გაიცეს, აღწერილია პოსტში დომენის სერვერზე მიმართვა და SSL-ის დამატება.
ყველაფერს წინ შეცდომის კოდი წაიკითხე#
წითელი გვერდი იმისთვის არის შექმნილი, რომ დამთვალიერებელი დააფრთხოს და არა იმისთვის, რომ გიშველოს, ამიტომ სასარგებლო ნაწილი პატარაა. Chrome-სა და Edge-ში ეს ახსნის ქვეშ მდებარე ნაცრისფერი კოდია ან "Advanced"-ის უკან. Firefox-შიც "Advanced"-ის უკანაა და სხვანაირად იწერება. Safari უმეტესად წერს "This Connection Is Not Private" და მიზეზს ფარავს "Show Details"-ისა და "view the certificate"-ის უკან.
| Chrome / Edge | Firefox | რას ნიშნავს |
|---|---|---|
NET::ERR_CERT_DATE_INVALID | SEC_ERROR_EXPIRED_CERTIFICATE | ვადაგასულია, ჯერ არ არის ძალაში ან საათი არასწორია |
NET::ERR_CERT_COMMON_NAME_INVALID | SSL_ERROR_BAD_CERT_DOMAIN | სერტიფიკატში ეს სახელი არ არის |
NET::ERR_CERT_AUTHORITY_INVALID | SEC_ERROR_UNKNOWN_ISSUER | უცნობი გამცემი ან დაკარგული შუალედური სერტიფიკატი |
NET::ERR_CERT_AUTHORITY_INVALID | MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT | self-signed სერტიფიკატი |
ERR_SSL_PROTOCOL_ERROR | SSL_ERROR_RX_RECORD_TOO_LONG | ამ პორტზე TLS არ არის, ხშირად უბრალო HTTP-ა |
ERR_SSL_VERSION_OR_CIPHER_MISMATCH | SSL_ERROR_NO_CYPHER_OVERLAP | საერთო TLS ვერსია ან cipher არ არის |
NET::ERR_CERT_REVOKED | SEC_ERROR_REVOKED_CERTIFICATE | გამცემმა სერტიფიკატი გააუქმა |
ამ გვერდზე ყურადღება მიაქციე კიდევ ორ რამეს. პირველი, არის თუ არა ბმული "Proceed anyway": თუ არ არის, საიტს HSTS აქვს ჩართული (ან HSTS-ის preload სიაში შემავალ დომენზეა, მაგალითად ყველაფერი .dev და .app ქვეშ) და ბრაუზერი არავის აძლევს გაგრძელების საშუალებას. ეს HSTS-ის საქმეა და ცალკე გაუმართაობა არ არის. მეორე, ვის უჩანს. გაფრთხილება, რომელსაც მხოლოდ ერთი ადამიანი ხედავს, თითქმის ყოველთვის მისი მანქანის ბრალია - საათი, ანტივირუსი, კორპორატიული proxy, სასტუმროს wifi. გაფრთხილება, რომელსაც ყველა ხედავს, სერვერის პრობლემაა.
შეამოწმე გარედან openssl s_client-ით#
ბრაუზერს აქვს cache, შენახული გამონაკლისები და შუალედური სერტიფიკატების საკუთარი ასლები, რომლებიც სხვაგან აიღო. openssl s_client-ს არაფერი ეს არ აქვს. ის უერთდება, ასრულებს handshake-ს, ზუსტად იმას ბეჭდავს, რაც სერვერმა გამოგზავნა, და გეუბნება, გადის თუ არა ვერიფიკაცია. გაუშვი სერვერისგან განსხვავებულ ქსელში მყოფი მანქანიდან, რადგან ადგილობრივი DNS-ის გადაფარვა ან hosts ფაილის ჩანაწერი სიამოვნებით გაჩვენებს სხვა სერვერს, ვიდრე სამყარო ხედავს.
$ openssl s_client -connect example.com:443 -servername example.com </dev/null-servername მნიშვნელოვანია. ის SNI-ს აგზავნის - handshake-ის იმ ნაწილს, რომელიც ბევრ საიტს ჰოსტინგის სერვერს ეუბნება, რომელი სერტიფიკატი გინდა. მის გარეშე იღებ იმას, რასაც სერვერი ნაგულისხმევად თვლის, ეს კი ხშირად არასწორი სერტიფიკატია და არარსებულ პრობლემას გადაგდევნებს. OpenSSL-ის ახალი ვერსიები SNI-ს -connect-ის ჰოსტიდან ავტომატურად აგზავნიან, ძველები კი - არა, ამიტომ ყოველთვის მიუთითე. </dev/null აკავშირებს მაშინვე, როგორც კი handshake დასრულდება, და არ ელოდება, რომ HTTP მოთხოვნა აკრიფო.
გამოტანა გრძელია. სამი მნიშვნელოვანი ნაწილი:
Certificate chain 0 s:CN = example.com i:C = US, O = Let's Encrypt, CN = R11 1 s:C = US, O = Let's Encrypt, CN = R11 i:C = US, O = Internet Security Research Group, CN = ISRG Root X1...Verify return code: 0 (ok)chain ჩამოთვლის იმას, რაც სერვერმა გამოგზავნა: 0 არის leaf (შენი სერტიფიკატი), s: არის subject, i: კი issuer. თითოეული სერტიფიკატის issuer შემდეგის subject უნდა იყოს და ბოლოს ისეთ რამეზე უნდა მიდიოდეს, რომელსაც ბრაუზერი ენდობა. შუალედური სერტიფიკატების სახელები დროთა განმავლობაში იცვლება, ამიტომ არ ინერვიულო, თუ შენი R11 არ არის; იმას ინერვიულე, თუ მხოლოდ 0 ხაზია. ბოლო ხაზი განაჩენია. 0 (ok) ნიშნავს, რომ chain შენი სისტემის trust store-ის მიხედვით გადის. ყველაფერი დანარჩენი შეცდომაა, OpenSSL-ის სიტყვებით.
თარიღებისა და სახელების გასაგებად, ზედმეტი ხმაურის გარეშე, გაატარე სერტიფიკატი openssl x509-ში:
$ openssl s_client -connect example.com:443 -servername example.com </dev/null \ 2>/dev/null | openssl x509 -noout -subject -issuer -dates -ext subjectAltName-ext-ს OpenSSL 1.1.1 ან უფრო ახალი სჭირდება. ძველ სისტემაზე გამოიყენე -text და X509v3 Subject Alternative Name ბლოკი თვალით მოძებნე.
ვერიფიკაციის კოდები, რომლებსაც რეალურად შეხვდები:
| კოდი | შეტყობინება | მნიშვნელობა |
|---|---|---|
10 | certificate has expired | განახლება ჩავარდა ან არასოდეს დაყენებულა |
18 | self-signed certificate | leaf თავისივე გასაღებით არის ხელმოწერილი |
19 | self-signed certificate in certificate chain | კლიენტისთვის უცნობი კერძო CA |
20 | unable to get local issuer certificate | chain არასრულია ან trust store არ არის |
21 | unable to verify the first certificate | სერვერმა leaf შუალედური სერტიფიკატის გარეშე გამოგზავნა |
62 | hostname mismatch | სახელი სერტიფიკატში არ არის (-verify_hostname-ით) |
გაითვალისწინე, რომ s_client სახელს ნაგულისხმევად არ ამოწმებს - სრულიად სხვა დომენის ვალიდურ სერტიფიკატზეც იტყვის 0 (ok). დაამატე -verify_hostname example.com, რომ შეამოწმოს, ან subjectAltName-ის გამოტანა თავად წაიკითხე.
NET::ERR_CERT_DATE_INVALID: ვადაგასულია ან საათია არასწორი#
სერტიფიკატს აქვს "not before" და "not after" თარიღი და ამ ფანჯრის გარეთ ის არავალიდურია. მის გარეთ მოხვედრის ორი ძალიან განსხვავებული გზა არსებობს.
სერტიფიკატს მართლა გაუვიდა ვადა. თუ openssl x509 -dates აჩვენებს წარსულში მყოფ notAfter-ს, განახლება ჩავარდა. Let's Encrypt-ის სერტიფიკატები 90 დღე მოქმედებს, ანუ რაღაც დაახლოებით ერთი თვეა ჩუმად ფუჭდება, რადგან კლიენტები ჩვეულებრივ ვადის გასვლამდე 30 დღით ადრე ახლდებიან. ჩვეულებრივი მიზეზები იგივეა, რაც თავდაპირველად გაცემას აჩერებს: დომენი აღარ მიუთითებს სერვერზე, firewall-ის ცვლილებით 80-ე პორტი დაიკეტა, origin-ის წინ CDN ჩაირთო ან განახლების timer არასოდეს დაყენებულა, რადგან პირველი სერტიფიკატი ხელით აიღეს. შეამოწმე განახლების ლოგი - Certbot-ისთვის ეს არის /var/log/letsencrypt/letsencrypt.log - და გაუშვი certbot renew --dry-run, რომ ჩავარდნა მოთხოვნისას გაიმეორო.
ვადაგასული სერტიფიკატის მეორე მახე: განახლება წარმატებით დასრულდა, მაგრამ არაფერი გადაიტვირთა. Certbot ახალ ფაილებს წერს, თუმცა nginx და უმეტესი სხვა სერვერი სერტიფიკატებს მხოლოდ გაშვებისას კითხულობს და ძველს მეხსიერებიდან აგრძელებს მომსახურებას, სანამ არ გადაიტვირთება. თუ დისკზე არსებულ ფაილს ახალი თარიღი აქვს, s_client კი ძველს აჩვენებს, ეს არის შენი პრობლემა. deploy hook მუდმივად ასწორებს:
$ certbot renew --deploy-hook "systemctl reload nginx"სერტიფიკატების ვადები მთელ ინდუსტრიაში მცირდება, არა მხოლოდ Let's Encrypt-ში - CA/Browser Forum-მა შეთანხმდა, რომ მაქსიმუმი მომდევნო რამდენიმე წლის განმავლობაში ეტაპობრივად შემცირდება და 2029 წელს 47 დღეზე გაჩერდება. ყველაფერი, რასაც ადამიანი კალენდრის შეხსენებით ანახლებს, ყოველ წელს უფრო ხშირად გაფუჭდება. თუ შენს სისტემაში რომელიმე სერტიფიკატი ხელით ახლდება, პირველ რიგში ის გააავტომატე.
დამთვალიერებლის საათი არასწორია. თუ შეცდომას მხოლოდ ერთი ადამიანი ხედავს და მისი ბრაუზერი წერს რაღაცას, როგორიცაა "Your clock is behind", სერტიფიკატი კარგადაა და მისი კომპიუტერი სხვა წელში ფიქრობს. ეს ემართება მანქანებს მკვდარი დედაპლატის ბატარეით, dual-boot სისტემებს, სადაც Windows და Linux ვერ თანხმდებიან, ტექნიკის საათი ადგილობრივი დროა თუ UTC, და ძველი snapshot-იდან აღდგენილ ვირტუალურ მანქანებს. სისტემური დროის გასწორება ერთბაშად ყველა საიტს ასწორებს. საიტის მფლობელს ამის გასწორება არ შეუძლია და არც უნდა სცადოს.
ჯერ არ არის ძალაში. უფრო იშვიათია, მაგრამ ხდება: ახალი სერტიფიკატის notBefore რამდენიმე წამით მომავალშია სერვერის ან კლიენტის დრიფტული საათის მიმართ. სერვერებზე NTP ჩართული გქონდეს - timedatectl-მა უნდა აჩვენოს System clock synchronized: yes.
NET::ERR_CERT_COMMON_NAME_INVALID: სერტიფიკატი სხვა სახელზეა#
მისამართის ზოლში არსებული სახელი სერტიფიკატის Subject Alternative Name სიაში უნდა იყოს. ბრაუზერები ძველ Common Name ველს მთლიანად უგულებელყოფენ - Chrome-მა მისი კითხვა 2017 წელს შეწყვიტა - ამიტომ სერტიფიკატი, რომელშიც სახელი მხოლოდ CN-შია, ვერ გადის, თუმცა ერთი შეხედვით სწორად გამოიყურება. ეს ძირითადად თვითნაკეთ სერტიფიკატებს ეხება; ყველა საჯარო გამცემი სახელებს SAN სიაში წერს.
აქ მოხვედრის გავრცელებული გზები:
- `www` და apex სხვადასხვა სახელებია.
example.com-ის სერტიფიკატიwww.example.com-ს არ ფარავს და პირიქითაც. ან აიღე ერთი სერტიფიკატი ორივე სახელით, ან ერთი მეორეზე გადაამისამართე - თან თვით გადამისამართებასაც ვალიდური სერტიფიკატი სჭირდება იმ სახელზე, საიდანაც გადამისამართებ, რადგან ბრაუზერი სერტიფიკატს გადამისამართების დანახვამდე ამოწმებს. www vs apex დომენი და გადამისამართებები განიხილავს, როგორ აირჩიო რომელია მთავარი. - Wildcard ზუსტად ერთ label-ს ფარავს.
*.example.comფარავსshop.example.com-ს, მაგრამ არაexample.com-სა და არაapi.shop.example.com-ს. wildcard სერტიფიკატები, რომლებიც "არ მუშაობს", თითქმის ყოველთვის ამ ორიდან ერთის დაფარვას ცდილობენ. - საერთო სერვერზე SNI არ ემთხვევა. როცა სერვერს მოთხოვნილი სახელისთვის სერტიფიკატი არ აქვს, ის ნაგულისხმევზე გადადის - ეს კი იმავე მანქანაზე რომელიღაც სხვა საიტს ეკუთვნის. nginx-ში ეს ნიშნავს, რომ მოთხოვნა მოხვდა
serverბლოკში, რომლისserver_name-შიც შენი ჰოსტი არ არის, ამიტომ გიპასუხა პირველმაlisten 443 sslბლოკმა (ან იმან, რომელიცdefault_server-ადაა მონიშნული). შეამოწმეserver_nameშეცდომებზე და გაუშვიnginx -T, რომ ნახო კონფიგურაცია, რომელიც nginx-მა რეალურად ჩატვირთა, და არა ფაილი, რომელიც გგონია, რომ შეცვალე. nginx reverse proxy-ის გზამკვლევში სამუშაო სტრუქტურაა. - DNS არასწორ მანქანაზე მიუთითებს. საიტი გადაიტანე, ძველი A ჩანაწერი ისევ არის ან ისევ cache-შია და ვიზიტორები წინა ჰოსტზე მიდიან, რომელსაც სულ სხვა სახელის სერტიფიკატი აქვს. შეადარე
dig +short example.com @1.1.1.1იმ მისამართს, რომელსაც ელოდები. შესაბამის ჩანაწერებს განიხილავს DNS ჩანაწერები განმარტებით. - IP მისამართით შესვლა.
https://203.0.113.10დომენის სერტიფიკატს არასოდეს დაემთხვევა. გამოიყენე სახელი.
არასრული chain: შენს ბრაუზერში მუშაობს, დანარჩენ ყველგან - არა#
ეს შეცდომა ყველაზე მეტ დროს ფლანგავს, რადგან სერვერის დამყენებელი მას ვერ იმეორებს. სერტიფიკატი ვალიდურია, სახელი სწორია, თარიღები წესრიგშია და საიტი მის ბრაუზერში იტვირთება. ამავე დროს curl ვარდება შეტყობინებით curl: (60) SSL certificate problem: unable to get local issuer certificate, Python-ის სკრიპტი ისვრის CERTIFICATE_VERIFY_FAILED-ს, გადახდის პროვაიდერის webhook არ იგზავნება და ზოგიერთ ტელეფონზე გაფრთხილება ჩანს.
საჯარო გამცემი შენს სერტიფიკატს root გასაღებით არ აწერს ხელს, რადგან ის ოფლაინ ინახება. ის ხელს შუალედურით აწერს, შუალედურს კი root აწერს ხელს. ბრაუზერებსა და ოპერაციულ სისტემებს root-ები მოყვებათ; შუალედური სერტიფიკატი კი აუცილებლად არა. ამიტომ სერვერმა ორივე უნდა გამოგზავნოს: ჯერ შენი სერტიფიკატი, მერე შუალედური. თუ მხოლოდ პირველს გამოგზავნის, კლიენტს უჭირავს სერტიფიკატი, რომელიც ისეთმა მხარემ მოაწერა ხელი, რომლის შესახებაც არასოდეს სმენია.
დესკტოპის ბრაუზერები შეცდომას ხშირად ფარავენ. Chrome და სხვები დაკარგულ შუალედურ სერტიფიკატს სერტიფიკატშივე მითითებული URL-ით წამოიღებენ ან სხვა საიტიდან cache-ში შენახულს გამოიყენებენ, თუ ის სწორად გამოგზავნა. ბრძანების ხაზის ინსტრუმენტები, პროგრამირების ენების HTTP ბიბლიოთეკები და ბევრი სხვა კლიენტი ამას არ აკეთებს და ვარდება. s_client ამას მყისვე აჩვენებს: chain-ში მხოლოდ 0 ხაზია და Verify return code: 21 (unable to verify the first certificate).
გამოსწორება ისაა, რომ შიშველი სერტიფიკატის ნაცვლად სრული chain ფაილი გაუშვა. Certbot-ის შემთხვევაში ეს ნიშნავს cert.pem-ის ნაცვლად fullchain.pem-ს:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;Apache 2.4.8 და უფრო ახალი chain-ს იმავე ფაილიდან კითხულობს, ამიტომ SSLCertificateFile-იც fullchain.pem-ზე უნდა მიუთითებდეს; ძველი SSLCertificateChainFile დირექტივა მოძველებულია. კომერციული გამცემისგან ნაყიდ სერტიფიკატთან ჩვეულებრივ შენს სერტიფიკატს და "bundle" ან "CA bundle" ფაილს ცალ-ცალკე იღებ. გააერთიანე, შენი სერტიფიკატი პირველი იყოს:
$ cat example_com.crt ca-bundle.crt > fullchain.crtთანმიმდევრობას მნიშვნელობა აქვს. თუ შუალედური პირველია, nginx დაიჩივლებს, რომ გასაღები სერტიფიკატს არ ემთხვევა, რადგან გასაღებს ფაილის პირველ სერტიფიკატს ადარებს. root თავად არ ჩართო - კლიენტებს ის უკვე აქვთ და გაგზავნა მხოლოდ ყოველ handshake-ს ზრდის.
Self-signed სერტიფიკატები და NET::ERR_CERT_AUTHORITY_INVALID#
self-signed სერტიფიკატს საკუთარი გასაღები აწერს ხელს. ის ტრაფიკს ისევე კარგად შიფრავს, როგორც ნებისმიერი სხვა, მაგრამ მას არავინ ადასტურებს, ამიტომ ყველა ბრაუზერი უარყოფს NET::ERR_CERT_AUTHORITY_INVALID-ით. საჯარო საიტისთვის ბრაუზერის მხარეს გასასწორებელი არაფერია: აიღე ნამდვილი სერტიფიკატი. Let's Encrypt უფასოა და სრულად ავტომატიზირდება, ამიტომ self-signed სერტიფიკატი საჯარო დომენზე 2026 წელს კონფიგურაციაა, რომელიც დროებითი უნდა ყოფილიყო.
სადაც ისინი კანონიერად გხვდება:
- ახალი ინსტალაცია. ბევრი control panel, router, NAS, Proxmox და web სერვერის ნაგულისხმევი პაკეტი ინსტალაციისას self-signed სერტიფიკატს აგენერირებს, რომ HTTPS საერთოდ იმუშაოს. გაფრთხილება მოსალოდნელია, სანამ სათანადოს არ დააყენებ.
- ლოკალური განვითარება. მისი გენერაცია ერთი ბრძანებით შეიძლება:
$ openssl req -x509 -newkey rsa:2048 -nodes -days 365 \ -keyout localhost.key -out localhost.crt \ -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost"-addext ხაზი ის ნაწილია, რომელსაც ხალხი ტოვებს, და მის გარეშე Chrome სერტიფიკატს სახელის გამოც უარყოფს და ნდობის გამოც. სწრაფ ტესტზე მეტისთვის mkcert უფრო მარტივია: ის პატარა ადგილობრივ გამცემს ქმნის, აყენებს მას შენს სისტემისა და ბრაუზერის trust store-ებში და გასცემს სერტიფიკატებს, რომლებსაც შენი მანქანა გაფრთხილებების გარეშე ენდობა - სხვა მანქანა კი არა.
- შიდა სერვისები კერძო CA-თი. კომპანიები შიდა სახელებისთვის საკუთარ გამცემს აწარმოებენ. ასეთი სერტიფიკატები ნებისმიერ მანქანაზე, რომელზეც კომპანიის root არ არის დაყენებული,
s_client-ში აჩვენებს19 (self-signed certificate in certificate chain)-ს. გამოსწორება root-ის გავრცელებაა და არა ვერიფიკაციის გამორთვა.
ორი გაფრთხილება მალსახმობებზე. "Proceed"-ზე დაჭერა მომხმარებლებს "Proceed"-ზე დაჭერას ასწავლის, ზუსტად ეს არის ჩვევა, რომელიც თავდამსხმელს სჭირდება. ხოლო curl -k, verify=False Python requests-ში ან NODE_TLS_REJECT_UNAUTHORIZED=0 შემოწმებას მთლიანად თიშავს - production კოდში დარჩენილი ისინი ნიშნავს, რომ გზაზე მყოფ ნებისმიერ მანქანას შეუძლია ტრაფიკის წაკითხვა და შეცვლა. ამის ნაცვლად კლიენტი სწორ CA ფაილზე მიუთითე: curl --cacert, REQUESTS_CA_BUNDLE ან NODE_EXTRA_CA_CERTS.
ERR_SSL_PROTOCOL_ERROR: handshake არ დასრულებულა#
ზემოთ ჩამოთვლილი ყველა შეცდომა ნიშნავს, რომ სერტიფიკატი მოვიდა და ბრაუზერს არ მოეწონა. ERR_SSL_PROTOCOL_ERROR ჩვეულებრივ ნიშნავს, რომ სერტიფიკატი საერთოდ არ მოსულა, რადგან პორტზე პასუხი ისეთმა რამ გასცა, რომელიც TLS-ზე ისე არ ლაპარაკობდა, როგორც ბრაუზერს ელოდა.
უბრალო HTTP HTTPS პორტზე. ყველაზე გავრცელებული მიზეზი. server ბლოკს აქვს listen 443; ssl-ის გარეშე, აპლიკაცია პირდაპირ 443-ზე უსმენს TLS-ის გარეშე ან https:// აკრიფე პორტის წინ, რომელიც მხოლოდ HTTP-ს უჭერს მხარს, მაგალითად აპლიკაციის საკუთარი :3000 ან :8080. Firefox-ის ვერსია, SSL_ERROR_RX_RECORD_TOO_LONG, უფრო პატიოსნად ამბობს: მან HTTP პასუხი მიიღო და TLS-ად წაკითხვა სცადა. s_client თავის შეცდომის ხაზებში წერს wrong version number ან packet length too long. შეამოწმე listen დირექტივა:
listen 443 ssl;http2 on;http2 on; არის ფორმა nginx 1.25.1-დან; ძველი ვერსიები წერენ listen 443 ssl http2;. ორივე შემთხვევაში ssl უნდა იყოს.
ამ სახელისთვის სერტიფიკატი არ არის კონფიგურირებული. ზოგი სერვერი, როცა SNI სახელი მიიღო, რომლისთვისაც სერტიფიკატი არ აქვს და ნაგულისხმევიც არ არის, handshake-ს წყვეტს და არასწორს არ აგზავნის. ბრაუზერი protocol error-ს ჩივის. გამოსწორება იგივეა, რაც სახელის შეუსაბამობისას: გააკეთე ისე, რომ სახელი კონფიგურაციაში არსებობდეს.
მხოლოდ ძველი პროტოკოლის ვერსიები. თანამედროვე ბრაუზერებმა TLS 1.0 და 1.1 მიატოვეს. სერვერი, appliance ან ძველი embedded მოწყობილობა, რომელიც მხოლოდ მათზე საუბრობს, protocol error-ის ნაცვლად ERR_SSL_VERSION_OR_CIPHER_MISMATCH-ს იძლევა, მაგრამ შემოწმება იგივეა:
$ openssl s_client -connect example.com:443 -servername example.com -tls1_2 </dev/null$ openssl s_client -connect example.com:443 -servername example.com -tls1_3 </dev/nullთუ ორივე ვარდება, სერვერი განახლებას საჭიროებს, nginx-ში კი ssl_protocols TLSv1.2 TLSv1.3; არის ხაზი, რომელიც უნდა დააყენო.
რაღაც შუაში დგას. ანტივირუსი "HTTPS scanning"-ით, კორპორატიული შემმოწმებელი proxy და captive portal-ები სასტუმროსა და მატარებლის wifi-ზე TLS-ს ჩაერევიან. იმის მიხედვით, რამდენად კარგად აკეთებენ, შედეგი protocol error ან authority error-ია, სერტიფიკატის issuer კი, როცა ხედავ, ანტივირუსის გამყიდველი ან კომპანიაა და არა საჯარო გამცემი. თუ პრობლემა მხოლოდ ერთ ქსელს ან ერთ მანქანას აქვს, ეს პირველი ეჭვმიტანილია. თავად გვერდი ამას ვერ გამოასწორებს.
წინ CDN დგას, origin არასწორია. Cloudflare-ის უკან გაფუჭებული origin CDN-ის საკუთარი შეცდომის გვერდებით ჩანს: 525 ნიშნავს, რომ CDN-სა და შენს სერვერს შორის handshake ჩავარდა, 526 ნიშნავს, რომ CDN-ის "Full (strict)" რეჟიმმა შენი origin-ის სერტიფიკატი არავალიდურად მიიჩნია. მისი "Flexible" რეჟიმი origin-თან ერთად, რომელიც HTTPS-ზე გადამისამართებს, ამის ნაცვლად ERR_TOO_MANY_REDIRECTS-ს იძლევა. რომელი რეჟიმი რომელ origin-ს ეკუთვნის, განხილულია პოსტში Cloudflare ვებსაიტებისა და თამაშის სერვერებისთვის.
ვალიდური სერტიფიკატი, მაგრამ მაინც "Not secure": mixed content#
როცა სერტიფიკატი კარგადაა, მაგრამ საკეტი არ ჩანს, გადახაზულია ან "Not secure"-ითაა ჩანაცვლებული, HTTPS-ით ჩატვირთული გვერდი რაღაცას უბრალო HTTP-ით იღებს. http://-ით მოთხოვნილი სკრიპტები, stylesheet-ები და iframe-ები პირდაპირ იბლოკება, რაც ჩვეულებრივ აშკარა შეცდომის ნაცვლად გვერდის გაუჩინარებული სტილით ან გაფუჭებული მენიუთი ჩანს. სურათები და მედია მიმდინარე Chrome-ში ავტომატურად HTTPS-ზე გადადის ან იბლოკება, თუ გადასვლა ვერ მოხერხდა.
ბრაუზერის console ყველა დამრღვევ URL-ს ასახელებს, რაც ამ პრობლემას ძიებიდან სიად აქცევს. Chrome-ში ასე იკითხება:
Mixed Content: The page at 'https://example.com/' was loaded over HTTPS,but requested an insecure script 'http://example.com/js/menu.js'.This request has been blocked; the content must be served over HTTPS.გამოსწორება ისაა, რომ http:// URL-ების გენერაცია შეწყვიტო - ჩვეულებრივ ეს არის CMS-ის მონაცემთა ბაზაში შენახული ძველი აბსოლუტური URL-ები, თემაში ჩაწერილი asset ჰოსტი ან reverse proxy-ის უკან მდგომი აპლიკაცია, რომელიც ვერ ხვდება, რომ ვიზიტორი HTTPS-ით მოვიდა, და ბმულებს ამის მიხედვით აგებს. ეს უკანასკნელი მოითხოვს, რომ აპლიკაციამ proxy-სგან მოსულ X-Forwarded-Proto-ს ენდოს. გაწმენდასა და proxy-ს პარამეტრებს განიხილავს როგორც HTTPS და Let's Encrypt მარტივად, ისე დომენის სერვერზე მიმართვა და SSL-ის დამატება, მონაცემთა ბაზაში უსაფრთხო search-and-replace კი აღწერილია პოსტში WordPress-ის ახალ ჰოსტზე გადატანა.
სად მუშავდება სერტიფიკატი შენს მაგივრად#
ზემოთ აღწერილი ჩავარდნების უმეტესობა ფაილების ხელით მართვას უკავშირდება: გაფუჭებული განახლება, reload, რომელიც არავის გაუშვია, cert.pem იქ, სადაც fullchain.pem უნდა ყოფილიყო. RE:NODE-ის web hosting და app hosting გეგმებზე ამ ნაწილს proxy slot აკეთებს. A ჩანაწერს მიუთითებ ნაჩვენებ მისამართზე და სერტიფიკატი ავტომატურად გაიცემა და ახლდება, ვადის გასვლამდე 21-დღიან ფანჯარაში. შენი აპლიკაცია ჩვეულებრივ HTTP-ს იღებს თავის პორტზე და ვიზიტორის რეალურ მისამართს X-Forwarded-For-ში, ამიტომ ის სერტიფიკატს არასოდეს ინახავს და chain-ის აწყობა არ გჭირდება.
რას არ ცვლის: DNS ისევ შენი დომენის პროვაიდერთანაა, ამიტომ არასწორი ან მოძველებული A ჩანაწერი მაინც სახელის ან გაცემის პრობლემას იძლევა, mixed content კი ისევ აპლიკაციის გასასწორებელია. როცა რამე ცუდად ჩანს, ზემოთ მოცემული s_client ბრძანებები ნებისმიერ ჰოსტზე მუშაობს, ჩვენსაზეც.
FAQ#
უსაფრთხოა თუ არა "Proceed anyway"-ზე დაჭერა?
საკუთარ სერვერზე, self-signed სატესტო სერტიფიკატის დასადასტურებლად - დიახ. სხვის საიტზე - არა: გაფრთხილება ნიშნავს, რომ ბრაუზერმა ვერ დაადასტურა, ვისთან საუბრობს, ხოლო ყველაზე გავრცელებული კანონიერი მიზეზები ზუსტად ჩარევასავით გამოიყურება. გადასვლის შემდეგ პაროლს ან ბარათის ნომერს არასოდეს შეიყვან.
რატომ მუშაობს საიტი Chrome-ში, მაგრამ curl-ში ან ჩემს აპლიკაციაში - არა?
სერვერი სერტიფიკატს შუალედურის გარეშე აგზავნის. დესკტოპის ბრაუზერები ხარვეზს თავად ავსებენ; უმეტესი სხვა კლიენტი - არა. გაუშვი სრული chain ფაილი და განსხვავება გაქრება.
რატომ ხედავს სერტიფიკატის შეცდომას მხოლოდ ერთი ვიზიტორი?
რადგან პრობლემა მის მხარესაა - არასწორი სისტემური საათი, ანტივირუსის HTTPS scanning, სამსახურის proxy ან საჯარო wifi-ის შესვლის გვერდი. სთხოვე ზუსტი შეცდომის კოდი და სერტიფიკატის დეტალებში ნაჩვენები issuer.
როგორ შევამოწმო, როდის იწურება ჩემი სერტიფიკატი?
გაუშვი s_client openssl x509 -noout -dates-ში გატარებით შენი ქსელის გარედან, როგორც ზემოთ არის ნაჩვენები. notAfter არის ვადის გასვლა. მნიშვნელოვანი რამისთვის მონიტორინგის შემოწმებას დააყენე, რომ 14 დღეზე ნაკლები რომ დარჩება, გაგაფრთხილოს, რათა გაფუჭებული განახლება ვიზიტორებამდე შენ შეამჩნიო.
შემიძლია HSTS შეცდომის გასუფთავება საიტისთვის, რომელზეც ვმუშაობ?
Chrome-ში chrome://net-internals/#hsts-ს აქვს "Delete domain security policies" ველი, რომელიც საიტის HSTS ჩანაწერს შენი ბრაუზერიდან შლის. ის ვერ შლის დომენს, რომელიც ბრაუზერის ჩაშენებულ preload სიაშია, ხოლო რეალური გამოსწორება მაინც ვალიდური სერტიფიკატია.
უფასო სერტიფიკატი უფრო მეტ შეცდომას იწვევს, ვიდრე ფასიანი?
არა. ბრაუზერები Let's Encrypt-ს ისევე ენდობიან, როგორც ნებისმიერ კომერციულ გამცემს, ამ პოსტის შეცდომები კი ფასიან სერტიფიკატებზეც ზუსტად ისევე ხშირად ხდება - დაკარგული chain-ების გამო უფრო ხშირადაც, რადგან bundle ფაილი ცალკე მოდის.


