Golang: Как выполнить запрос https с плохим сертификатом?
Скажем, я хочу получить https://golang.org
программно. В настоящее время golang.org(ssl) имеет плохой сертификат, который выдается *.appspot.com
So, когда я запускаю это:
package main
import (
"log"
"net/http"
)
func main() {
_, err := http.Get("https://golang.org/")
if err != nil {
log.Fatal(err)
}
}
Я получаю (как и ожидалось)
Get https://golang.org/: certificate is valid for *.appspot.com, *.*.appspot.com, appspot.com, not golang.org
Теперь я хочу доверять этому сертификату самостоятельно (представьте себе самовыраженный сертификат, где я могу проверить отпечаток пальца и т.д.): как я могу сделать запрос и проверить/доверять сертификату?
Мне, вероятно, нужно использовать openssl для загрузки сертификата, загрузки его в файл и заполнения tls.Config
struct!?
Ответы
Ответ 1
Вы можете отключить проверку безопасности (на свой страх и риск):
package main
import (
"fmt"
"net/http"
"crypto/tls"
)
func main() {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}
_, err := client.Get("https://golang.org/")
if err != nil {
fmt.Println(err)
}
}
Ответ 2
Если вы хотите использовать настройки по умолчанию из пакета http, поэтому вам не нужно создавать новый объект Transport and Client, вы можете изменить игнорировать проверку сертификата следующим образом:
tr := http.DefaultTransport.(*http.Transport)
tr.TLSClientConfig.InsecureSkipVerify = true
Ответ 3
Здесь вы можете сделать это, не потеряв настройки по умолчанию DefaultTransport
и не нуждаясь в поддельном запросе в соответствии с комментариями пользователя.
defaultTransport := http.DefaultTransport.(*http.Transport)
// Create new Transport that ignores self-signed SSL
httpClientWithSelfSignedTLS := &http.Transport{
Proxy: defaultTransport.Proxy,
DialContext: defaultTransport.DialContext,
MaxIdleConns: defaultTransport.MaxIdleConns,
IdleConnTimeout: defaultTransport.IdleConnTimeout,
ExpectContinueTimeout: defaultTransport.ExpectContinueTimeout,
TLSHandshakeTimeout: defaultTransport.TLSHandshakeTimeout,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
Ответ 4
Все эти ответы неверны! Не используйте InsecureSkipVerify для работы с CN, который не соответствует имени хоста. Разработчики Go были необоснованны, не отказываясь от проверки имени хоста (который имеет законное использование - туннели, nats, общие сертификаты кластера и т.д.), А также имеют нечто похожее, но фактически полностью игнорируют проверку сертификата. Вы должны знать, что сертификат действителен и подписан сертификатом, которому вы доверяете. Но в общих сценариях вы знаете, что CN не будет соответствовать имени хоста, с которым вы связаны. Для них установите ServerName на tls.Config. Если tls.Config.ServerName == remoteServerCN, то проверка сертификата будет успешной. Это то, что вы хотите. InsecureSkipVerify означает, что нет аутентификации; и он созрел для "Человек-в-середине"; победив цель использования TLS.
Существует одно законное использование для InsecureSkipVerify... Используйте его для подключения к хосту и получения его сертификата, а затем немедленно отключите его. Если вы настроите свой код на использование InsecureSkipVerify, это обычно потому, что вы не правильно установили имя_сервера (ему нужно будет перейти от env var или что-то еще - не бойтесь этого требования... сделайте это правильно).
В частности, если вы используете клиентские сертификаты и полагаетесь на них для проверки подлинности, у вас в основном есть поддельный логин, который больше не регистрируется. Код отказа, который делает InsecureSkipVerify, или вы узнаете, что с ним не так сложно!