Maison  >  Article  >  développement back-end  >  Comment réparer proxyconnect tcp : tls : le premier enregistrement ne ressemble pas à une poignée de main TLS

Comment réparer proxyconnect tcp : tls : le premier enregistrement ne ressemble pas à une poignée de main TLS

王林
王林avant
2024-02-11 10:18:07606parcourir

如何修复 proxyconnect tcp: tls: 第一条记录看起来不像 TLS 握手

Éditeur PHP Apple est là pour vous apporter une solution au problème « proxyconnect tcp : tls : le premier enregistrement ne ressemble pas à une prise de contact TLS ». Cette erreur se produit généralement lors de l'utilisation d'un serveur proxy et peut entraîner des problèmes de connexion réseau. Avant de pouvoir résoudre ce problème, nous devons d’abord comprendre la source du problème. Avec les étapes simples suivantes, nous allons vous montrer comment résoudre ce problème pour garantir le bon fonctionnement de votre connexion réseau.

Contenu de la question

Dans Comment utiliser l'API REST dans Go, un exemple de code entièrement fonctionnel est fourni pour appeler l'API REST publique. Mais si j'essaie l'exemple, j'obtiens cette erreur :

error getting cat fact: 
      Get "https://catfact.ninja/fact": 
      proxyconnect tcp: tls: first record does not look like a TLS handshake

Documentation sur le statut http

<code>
For control over proxies, TLS configuration, keep-alives, compression, and other settings, create a Transport:
</code>

Et documents de transfert :

<code>    // DialContext specifies the dial function for creating unencrypted TCP connections.
    // If DialContext is nil (and the deprecated Dial below is also nil),
    // then the transport dials using package net.
    //
    // DialContext runs concurrently with calls to RoundTrip.
    // A RoundTrip call that initiates a dial may end up using
    // a connection dialed previously when the earlier connection
    // becomes idle before the later DialContext completes.
    DialContext func(ctx context.Context, network, addr string) (net.Conn, error)
</code>

Je suppose donc que je dois configurer le Dialcontext pour activer les connexions non sécurisées du client au proxy without TLS. Mais je ne sais pas comment faire. Lisez-les :

  • Comment faire du proxy et du TLS dans Golang ;
  • Comment faire HTTP/HTTPS GET via proxy et
  • Comment effectuer une requête https avec un mauvais certificat ?

Pas utile non plus. Certains ont la même erreur proxyconnect tcp: tls:first record does not Look like a TLS handshake et expliquent pourquoi :

<code>
This is because the proxy answers with an plain HTTP error to the strange HTTP request (which is actually the start of the TLS handshake).
</code>

Mais la réponse de Steffen ne contient pas d'exemple de code sur la façon de le configurer DialContext func(ctx context.Context, network, addr string),Bogdan和cyberdelia都建议设置tls.Config{InsecureSkipVerify: true}, par exemple comme celui-ci

<code>    tr := &http.Transport{
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    }
    client := &http.Client{Transport: tr}
</code>

Mais ce qui précède n’a aucun effet. Je reçois toujours la même erreur. et la connexion appelle toujours https://* 而不是 http://*

Voici un exemple de code, j'ai essayé d'inclure les suggestions ci-dessus et de l'adapter :

<code>var tr = &http.Transport{ TLSClientConfig: 
                           &tls.Config{InsecureSkipVerify: true}, } 
                           // lacks DialContext config
var client*  http.Client = &http.Client{Transport: tr} // modified * added
// var client *http.Client // code from tutorial

type CatFact struct {
    Fact   string `json:"fact"`
    Length int    `json:"length"`
}

func GetCatFact() {
    url := "http://catfact.ninja/fact" // changed from https to http
    var catFact CatFact

    err := GetJson(url, &catFact)
    if err != nil {
        fmt.Printf("error getting cat fact: %s\n", err.Error())
    } else {
        fmt.Printf("A super interesting Cat Fact: %s\n", catFact.Fact)
    }
}

func main() {
    client = &http.Client{Timeout: 10 * time.Second}
    GetCatFact()
    // same error 
    // proxyconnect tcp: tls: first record does 
    //                   not look like a TLS handshake
    // still uses https 
    // for GET catfact.ninja
}
</code>

Comment configurer la connexion pour utiliser une connexion non cryptée de myClient au serveur via un proxy ? Le réglage DialContext func(ctx context.Context, network, addr string) aide-t-il à cela ? ce qu'il faut faire?

Solution

Je viens d'essayer :

package main

import (
    "context"
    "crypto/tls"
    "encoding/json"
    "fmt"
    "net"
    "net/http"
    "time"
)

type CatFact struct {
    Fact   string `json:"fact"`
    Length int    `json:"length"`
}

// Custom dialing function to handle connections
func customDialContext(ctx context.Context, network, addr string) (net.Conn, error) {
    conn, err := net.Dial(network, addr)
    return conn, err
}

