VMHeaven

Решение проблем

ERR_SSL_PROTOCOL_ERROR: «Этот сайт не может обеспечить безопасное подключение» — причины и решение

«Этот сайт не может обеспечить безопасное подключение» (ERR_SSL_PROTOCOL_ERROR) в Chrome и Яндекс Браузере: что проверить у себя и как исправить на сервере.

Опубликовано ~10 мин чтения

Коротко: ERR_SSL_PROTOCOL_ERROR значит, что Chrome начал TLS-рукопожатие, получил в ответ что-то, что не является корректным TLS, и прервал соединение. Чаще всего порт за адресом https:// отвечает по обычному HTTP: nginx с listen 443; без ssl, порт Docker, проброшенный не на тот порт контейнера, или dev-сервер на localhost. Если ошибку видите только вы, а у других сайт открывается, HTTPS мешает что-то на вашем устройстве или в вашей сети.

В русском Chrome над кодом написано Этот сайт не может обеспечить безопасное подключение и Сайт example.com отправил недействительный ответ., в английском — This site can’t provide a secure connection. Edge и Яндекс Браузер построены на Chromium и показывают тот же код ERR_SSL_PROTOCOL_ERROR, так что причины и проверки у них те же.

Две команды с любой машины, где есть curl, покажут, на чьей стороне проблема:

Linux · macOS · WSL
# 1. Где обрывается рукопожатие?
curl -sv -o /dev/null https://example.com/

# 2. Отвечает ли порт 443 обычным HTTP?
curl -sS -i http://example.com:443/

Замените example.com на проблемный хост. Порт, который действительно ждёт TLS, вторую команду отвергнет: nginx и Cloudflare отвечают 400 The plain HTTP request was sent to HTTPS port, Apache — You’re speaking plain HTTP to an SSL-enabled server port, Caddy и другие серверы на Go — Client sent an HTTP request to an HTTPS server. Если же пришла обычная страница или редирект, порт 443 отвечает по обычному HTTP — ошибка найдена: причина 1. Сообщения ниже получены в curl 7.88 с OpenSSL 3.0 на Debian 12; LibreSSL в macOS формулирует их немного иначе. curl, OpenSSL и nginx свои сообщения не переводят, поэтому на сервере с русской локалью текст будет тем же.

Какое сообщение вы видите?

КлиентСообщениеОбычно означает
Chrome, EdgeERR_SSL_PROTOCOL_ERROR; в русском Chrome под заголовком Этот сайт не может обеспечить безопасное подключение и Сайт example.com отправил недействительный ответ., в английском — This site can’t provide a secure connection и example.com sent an invalid response.Ответ был не TLS, или рукопожатие сорвалось нестандартно: обычный HTTP на 443, другой сервис, фильтр
Яндекс БраузерERR_SSL_PROTOCOL_ERROR; в справке Браузера рядом с ней разобраны сообщения «Этот сайт не может обеспечить безопасное соединение» и «Сайт отправил некорректный ответ»То же, что в Chrome: Браузер построен на Chromium
Chrome, Edgelocalhost sent an invalid response.; в русском Chrome — Сайт localhost отправил недействительный ответ.Dev-сервер работает по HTTP, а вы запросили HTTPS: localhost
FirefoxSecure Connection Failed (в русском Firefox — Ошибка при установлении защищённого соединения) · SSL_ERROR_RX_RECORD_TOO_LONGОбычный HTTP на HTTPS-порту
FirefoxPR_END_OF_FILE_ERRORСоединение оборвалось посреди рукопожатия: прокси, VPN, антивирус, фильтр
SafariSafari can’t establish a secure connection to the serverЛюбой сбой TLS; запустите проверку curl выше
curlcurl: (35) … wrong version numberОбычный HTTP или другой протокол на порту
Chrome, Edgeuses an unsupported protocol. (в русском Chrome — На сайте example.com используется неподдерживаемый протокол.) · ERR_SSL_VERSION_OR_CIPHER_MISMATCHНе эта ошибка: нет общей версии TLS или шифра
Chrome, EdgeYour connection is not private (в русском Chrome — Подключение не защищено) · NET::ERR_CERT_…Не эта ошибка: рукопожатие прошло, а сертификат отклонён
Страница CloudflareError 525 SSL handshake failedТот же сбой, но между Cloudflare и вашим сервером: Cloudflare

Что на самом деле означает ошибка

Когда рукопожатие не удаётся, Chromium переводит причину из BoringSSL в код net::ERR_*. Для нескольких причин есть собственные коды, всё остальное попадает в ERR_SSL_PROTOCOL_ERROR (код -107). Это код «для всего остального», поэтому советы по нему так разбросаны.

