TLS и закрепление сертификатов
Управление версиями TLS
HTTPC по умолчанию требует TLS 1.2+, рекомендуется TLS 1.3:
cfg := httpc.DefaultConfig()
cfg.Security.MinTLSVersion = tls.VersionTLS12 // по умолчанию
cfg.Security.MaxTLSVersion = tls.VersionTLS13 // по умолчаниюОписание версий
| Версия | Статус | По умолчанию в HTTPC |
|---|---|---|
| TLS 1.0 | Небезопасна, устарела | Отклоняется |
| TLS 1.1 | Небезопасна, устарела | Отклоняется |
| TLS 1.2 | Безопасна | Минимальное требование |
| TLS 1.3 | Наиболее безопасна, рекомендуется | Поддерживается |
Шифрские наборы
Конфигурация по умолчанию допускает только безопасные шифрские наборы:
| Шифрский набор | Описание |
|---|---|
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 | Рекомендуется |
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 | Рекомендуется |
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 | Рекомендуется |
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 | Рекомендуется |
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 | Рекомендуется |
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 | Рекомендуется |
Пользовательская конфигурация TLS
cfg := httpc.DefaultConfig()
cfg.Security.TLSConfig = &tls.Config{
MinVersion: tls.VersionTLS13, // Принудительный TLS 1.3
// Другие пользовательские настройки
}Пользовательский CA-сертификат
caCert, _ := os.ReadFile("custom-ca.pem")
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
cfg := httpc.DefaultConfig()
cfg.Security.TLSConfig = &tls.Config{
RootCAs: caCertPool,
MinVersion: tls.VersionTLS12,
}
client, _ := httpc.New(cfg)Взаимная аутентификация TLS (mTLS)
cert, _ := tls.LoadX509KeyPair("client-cert.pem", "client-key.pem")
cfg := httpc.DefaultConfig()
cfg.Security.TLSConfig = &tls.Config{
Certificates: []tls.Certificate{cert},
MinVersion: tls.VersionTLS12,
}
client, _ := httpc.New(cfg)Закрепление сертификатов
Закрепление сертификатов (Certificate Pinning) предотвращает атаки типа "человек посередине" путём проверки хеша открытого ключа серверного сертификата.
Закрепление хеша SPKI (рекомендуется)
Наиболее распространённый метод. Через NewSPKIHashPinner проверяется SPKI (SubjectPublicKeyInfo) SHA-256-хэш любого сертификата в серверной цепочке. Указание нескольких хэшей поддерживает ротацию ключей — соответствие любого из них считается успешным.
Генерация SPKI-хэша:
openssl x509 -in cert.pem -pubkey -noout | \
openssl pkey -pubin -outform der | \
openssl dgst -sha256 -binary | \
openssl enc -base64Закрепление промежуточного сертификата Let's Encrypt (рекомендуется закреплять именно промежуточный — баланс безопасности и стоимости поддержки):
pinner, err := httpc.NewSPKIHashPinner(
"YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2fuihg=", // Текущий промежуточный сертификат
"C5+lpZ7tcVwmwQIMcRtPbsQtWLABXhQzejna0wHFr8M=", // Резервный (ротация ключей)
)
if err != nil {
log.Fatal(err)
}
cfg := httpc.DefaultConfig()
cfg.Security.CertificatePinner = pinner
client, err := httpc.New(cfg)TIP
CertificatePinner дополняет стандартную проверку цепочки TLS, не требуя InsecureSkipVerify. Проверка применяется к любому уровню сертификата в цепочке, поэтому закрепление промежуточного сертификата остаётся действующим и после продления листового сертификата.
WARNING
Закрепление сертификатов увеличивает расходы на обслуживание. Если сервер заменяет сертификат (например, при продлении Let's Encrypt), клиенту необходимо обновить закреплённые значения. Рекомендуется закреплять несколько сертификатов одновременно (например, листовый + промежуточный) и настроить механизм обновления.
Другие конструкторы закрепления
Помимо SPKI-хэшей HTTPC предоставляет:
// Напрямую из DER-кодированных публичных ключей PKIX (внутренне вычисляется SHA-256)
pubPinner, err := httpc.NewPublicKeyPinner(pubKeyDER1, pubKeyDER2)
// Объединяет несколько pinner; принимается, если проходит хотя бы один (смешанная стратегия или ротация ключей)
chainPinner := httpc.NewCertificatePinnerChain(spkiPinner, pubPinner)
cfg.Security.CertificatePinner = chainPinnerПродвинутое: пользовательский callback проверки TLS
Если требуется полный контроль над логикой проверки TLS (например, закрепление полного сертификата, а не открытого ключа), можно реализовать его самостоятельно через TLSConfig. При этом стандартная проверка цепочки пропускается через InsecureSkipVerify, и необходимо выполнить все проверки в VerifyPeerCertificate:
cfg := httpc.DefaultConfig()
cfg.Security.TLSConfig = &tls.Config{
InsecureSkipVerify: true, // Пропускает стандартную проверку цепочки; все проверки нужно выполнить в callback
VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
// Здесь реализуется полная проверка сертификатов + логика закрепления
return nil
},
}WARNING
InsecureSkipVerify = true полностью отключает стандартную проверку цепочки сертификатов. Используйте только если действительно нужна пользовательская логика проверки, и обеспечьте выполнение всех необходимых проверок в callback. В большинстве сценариев закрепления предпочтительнее использовать CertificatePinner.
Стратегия закрепления
| Стратегия | Безопасность | Стоимость обслуживания | Рекомендация |
|---|---|---|---|
| Закрепление корневого сертификата | Низкая | Низкая | Только защита от подмены |
| Закрепление промежуточного сертификата | Средняя | Средняя | Рекомендуется |
| Закрепление листового сертификата | Высокая | Высокая | Сценарии повышенной безопасности |
| Закрепление нескольких уровней | Высокая | Средняя | Лучший вариант |
InsecureSkipVerify
// Только для тестирования!
cfg := httpc.TestingConfig()
// InsecureSkipVerify = true → пропуск проверки TLS-сертификатовDANGER
InsecureSkipVerify = true отключает все меры безопасности TLS, используйте только в тестовой среде. Никогда не устанавливайте true в продакшене.
HTTP/2
HTTP/2 включён по умолчанию, доступен только при использовании TLS:
cfg := httpc.DefaultConfig()
cfg.Connection.EnableHTTP2 = false // Отключить HTTP/2Лучшие практики
- Используйте конфигурацию TLS по умолчанию (TLS 1.2+)
- При закреплении сертификатов закрепляйте промежуточные сертификаты и подготовьте запасные закреплённые значения
- Регулярно обновляйте закреплённые значения в соответствии с продлением серверных сертификатов
- Используйте
SecureConfig()как базовую конфигурацию безопасности - Никогда не устанавливайте
InsecureSkipVerifyв продакшене
Что дальше
- Защита от SSRF - конфигурация безопасности SSRF
- Обзор безопасности - обзор функций безопасности
- Конфигурация API - справочник по SecurityConfig