Сообщение об ошибке
tls: client offered only unsupported versions: [301]
net/http записывает это как «http: TLS handshake error from <client address>: tls: client offered only unsupported versions: [301]»; в списке перечислены все версии, которые предложил клиент (300 = SSL 3.0, 301 = TLS 1.0, 302 = TLS 1.1).
Go crypto/tls server (net/http ErrorLog) — the client offered only TLS versions below the server's minimum
Что это означает
TLS-сервер на Go получил ClientHello, в котором предложены только версии протокола ниже его минимальной, в данном случае TLS 1.0 (код версии 301). Серверы на Go по умолчанию принимают TLS 1.2 и 1.3, поэтому рукопожатие отклоняется с оповещением protocol_version, а net/http записывает эту строку в журнал. Клиент на другой стороне либо устарел, либо намеренно прощупывает сервер.
Почему это происходит
Устаревшие клиенты
частоУстаревшие устройства, старые приложения на Java 6/7 или .NET Framework и встроенные HTTP-клиенты, которые не умеют работать с TLS 1.2.
Интернет-сканеры и инструменты безопасности
частоСканеры намеренно предлагают старые версии, чтобы классифицировать серверы; на публичных эндпоинтах такие строки с множества разных адресов — обычное дело.
Клиенты, настроенные на старую версию
иногдаПриложения, в которых протокол жёстко зафиксирован на TLS 1.0 ради давно исчезнувшей устаревшей интеграции.
Как исправить
- 1.
Выясните, кто их отправляет
Сгруппируйте строки журнала по адресу клиента: несколько известных адресов означают устаревших клиентов, которых нужно обновить, а множество неизвестных — сканеры.
bash # Which addresses send these handshakes, and how often? journalctl -u myservice --since today | grep 'client offered only unsupported versions' \ | grep -oE 'from [0-9a-f.:]+' | sort | uniq -c | sort -rn | head - 2.
Оставьте TLS 1.2 минимальной версией на сервере
Не понижайте MinVersion ради сканеров; вместо этого обновите немногочисленных легитимных старых клиентов.
go // Keep TLS 1.2 as the minimum (Go's server default); set it explicitly to document intent srv := &http.Server{Addr: ":443", TLSConfig: &tls.Config{MinVersion: tls.VersionTLS12}} - 3.
Отделите шум рукопожатий
Ошибки рукопожатия попадают в http.Server.ErrorLog; если направить его в отдельный логгер, журналы приложения останутся читаемыми.
go // Route handshake noise from scanners to a separate logger instead of the main log srv.ErrorLog = log.New(handshakeLogWriter, "tls: ", 0)