Dites que je veux obtenir https://golang.org
par programme. Actuellement, golang.org (ssl) a un mauvais certificat qui est attribué à *.appspot.com
Donc quand j’exécute ceci:
package main
import (
"log"
"net/http"
)
func main() {
_, err := http.Get("https://golang.org/")
if err != nil {
log.Fatal(err)
}
}
Je reçois (comme je m'y attendais)
Get https://golang.org/: certificate is valid for *.appspot.com, *.*.appspot.com, appspot.com, not golang.org
Maintenant, je veux faire confiance à ce certificat moi-même (imaginez un certificat auto-émis où je puisse valider une empreinte digitale, etc.): comment puis-je faire une demande et valider/faire confiance au certificat?
J'ai probablement besoin d'utiliser openssl pour télécharger le certificat, le charger dans mon fichier et remplir tls.Config
struct!?
Note de sécurité: Désactiver les contrôles de sécurité est dangereux et doit être évité
Vous pouvez désactiver les contrôles de sécurité globalement pour toutes les demandes du client par défaut:
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)
}
}
Vous pouvez désactiver le contrôle de sécurité pour un client:
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)
}
}
Voici un moyen de le faire sans perdre les paramètres par défaut de la DefaultTransport
et sans avoir besoin de la fausse demande conformément au commentaire de l'utilisateur.
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},
}
Toutes ces réponses sont fausses! N'utilisez pas InsecureSkipVerify
pour traiter un CN qui ne correspond pas au nom d'hôte. Les développeurs de Go ont imprudemment insisté sur le fait de ne pas désactiver les vérifications de nom d’hôte (qui ont des utilisations légitimes - tunnels, nats, certificats de cluster partagés, etc.), tout en conservant un aspect similaire mais en réalité complètement ignore la vérification du certificat. Vous devez savoir que le certificat est valide et signé par un certificat en lequel vous avez confiance. Mais dans les scénarios courants, vous savez que le CN ne correspond pas au nom d’hôte avec lequel vous vous êtes connecté. Pour ceux-ci, définissez ServerName
sur tls.Config
. Si tls.Config.ServerName
== remoteServerCN, la vérification du certificat réussira. Voici ce que vous voulez. InsecureSkipVerify
signifie qu'il n'y a PAS d'authentification; et c'est mûr pour un homme du milieu; vider l'objectif d'utiliser TLS.
Il y a une utilisation légitime pour InsecureSkipVerify
: utilisez-le pour vous connecter à un hôte et récupérer son certificat, puis déconnectez-vous immédiatement. Si vous configurez votre code pour utiliser InsecureSkipVerify
, c'est généralement parce que vous n'avez pas défini ServerName
correctement (cela doit provenir d'une variable d'env ou quelque chose d'autre. N'ayez pas mal au ventre à propos de cette exigence ... faites le correctement).
En particulier, si vous utilisez des certificats de client et comptez sur eux pour l'authentification, vous disposez en réalité d'un faux login qui ne se connecte plus. Refusez le code qui contient InsecureSkipVerify
ou vous apprendrez ce qui ne va pas avec cela à la dure!
Si vous souhaitez utiliser les paramètres par défaut du package http, de sorte que vous n'avez pas besoin de créer un nouvel objet Transport et Client, vous pouvez modifier pour ignorer la vérification du certificat comme suit:
tr := http.DefaultTransport.(*http.Transport)
tr.TLSClientConfig.InsecureSkipVerify = true
Généralement, le domaine DNS de l'URL DOIT correspondre à l'objet du certificat du certificat.
Auparavant, vous pouviez définir le domaine en tant que cn du certificat ou en définissant le domaine en tant que nom alternatif de sujet.
La prise en charge de cn était obsolète depuis longtemps (depuis 2000 dans RFC 2818 ) et le navigateur Chrome ne le regarde même plus. Aujourd'hui, vous devez disposer du domaine DNS de l'URL comme nom alternatif du sujet. .
RFC 6125 qui interdit de vérifier le cn si SAN pour le domaine DNS est présent, mais pas si SAN pour l'adresse IP est présent. La RFC 6125 répète également que cn est obsolète, ce qui avait déjà été dit dans la RFC 2818. Le forum du navigateur de l'autorité de certification est également présent, ce qui, combiné à la RFC 6125, signifie essentiellement que cn ne sera jamais vérifié pour le nom de domaine DNS.