Соответствие ниже взято из openssl_ssl_util.cc в исходниках Chromium; строки curl — настоящий вывод, полученный от example.com:80 и от локальных тестовых серверов, которые отправляют именно такой ответ:

Что прислал серверЧто пишет curlЧто показывает Chrome
Обычный HTTP или баннер SSHwrong version numberERR_SSL_PROTOCOL_ERROR
TLS-алерт access_denied (49), хотя клиентский сертификат не запрашивалсяtlsv1 alert access deniedERR_SSL_PROTOCOL_ERROR; в Chromium отмечено, что так страницу блокируют некоторые файрволы
TLS-алерт illegal_parameter (47)sslv3 alert illegal parameterERR_SSL_PROTOCOL_ERROR
TLS-алерт handshake_failure (40) сразу после ClientHellosslv3 alert handshake failureERR_SSL_VERSION_OR_CIPHER_MISMATCH
TLS-алерт protocol_version (70), например от сервера только с TLS 1.0/1.1tlsv1 alert protocol version или unsupported protocol, если сервер отвечает старым ServerHello (с --tlsv1.2)ERR_SSL_VERSION_OR_CIPHER_MISMATCH
TLS-алерт unrecognized_name (112)tlsv1 unrecognized nameERR_SSL_UNRECOGNIZED_NAME_ALERT
Ничего, соединение закрытоSSL_ERROR_SYSCALLERR_CONNECTION_CLOSED
Сброс TCPRecv failure: Connection reset by peerERR_CONNECTION_RESET

curl 7.88 всё ещё предлагает TLS 1.0 и 1.1; на таком сервере OpenSSL 3.0 затем останавливается с legacy sigalg disallowed or unsupported. Добавьте --tlsv1.2, чтобы проверять так, как подключается браузер. Просроченный сертификат, старая версия TLS или неверные часы в современном Chrome не дают ERR_SSL_PROTOCOL_ERROR: у них свои коды.

Если ошибку видите только вы: проверки на своём устройстве

Откройте адрес на телефоне через мобильный интернет. Если там сайт загружается, причина на вашем компьютере или в вашей сети:

  • Окно инкогнито и второй браузер. В режиме инкогнито расширения выключены, если вы сами их там не разрешили. Расширения для VPN и прокси — частые виновники, как и системный прокси в сетевых настройках ОС.
  • Проверка HTTPS в антивирусе и корпоративные файрволы. Они встраиваются в каждое рукопожатие, и когда спотыкаются, Chrome получает мусор. Для проверки выключите сканирование HTTPS или фильтрацию SSL/TLS: у Kaspersky это раздел «Проверка защищенных соединений» в настройках сети с вариантом «Не проверять защищенные соединения», у ESET — параметр «Включить SSL/TLS» в разделе «Расширенные параметры → Защита → SSL/TLS». На сайте, который работает, нажмите значок слева от адреса, затем Подключение защищено и Действительный сертификат (в английском Chrome — Connection is secure и Certificate is valid): если издатель назван по имени вашего антивируса или работодателя, ваш HTTPS перехватывают.
  • Постквантовый обмен ключами через старые шлюзы инспекции. Начиная с версии 131 Chrome предлагает в рукопожатии TLS 1.3 постквантовый key share на основе ML-KEM. Согласно заметке Fortinet об известной проблеме, глубокая инспекция FortiGate в режиме flow-based со старыми движками IPS отвечает на неё алертом illegal_parameter, а это ERR_SSL_PROTOCOL_ERROR. Лечится обновлением файрвола, а политика Chrome PostQuantumKeyAgreementEnabled, которой этот key share можно было отключить, действовала только до Chrome 146.
  • Запись в файле hosts. Строка для сайта в /etc/hosts или C:\Windows\System32\drivers\etc\hosts, оставшаяся после тестов переезда, отправляет вас на старую машину, которая может вообще не поддерживать TLS. Удалите её.
  • QUIC. Отключить chrome://flags/#enable-quic — быстрая проверка, но сбои QUIC обычно выглядят как ERR_QUIC_PROTOCOL_ERROR, и Chrome сам переходит на TCP. В Яндекс Браузере служебные страницы открываются через browser://, например browser://flags.
  • Устаревшая запись HSTS. Если сайт раньше работал по HTTPS, а потом от него отказался, Chrome всё равно принудительно открывает его по HTTPS. На странице chrome://net-internals/#hsts (в Edge — edge://net-internals/#hsts) есть поле Delete domain security policies; записи из предзагруженного списка там удалить нельзя.

Владельцу сайта: воспроизведите ошибку снаружи

