php小編蘋果在這裡為大家帶來解決"proxyconnect tcp: tls: 第一筆記錄看起來不像 TLS 握手"問題的方法。這種錯誤通常出現在使用代理伺服器時,可能會導致網路連線問題。在解決此問題之前,我們首先需要了解問題的根源。透過以下簡潔的步驟,我們將向您展示如何修復這個問題,以確保您的網路連線正常運作。
在如何在 Go 中使用 REST API 中,提供了一個完全有效的範例程式碼來呼叫公共 REST API。但如果我嘗試範例,則會出現此錯誤:
error getting cat fact: Get "https://catfact.ninja/fact": proxyconnect tcp: tls: first record does not look like a TLS handshake
有關http狀態的文檔
<code> For control over proxies, TLS configuration, keep-alives, compression, and other settings, create a Transport: </code>
以及傳輸文件:
<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>
因此,我假設我必須設定 Dialcontext 才能啟用從客戶端到代理的不安全連線 without TLS
。但我不知道該怎麼做。閱讀這些:
也沒有幫助。有些有同樣的錯誤 proxyconnect tcp: tls:first record does not Look like a TLS handshake
並解釋原因:
<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>
但是Steffen的回覆沒有範例程式碼如何設定DialContext func(ctx context.Context, network, addr string)
,Bogdan和cyberdelia都建議設定tls.Config{InsecureSkipVerify: true}
,例如這樣
<code> tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } client := &http.Client{Transport: tr} </code>
但是上面的沒有效果。我仍然遇到同樣的錯誤。並且連接仍然調用 https://*
而不是 http://*
這是範例程式碼,我嘗試包含上述建議並對其進行調整:
<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>
如何將連線配置為使用從 myClient 透過代理程式到伺服器的未加密連線?設定 DialContext func(ctx context.Context, network, addr string)
有助於做到這一點嗎?怎麼辦?
我剛剛嘗試過:
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) }
它包括:
自訂撥號函數customDialContext
:
#
該函數目前是 net.Dial
的簡單包裝,但它提供了一個可以在必要時引入自訂撥號邏輯的位置。它用作自訂撥號功能,用於建立網路連線。
傳輸設定:
http.Transport
,包括自訂撥號功能、環境中的代理設定以及跳過憑證驗證的 TLS 配置(用於測試)。 http.Transport
,但僅包含跳過憑證驗證的TLS配置,並沒有設定自訂撥號功能或代理設定。 客戶端設定:
http.Transport
建立新的 http.Client
,並設定逾時為 10 秒。 http.Transport
建立新的http.Client
,但後來在main
函數中,它使用新的http.Client
覆寫了client
變量,其中包含預設的Transport
和逾時10秒的,有效丟棄自訂的Transport
。 函數簽章:
GetCatFact
和GetJson
函數以接受*http.Client
參數,允許它們使用在main
中建立的自訂http.Client
。 http.Client
傳遞給這些函數,因此它們將使用 net/http
套件提供的預設 http.Client
。 網址:
GetCatFact
函數中的 URL 恢復為“https://catfact.ninja/fact”,因為伺服器無論如何都會將 HTTP 請求重新導向到 HTTPS。 上面提供的程式碼中的 customDialContext
函數不包含任何專門忽略 TLS 握手錯誤或將 TLS 握手更改為非 TLS 連線的邏輯。它只提供了自訂撥號功能,在提供的形式中,直接呼叫net.Dial
,無需任何特殊處理。
忽略TLS憑證驗證錯誤的機制實際上是由http.Transport
結構體的TLSClientConfig
欄位提供的,具體是將InsecureSkipVerify
欄位設定為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 连接。
以上是如何修復 proxyconnect tcp: tls: 第一筆記錄看起來不像 TLS 握手的詳細內容。更多資訊請關注PHP中文網其他相關文章!