web-dev-qa-db-ja.com

不正な証明書で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!?

106
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)
    }
}
229
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

これらの答えはすべて間違っています!ホスト名と一致しないCNを処理するためにInsecureSkipVerifyを使用しないでください。 Go開発者は、ホスト名チェック(トンネル、NAT、共有クラスター証明書など)を無効にしないことを賢明に断念しましたが、同様に見えるが実際には完全は証明書チェックを無視します証明書が有効であり、信頼できる証明書によって署名されていることを知る必要があります。しかし、一般的なシナリオでは、CNが接続先のホスト名と一致しないことを知っています。それらの場合、tls.ConfigServerNameを設定します。 tls.Config.ServerName == remoteServerCNの場合、証明書のチェックは成功します。これはあなたが望むものです。 InsecureSkipVerifyは、認証がないことを意味します。そして、それはMan-In-The-Middleのために熟しています。 TLSを使用する目的を無効にする。

InsecureSkipVerifyには正当な使用法が1つあります。それを使用してホストに接続し、証明書を取得して、すぐに切断します。 InsecureSkipVerifyを使用するようにコードを設定する場合、通常はServerNameを適切に設定しなかったためです(env varなどから取得する必要があります-この要件については気にしないでください)。 ..正しく行う)。

特に、クライアント証明書を使用し、それらの認証に依存している場合、基本的には実際にはもうログインしない偽のログインがあります。 InsecureSkipVerifyを実行しないコードを拒否します。そうしないと、困難な点がわかります。

12
Rob

Httpパッケージのデフォルト設定を使用するため、新しいトランスポートおよびクライアントオブジェクトを作成する必要がない場合は、次のように証明書の検証を無視するように変更できます。

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

通常、URLのDNSドメインは、証明書の証明書サブジェクトと一致する必要があります。

以前は、ドメインを証明書のcnとして設定するか、ドメインをサブジェクトの別名として設定することでこれを行うことができました。

Cnのサポートは長い間廃止されました(2000年以降 RFC 2818 であったため)。また、Chromeブラウザはcnを参照しなくなるため、今日はDNSサブジェクトの別名としてのURLのドメイン。

RFC 6125 DNSドメインのSANが存在する場合はcnのチェックを禁止しますが、IPアドレスのSANは存在しません。また、RFC 6125は、cnが廃止されていることを繰り返します。これは、RFC 2818で既に述べられています。

0
jwilleke