// Function to get a cat fact
func GetCatFact(client *http.Client) {
    url := "https://catfact.ninja/fact"  // Reverted back to https
    var catFact CatFact

    err := GetJson(url, &catFact, client)
    if err != nil {
        fmt.Printf("error getting cat fact: %s\n", err.Error())
    } else {
        fmt.Printf("A super interesting Cat Fact: %s\n", catFact.Fact)
    }
}

// Function to send a GET request and decode the JSON response
func GetJson(url string, target interface{}, client *http.Client) error {
    resp, err := client.Get(url)
    if err != nil {
        return fmt.Errorf("error sending GET request: %w", err)
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        return fmt.Errorf("received non-OK HTTP status: %d", resp.StatusCode)
    }

    err = json.NewDecoder(resp.Body).Decode(target)
    if err != nil {
        return fmt.Errorf("error decoding JSON response: %w", err)
    }

    return nil
}

func main() {
    // Create a custom Transport with the desired settings
    tr := &http.Transport{
        Proxy: http.ProxyFromEnvironment,  // Use the proxy settings from the environment
        DialContext: customDialContext,    // Use the custom dialing function
        TLSClientConfig: &tls.Config{
            InsecureSkipVerify: true,  // Skip certificate verification (not recommended in production)
        },
    }

    // Create a new HTTP client using the custom Transport
    client := &http.Client{
        Transport: tr,
        Timeout:   10 * time.Second,
    }

    // Call the function to get a cat fact
    GetCatFact(client)
}

Il comprend :

  • Fonction de numérotation personnaliséecustomDialContext :
    Cette fonction est actuellement un simple wrapper autour de net.Dial , mais elle fournit un endroit pour introduire une logique de numérotation personnalisée si nécessaire. Il est utilisé comme fonction de numérotation personnalisée pour créer des connexions réseau.

  • Configuration de la transmission :

    • Le code modifié est personnalisé http.Transport avec une configuration de paramètres spécifiques, notamment une fonctionnalité de numérotation personnalisée, des paramètres de proxy dans l'environnement et une configuration TLS qui ignore la vérification du certificat (à des fins de test).
    • Le code d'origine tentait également de configurer un http.Transport personnalisé, mais incluait uniquement une configuration TLS qui ignorait la vérification du certificat et ne définissait pas de capacités de numérotation personnalisées ni de paramètres de proxy.
  • Configuration client :

    • Le code modifié utilise un http.Transport 创建新的 http.Client personnalisé pour créer un nouveau http.Client et définir le délai d'attente à 10 secondes.
    • Le code d'origine essaie également de créer un nouveau http.Client en utilisant la personnalisation http.Transport 创建新的 http.Client ,但后来在 main 函数中,它使用新的 http.Client 覆盖了 client 变量,其中包含默认的 Transport 和超时10秒的,有效丢弃自定义的 Transport mais ensuite dans la fonction main, il utilise le nouveau http.Client Remplace la variable client, qui contient le Transport par défaut et un délai d'attente de 10 secondes, supprimant ainsi le Transport personnalisé.
  • Signature de fonction :

    • Le code modifié a été modifié GetCatFactGetJson 函数以接受 *http.Client 参数,允许它们使用在 main 中创建的自定义 http.Client.
    • Le code original n'incluait pas http.Client 传递给这些函数,因此它们将使用 net/http 包提供的默认 http.Client .
  • Site Internet :

    • Le code modifié restaure l'URL de la fonction GetCatFact vers "https://catfact.ninja/fact" puisque le serveur redirige de toute façon les requêtes HTTP vers HTTPS.
    • Le code d'origine a modifié l'URL en "http://catfact.ninja/fact" pour éviter les erreurs de négociation TLS.

La fonction customDialContext 函数不包含任何专门忽略 TLS 握手错误或将 TLS 握手更改为非 TLS 连接的逻辑。它只提供了自定义拨号功能,在提供的形式中,直接调用net.Dial dans le code fourni ci-dessus ne contient aucune logique permettant d'ignorer spécifiquement les erreurs de prise de contact TLS ou de modifier la prise de contact TLS en une connexion non TLS. Il fournit uniquement des fonctions de numérotation personnalisées, sous la forme fournie, appelant directement

sans aucun traitement particulier.

http.Transport结构体的TLSClientConfig字段提供的,具体是将InsecureSkipVerify字段设置为trueLe mécanisme permettant d'ignorer les erreurs de vérification du certificat TLS est en fait fourni par le champ TLSClientConfig de la

structure, notamment en définissant le champ InsecureSkipVerify sur true. :🎜
tr := &http.Transport{
    TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}

该配置告诉 Go 跳过验证服务器的证书链和主机名,这是 TLS 握手过程的一部分。但是,它不会忽略其他类型的 TLS 握手错误或切换到非 TLS 连接。通常不建议在生产环境中使用 InsecureSkipVerify: true,因为它会禁用重要的安全检查。

如果您想强制使用非 TLS(纯 HTTP)连接,通常只需使用 http:// URL,而不是 https:// URL。但是,如果服务器或代理服务器将 HTTP 重定向到 HTTPS(例如 http://catfact.ninja/fact 的情况),则客户端将遵循重定向并切换到 TLS 连接。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer