ERR_SSL_PROTOCOL_ERROR: что означает и как исправить
ERR_SSL_PROTOCOL_ERROR означает, что само TLS-рукопожатие провалилось еще до того, как браузер вообще получил сертификат для оценки. Это различие важно: что бы ни было не так, оно лежит ниже уровня сертификата - в согласовании протокола, порту или самом соединении, так что замена сертификата это не исправит.
Что означает ERR_SSL_PROTOCOL_ERROR
TLS-соединение начинается с рукопожатия: клиент отправляет ClientHello, перечисляя поддерживаемые версии протокола и наборы шифров, а сервер должен ответить ServerHello, выбрав один из них, и следом отправить свой сертификат. ERR_SSL_PROTOCOL_ERROR срабатывает, когда этот обмен ломается еще до того, как дело доходит до этапа сертификата, чаще всего потому, что то, что ответило на порту, вообще не говорило на TLS, либо обе стороны не смогли договориться, как на нем разговаривать. Это самый частый по объему поисковых запросов код ошибки в Chrome, и этот объем отражает то, сколько разных первопричин схлопывается в одно и то же общее сообщение, а не один общий сбой.
Как проявляется ошибка
Chrome и Edge показывают ERR_SSL_PROTOCOL_ERROR без каких-либо деталей сертификата, потому что никакой сертификат вообще не был предъявлен для показа. Firefox обычно показывает "Secure Connection Failed" с кодом вроде SSL_ERROR_RX_MALFORMED_HANDSHAKE или SSL_ERROR_PROTOCOL_VERSION_ALERT в зависимости от того, как именно сломалось рукопожатие.
Из командной строки и curl, и openssl точно определяют сбой, что быстрее всего избавляет от догадок:
curl -v https://example.com/
...
* TLSv1.3 (OUT), TLS handshake, Client hello
* OpenSSL/3.x: error:0A000126:SSL routines::unexpected eof while reading
* OpenSSL SSL_connect: SSL_ERROR_SYSCALL
openssl s_client -connect example.com:443 -servername example.com
...
140... error:1408F10B:SSL routines:ssl3_get_record:wrong version number
"Wrong version number" почти всегда означает, что порт 443 ответил обычным HTTP, а не TLS, поскольку первые байты HTTP-ответа выглядят для TLS-парсера, ожидающего ServerHello, как бессмыслица. Соединение, которое зависает и падает по таймауту вообще без ошибки, вместо того чтобы быстро провалиться, обычно означает, что файрвол или прокси молча отбрасывает пакеты вместо того, чтобы сервер их активно отклонял.
Что вызывает ERR_SSL_PROTOCOL_ERROR
- Порт 443 отдает обычный HTTP, либо вообще не тот сервис. Неправильно настроенный обратный прокси, упавший сервис, оставивший запасной слушатель, либо правило NAT, указывающее не на тот бэкенд, - все это дает не-TLS ответ на TLS-порту.
- Несовпадение версии TLS или набора шифров. Сервер, зафиксированный на TLS 1.0 или 1.1 ради устаревшей совместимости, не имеет общего протокола с браузером, требующим TLS 1.2 или выше, поэтому рукопожатие проваливается сразу.
- Server Name Indication (SNI) отсутствует или неправильно настроен. На сервере, обслуживающем несколько сертификатов на одном IP, отсутствие совпадения SNI может заставить его предъявить не тот сертификат либо отказать в рукопожатии.
- Эксперименты с QUIC и HTTP/3. Chrome иногда сначала пробует QUIC, а затем откатывается на TLS поверх TCP; сеть, неправильно обрабатывающая UDP-трафик QUIC, может проявить это как ошибку протокола именно на этапе отката.
- Сканирование HTTPS антивирусом или корпоративным прокси. Программа, перехватывающая TLS для проверки трафика, начинает собственное рукопожатие вместо настоящего, и сломанный сертификат перехвата ломает эту подмену.
- HSTS принудительно направляет на HTTPS хост со сломанным TLS. Как только браузер закэшировал политику HSTS для домена, он больше не будет пробовать обычный HTTP, поэтому хост, который раньше плавно откатывался, теперь вместо этого жестко проваливается.
- Старая или сломанная цепочка сертификатов на старом клиенте. Очень старые операционные системы и браузеры, появившиеся раньше более нового корневого или промежуточного сертификата, могут проваливать рукопожатие способом, неотличимым от несовпадения версии.
- Часы клиента сильно ошибаются. Достаточно сильно сбитые часы могут заставить клиента вообще отказаться согласовывать сессию, а не просто отклонить сертификат уже после этого.
Как понять, кто виноват
Выполните тот же запрос из другой сети, например с телефона на мобильном интернете вместо офисного Wi-Fi. Если там сайт загружается без проблем, проблема локальна: корпоративный прокси, перехват антивирусом либо captive-портал в первой сети. Если рукопожатие проваливается одинаково повсюду, где вы пробуете, причина - в настройках TLS сервера. SSL-проверка, запущенная сразу из нескольких мест, отвечает на это одним запросом вместо того, чтобы одалживать второе устройство, и сообщает точный протокол и шифр, согласованные (или отклоненные) сервером с каждой точки обзора.
Как исправить ERR_SSL_PROTOCOL_ERROR
Если вы посетитель
- Очистите состояние TLS в Chrome на странице
chrome://net-internals/#hstsиchrome://restart, либо просто очистите данные просмотра "кэшированные изображения и файлы" и "cookie и данные сайтов" для затронутого сайта - это также очистит закэшированный HSTS и состояние сессии SSL. - Отключите эксперимент QUIC на странице
chrome://flags/#enable-quic, установите значение Disabled и перезапустите браузер. Если после этого сайт загружается, причиной была недружественная к QUIC сеть или прокси. - Проверьте системную дату и время и настройте автоматическую синхронизацию; достаточно сильно сбитые часы могут сорвать само рукопожатие, а не только последующую проверку сертификата.
- Отключите сканирование HTTPS в антивирусе (обычно в настройке вроде "веб-защита" или "сканирование SSL/TLS") и повторите попытку. Если это помогло, обновите антивирус либо добавьте сайт в список исключений, а не оставляйте сканирование выключенным насовсем.
- Попробуйте другую сеть, например мобильный интернет. Корпоративный прокси или сломанный сетевой прибор, затрагивающий только одно соединение, - частая причина, никак не связанная с самим сайтом.
Если вы администрируете сайт
- Убедитесь, что порт 443 действительно отдает TLS с помощью команды openssl выше. "Wrong version number" или ответ обычным текстом означает, что на этом порту закреплен не тот сервис; сначала исправьте настройку прокси или слушателя, прежде чем вообще трогать сертификаты.
- Задайте явные поддерживаемые версии протокола. В nginx:
Отключение TLS 1.0 и 1.1 исправляет рукопожатия у современных клиентов, но нарушит доступ для очень старых клиентов, все еще на них полагающихся; принимайте этот компромисс осознанно, а не случайно.ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; - Убедитесь, что блок сервера действительно слушает TLS на нужном порту:
listen 443 ssl;(илиlisten 443 ssl http2;), и что директивы сертификата и ключа указывают на существующие и соответствующие друг другу файлы. - Проверьте порядок цепочки сертификатов. Листовой сертификат должен идти первым, за ним по порядку - промежуточные вплоть до корневого (не включая его); цепочка, отданная в неправильном порядке или с пропущенным промежуточным сертификатом, вызывает сбои рукопожатия у одних клиентов, но не у других, которые кэшируют недостающий промежуточный сертификат откуда-то еще.
- Если домен находится за Cloudflare, проверьте режим SSL/TLS. Режим Flexible терминирует TLS на edge и общается с origin по обычному HTTP, что сразу проваливается, если origin принимает только HTTPS; режим Full требует любого сертификата на origin; Full (strict) требует валидного сертификата на origin, которому доверяют, и сам вызовет сбой рукопожатия, если сертификат origin самоподписан или просрочен.
- После любого изменения конфигурации перезагружайте, а не просто редактируйте:
nginx -t && systemctl reload nginxпроверяет конфигурацию перед ее применением.
ERR_SSL_PROTOCOL_ERROR в сравнении с похожими на вид ошибками
- ERR_CERT_DATE_INVALID случается уже после того, как сертификат был получен и прочитан; рукопожатие дошло до этого этапа и затем провалило сравнение дат. ERR_SSL_PROTOCOL_ERROR не доходит настолько далеко вообще.
- ERR_CERT_AUTHORITY_INVALID тоже случается уже после получения сертификата; браузер прочитал его и не доверился тому, кто его подписал. И снова, ошибка протокола означает, что ни один сертификат вообще не был оценен.
- ERR_SSL_VERSION_OR_CIPHER_MISMATCH - более конкретный родственник этой ошибки: она срабатывает, когда рукопожатие все же продвинулось достаточно далеко, чтобы сравнить поддерживаемые версии и шифры, и не нашло вообще никакого пересечения, типично когда старый сервер предлагает только SSLv3 или TLS 1.0 против современного браузера, который их отвергает. ERR_SSL_PROTOCOL_ERROR - более широкий, менее конкретный сбой, покрывающий все остальное, включая не-TLS ответ на порту, некорректные данные рукопожатия и сломавшееся ПО перехвата.
Как предотвратить ERR_SSL_PROTOCOL_ERROR
Сбой рукопожатия, вызванный изменением конфигурации, обновлением прокси или переключением режима SSL в Cloudflare, не проявляется в обычной проверке HTTP-статуса, поскольку соединение никогда не заходит настолько далеко, чтобы его произвести. Специализированная SSL-проверка напрямую считывает согласованный протокол и шифр и, будучи запущенной из 300+ контрольных точек в 158 городах, показывает, проваливается ли рукопожатие повсюду или только из одной сети, - тот же разбор, который это руководство проходит вручную. Запустите проверку SSL-сертификата для домена и настройте постоянный мониторинг SSL и срока действия домена, чтобы сломанное рукопожатие оповещало вас до того, как об этом сообщат посетители.
Часто задаваемые вопросы
Означает ли ERR_SSL_PROTOCOL_ERROR, что мой сертификат плохой?
Не обязательно. Ошибка срабатывает еще до того, как браузер доходит до сертификата, поэтому сам сертификат может быть совершенно в порядке, пока сама лежащая в основе TLS-договоренность все равно проваливается.
Почему это происходит только на одном компьютере или в одной сети?
Сканирование HTTPS антивирусом, корпоративный прокси или сломанный путь QUIC именно в этой сети - обычные причины, по которым рукопожатие проваливается в одном месте и проходит успешно везде еще. Тест из второй сети быстрее всего это подтверждает.
Я только что перенес сайт за Cloudflare, и теперь посетители видят это. Что изменилось?
Проверьте режим SSL/TLS в панели управления. Режим Flexible ожидает, что origin принимает обычный HTTP, и проваливается, если он отдает только HTTPS; Full (strict) ожидает валидного сертификата origin, которому доверяют, и проваливается на самоподписанном или просроченном.
Ломает ли что-нибудь отключение TLS 1.0 и 1.1 на моем сервере?
Может, для посетителей на очень старых браузерах, так и не получивших обновление до TLS 1.2. Для большинства современного трафика это исправляет больше рукопожатий, чем ломает, но сначала проверьте состав ваших собственных клиентов.
Почему curl сказал "wrong version number"?
Это сообщение означает, что curl отправил TLS ClientHello и получил в ответ байты, не разбирающиеся как TLS ServerHello, - почти всегда потому, что порт отдает обычный HTTP или другой не-TLS протокол.