it-swarm.com.ru

Как сделать запрос https с плохим сертификатом?

Скажем, я хочу получить https://golang.org программно. В настоящее время golang.org (ssl) имеет неверный сертификат, который выдается *.appspot.com, поэтому, когда я запускаю это:

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!?

93
topskip

Примечание по безопасности: отключение проверок безопасности опасно и его следует избегать

Вы можете отключить проверки безопасности глобально для всех запросов клиента по умолчанию:

package main

import (
    "fmt"
    "net/http"
    "crypto/tls"
)

func main() {
    http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
    _, err := http.Get("https://golang.org/")
    if err != nil {
        fmt.Println(err)
    }
}

Вы можете отключить проверку безопасности для клиента:

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)
    }
}
204
cyberdelia

Вот способ сделать это, не теряя настройки по умолчанию для 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},
}
13
Jonathan Lin

Все эти ответы неверны! Не используйте InsecureSkipVerify для работы с CN, который не соответствует имени хоста. Разработчики Go неразумно были непреклонны в том, чтобы не отключать проверки имени хоста (которые имеют законное применение - туннели, nats, сертификаты общего кластера и т.д.), И в то же время иметь что-то похожее, но на самом деле полностью игнорирует проверку сертификата. Вы должны знать, что сертификат действителен и подписан сертификатом, которому вы доверяете. Но в обычных сценариях вы знаете, что CN не будет соответствовать имени хоста, с которым вы связаны. Для них установите ServerName на tls.Config. Если tls.Config.ServerName == remoteServerCN, то проверка сертификата будет выполнена успешно. Это то, что вы хотите. InsecureSkipVerify означает, что нет аутентификации; и он созрел для человека в середине; победив цель использования TLS.

Существует одно допустимое использование InsecureSkipVerify: используйте его для подключения к хосту и получения его сертификата, а затем немедленно отключите. Если вы настраиваете свой код для использования InsecureSkipVerify, это, как правило, потому, что вы не установили ServerName должным образом (он должен исходить из env var или чего-то еще - не переживайте из-за этого требования ... делайте это правильно).

В частности, если вы используете клиентские сертификаты и полагаетесь на них для аутентификации, у вас, в основном, есть фальшивый логин, который на самом деле больше не авторизуется. Откажитесь от кода, который делает InsecureSkipVerify, или вы узнаете, что с ним не так, как надо!

8
Rob

Если вы хотите использовать настройки по умолчанию из пакета http, поэтому вам не нужно создавать новый объект транспорта и клиента, вы можете изменить игнорирование проверки сертификата следующим образом:

tr := http.DefaultTransport.(*http.Transport)
tr.TLSClientConfig.InsecureSkipVerify = true
7
Cornel Damian

Обычно DNS-домен URL-адреса ДОЛЖЕН совпадать с темой сертификата сертификата.

В прежние времена это можно было сделать либо установив домен как cn сертификата, либо указав домен в качестве альтернативного имени субъекта. 

Поддержка cn давно устарела (с 2000 г. в RFC 2818 ), и браузер Chrome больше не будет даже смотреть на cn, поэтому сегодня вам нужно иметь домен DNS URL в качестве альтернативного имени субъекта ,

RFC 6125 который запрещает проверку cn, если SAN для DNS-домена присутствует, но нет, если SAN для IP-адреса присутствует. RFC 6125 также повторяет, что cn устарел, что уже было сказано в RFC 2818. И должен присутствовать форум по сертификации Certification Authority, который в сочетании с RFC 6125, по сути, означает, что cn никогда не будет проверяться на предмет доменного имени DNS.

0
jwilleke