Проверяйте снаружи и по обоим семействам адресов: сервер может отвечать по TLS на IPv4 и по обычному HTTP на IPv6, и тогда ошибку видит только часть посетителей.

Linux · macOS · WSL
curl -4 -sS -o /dev/null -w '%{http_code}\n' https://example.com/
curl -6 -sS -o /dev/null -w '%{http_code}\n' https://example.com/

Если пришёл код статуса, этот путь работает. Подробности покажет OpenSSL, если провести рукопожатие им:

Linux · OpenSSL 3
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>&1 \
  | grep -E 'error|handshake has read'
Пример вывода · порт с обычным HTTP (example.com:80)
40378B48D87F0000:error:0A00010B:SSL routines:ssl3_get_record:wrong version number:../ssl/record/ssl3_record.c:350:
SSL handshake has read 5 bytes and written 317 bytes

read 5 bytes — вот признак: OpenSSL прочитал заголовок одной записи, нашёл HTTP/ там, где должен начинаться TLS, и сдался. У рабочего сервера строки с ошибкой нет, а прочитано несколько килобайт, для example.com:443 около 4000 байт.

Без доступа к shell поможет наша проверка SSL (англ.): она выполняет TLS-рукопожатие с портом 443 из Амстердама и, если оно не завершается, показывает ошибку вместо сертификата.

Если проверка вообще не может подключиться, проверка открытых портов (англ.) покажет, доступен ли TCP 443 в принципе; закрытый порт даёт ERR_CONNECTION_REFUSED, а не эту ошибку.

Причина 1: порт 443 отвечает обычным HTTP

nginx работает по TLS только на сокете, у которого в строке listen есть ssl. Без него nginx отдаёт на 443 обычный HTTP, даже если в том же блоке есть строки ssl_certificate, и nginx -t не возражает. Этот блок проходит проверку в nginx 1.22 из Debian 12:

nginx · ошибка: TLS так и не начинается
server {
    listen 443;                 # нет "ssl"
    server_name example.com;
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
}

Чаще всего забывают строку для IPv6: listen [::]:443; рядом с правильной listen 443 ssl; — это отдельный сокет, и посетители по IPv6 получают обычный HTTP. Выведите все строки для 443 без ssl из конфигурации, которую nginx на самом деле загрузил:

Debian · Ubuntu
sudo nginx -T 2>/dev/null | grep -E '^\s*listen\s+(\S*:)?443\b' | grep -vE 'ssl|quic'

Пустой вывод — то, что нужно. В каждую выведенную строку добавьте ssl, затем проверьте конфигурацию и перезагрузите nginx:

nginx · исправлено
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name example.com www.example.com;
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    root /var/www/example.com;
}
Debian · Ubuntu
sudo nginx -t && sudo systemctl reload nginx

Кроме того, nginx оставляет след. Когда браузер отправляет TLS ClientHello на сокет с обычным HTTP, в access-логе появляется «запрос», который начинается с заголовка TLS-записи \x16\x03\x01, со статусом 400:

Debian · Ubuntu
sudo grep -c '\\x16\\x03\\x01' /var/log/nginx/access.log

Несколько совпадений в день — это сканеры; совпадение на каждый заход по HTTPS значит, что какой-то блок на 443 отвечает по обычному HTTP. В других стеках та же ловушка:

  • Apache: <VirtualHost *:443>, скопированный с блока для порта 80, без SSLEngine on. mod_ssl выключен для каждого виртуального хоста, пока эта строка его не включит; на Debian также выполните sudo a2enmod ssl.
  • Docker: -p 443:80 или "443:80" в Compose публикует порт контейнера с обычным HTTP на HTTPS-порту хоста, а docker ps показывает это как 0.0.0.0:443->80/tcp. Опубликуйте приложение на 127.0.0.1:8080:80, а 443 отдайте обратному прокси с сертификатом.
  • Приложения на Node: app.listen(443) в Express запускает обычный HTTP-сервер. Используйте модуль https или, что лучше, запустите приложение на локальном порту за nginx.

Причина 2: исправление так и не загрузилось

Сертификат и ключ, которые не подходят друг к другу, эту ошибку вызвать не могут: nginx, Node и Python отказываются загружать такую пару. Подвох в другом, и он незаметнее. Вы исправляете строку listen, перезагрузка не проходит, и nginx продолжает работать со старой конфигурацией. Два типичных сообщения nginx -t (nginx 1.22, OpenSSL 3.0, пути для примера):

Пример вывода · nginx -t, ключ от другого сертификата
nginx: [emerg] SSL_CTX_use_PrivateKey("/etc/ssl/private/example.com.key") failed (SSL: error:05800074:x509 certificate routines::key values mismatch)
nginx: configuration file /etc/nginx/nginx.conf test failed
Пример вывода · nginx -t, listen … ssl без сертификата
nginx: [emerg] no "ssl_certificate" is defined for the "listen ... ssl" directive in /etc/nginx/sites-enabled/example.com:1
nginx: configuration file /etc/nginx/nginx.conf test failed

Номер строки указывает на начало блока server. Неудачный systemctl reload оставляет работающий nginx нетронутым, а restart с той же ошибкой оставляет nginx остановленным, и вместо ERR_SSL_PROTOCOL_ERROR посетители получат ERR_CONNECTION_REFUSED. Всегда ставьте nginx -t && перед перезагрузкой, а после неё проверяйте снаружи.

Причина 3: отвечает не веб-сервер

Порт 443 открыт даже в строгих сетях, поэтому его часто занимает что-то, что не является HTTPS: SSH, сервер OpenVPN на TCP, мультиплексор вроде sslh с неверным маршрутом по умолчанию или роутер, который пробрасывает 443 не на тот внутренний порт. Настоящий вывод curl для локального тестового сервера, который отвечает баннером OpenSSH:

Пример вывода · SSH-сервер на HTTPS-порту
curl: (35) OpenSSL/3.0.22: error:0A00010B:SSL routines::wrong version number

Посмотрите на сервере, какой процесс занимает порт:

Debian · Ubuntu
sudo ss -ltnp 'sport = :443'

В последней колонке указана программа, например users:(("nginx",…)). Если это не ваш веб-сервер или там пусто, а порт снаружи всё равно отвечает, трафик попадает куда-то ещё: проверьте проброс портов на роутере, целевой порт балансировщика, проброс портов в Docker и не указывают ли записи A и AAAA (dig +short example.com A, затем AAAA) всё ещё на старый сервер.

Причина 4: HSTS отправляет браузер на HTTPS там, где его нет

Как только сайт отправил заголовок Strict-Transport-Security, браузер переписывает каждый запрос http:// к этому хосту на https:// на срок из max-age, а с includeSubDomains — ещё и для каждого внутреннего инструмента на поддомене.

Подвох — в номере порта. Chromium меняет только схему, поэтому http://tools.example.com:8080/ превращается в https://tools.example.com:8080/, и приложение с обычным HTTP на 8080 получает TLS-рукопожатие: ERR_SSL_PROTOCOL_ERROR. В DevTools на вкладке Network эта подмена видна как 307 Internal Redirect с Non-Authoritative-Reason: HSTS. В 443 превращается только порт 80.

Целые домены верхнего уровня внесены в предзагруженный список HSTS в Chrome, среди них .dev, .app и .page: всё, что под ними, работает только по HTTPS. Отдавайте на таком имени TLS или выведите инструмент из-под политики. Быстро отозвать HSTS нельзя: браузеры забывают его, когда истекает max-age или когда получают от этого хоста max-age=0 по корректному HTTPS.

За Cloudflare

Если запись проксируется (оранжевое облако), TLS-рукопожатие браузера заканчивается на Cloudflare, а не на вашем сервере. Если сломан исходный сервер (origin), посетитель видит собственную страницу ошибки Cloudflare — 525 SSL handshake failed или 526 Invalid SSL certificate, — но никогда не ERR_SSL_PROTOCOL_ERROR. Проверьте, какой у вас случай:

Linux · macOS
dig +short example.com A
dig +short example.com AAAA

Адреса Cloudflare (список — на cloudflare.com/ips) значат, что эта ошибка почти всегда на стороне посетителя. Если в ответе IP вашего сервера, запись работает в режиме DNS only (серое облако) или Cloudflare поставлен на паузу.

Именно на этом переключении падают сайты в режиме Flexible: Flexible общается с вашим сервером по обычному HTTP, поэтому origin никогда не нуждался в TLS на 443. При прямом обращении посетители по HTTPS получают эту ошибку или ERR_CONNECTION_REFUSED. Установите на origin настоящий сертификат и переключитесь на Full (strict). Сертификат Cloudflare Origin CA работает только при включённом проксировании, потому что браузеры ему не доверяют.

ERR_SSL_PROTOCOL_ERROR на localhost

localhost sent an invalid response (в русском Chrome — Сайт localhost отправил недействительный ответ.) почти всегда значит, что dev-сервер работает по обычному HTTP, а браузер запросил HTTPS. Настоящий вывод для Python http.server на 127.0.0.1:18443 — от curl и из лога сервера:

Пример вывода · curl https://localhost:18443/
curl: (35) OpenSSL/3.0.22: error:0A00010B:SSL routines::wrong version number
Пример вывода · лог dev-сервера (сокращён)
127.0.0.1 - - [12/Oct/2026 10:09:16] "\x16\x03\x01\x02\x00\x01\x00\x01…" 400 -

Почему браузер пошёл по HTTPS:

  • Вы так набрали адрес, или так он сохранён в закладке. Откройте http://localhost:PORT.
  • Приложение перенаправляет на HTTPS. config.force_ssl в Rails, SECURE_SSL_REDIRECT в Django и UseHttpsRedirection() в ASP.NET Core рассчитаны на продакшен; выключите их в конфигурации для разработки.
  • HSTS от прошлого проекта. Начиная с версии 132 Chrome игнорирует HSTS для localhost и *.localhost. Старые версии и собственные имена вроде myapp.test его сохраняют: удалите запись на chrome://net-internals/#hsts. Локальному имени в .dev или .app HTTPS нужен всегда; берите вместо них .test или .localhost.

Если HTTPS нужен при разработке, дайте dev-серверу сертификат. В Next.js есть next dev --experimental-https, который создаёт самоподписанный; mkcert выпускает локально доверенные сертификаты для любого dev-сервера.

Не эта ошибка: проблемы с версией, шифром и сертификатом

Другой код значит, что рукопожатие продвинулось дальше. Сервер только с TLS 1.0 или 1.1 или без шифра, который принимает Chrome, даёт ERR_SSL_VERSION_OR_CIPHER_MISMATCH с надписью «На сайте … используется неподдерживаемый протокол». Просроченный, самоподписанный или выданный на другое имя сертификат даёт код NET::ERR_CERT_* под заголовком «Подключение не защищено» (Your connection is not private).

В Яндекс Браузере у ERR_SSL_VERSION_OR_CIPHER_MISMATCH есть ещё одна частая причина. Согласно справке Браузера, обычно это значит, что сервер поддерживает только TLS с шифрованием по ГОСТ, а поддержка ГОСТ в Браузере выключена. Её включает опция «Подключаться к сайтам, использующим шифрование по ГОСТ. Требуется КриптоПро CSP» в разделе Настройки → Системные → Сеть; КриптоПро CSP должен быть установлен на компьютере.

Чек-лист после любых изменений HTTPS

  • sudo nginx -t пишет test is successful, а перезагрузка ничего не вывела.
  • curl -sS -i http://example.com:443/ отвергается с кодом 400, а curl -4 и curl -6 к https:// оба возвращают код статуса — при проверке снаружи сервера.
  • Порты 80 и 443 открыты в файрволе: как открыть и проверить оба, рассказано в статье порты 443 и 80 (англ.).

На Linux VPS от VMHeaven у вас есть root для каждого шага из этой статьи, а если правка nginx или файрвола отрежет доступ, VNC-консоль в панели, которая открывается прямо в браузере, по-прежнему достаёт до сервера.

Частые вопросы

Ошибка ERR_SSL_PROTOCOL_ERROR — это проблема у меня или у сайта?

Откройте сайт из другой сети, например с телефона через мобильный интернет, или выполните с любого сервера «curl -sv https://example.com/». Если не работает нигде, сломан сайт: обычно на порту 443 отвечает обычный HTTP. Если ошибка только на вашем компьютере или в вашей сети, ищите причину в проверке HTTPS антивирусом, корпоративном файрволе, VPN или прокси.

Как исправить ERR_SSL_PROTOCOL_ERROR в Яндекс Браузере?

Так же, как в Chrome: Яндекс Браузер построен на Chromium и показывает тот же код. Откройте сайт в другом браузере и из другой сети, временно отключите проверку HTTPS в антивирусе, проверьте прокси. Если вместо этого кода Браузер пишет ERR_SSL_VERSION_OR_CIPHER_MISMATCH на сайте с шифрованием по ГОСТ, установите КриптоПро CSP и включите в разделе «Настройки → Системные → Сеть» опцию «Подключаться к сайтам, использующим шифрование по ГОСТ. Требуется КриптоПро CSP».

Помогает ли «Очистить SSL» или очистка кеша при ERR_SSL_PROTOCOL_ERROR?

Редко. Кеш хранит страницы, а не рукопожатия, а кнопка «Очистить SSL» в свойствах браузера Windows затрагивает собственный TLS-стек Windows, а не Chrome или Edge. Помочь может удаление устаревшей записи HSTS на chrome://net-internals/#hsts, если хост больше не отдаёт HTTPS, а если ошибка только у вас — временное отключение проверки защищённых соединений в антивирусе.

Читайте также

Все статьи раздела