当前位置:首页 > 文章列表 > Golang > Go问答 > 如何解决 ProxyConnect TCP:TLS:第一条记录不正确的 TLS 握手问题

如何解决 ProxyConnect TCP:TLS:第一条记录不正确的 TLS 握手问题

来源:stackoverflow 2024-02-02 21:14:39 0浏览 收藏

本篇文章向大家介绍《如何解决 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状态的文档


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

以及传输文档:

    // 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)

因此,我假设我必须配置 Dialcontext 才能启用从客户端到代理的不安全连接 without TLS。但我不知道该怎么做。阅读这些:

  • 如何在golang中进行代理和TLS;
  • 如何通过代理进行 HTTP/HTTPS GET;和
  • 如何使用错误的证书执行 https 请求?

也没有帮助。有些有同样的错误 proxyconnect tcp: tls:first record does not Look like a TLS handshake 并解释原因:


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).

但是Steffen的回复没有示例代码如何设置DialContext func(ctx context.Context, network, addr string),Bogdan和cyberdelia都建议设置tls.Config{InsecureSkipVerify: true},例如这样

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

但是上面的没有效果。我仍然遇到同样的错误。并且连接仍然调用 https://* 而不是 http://*

这是示例代码,我尝试包含上述建议并对其进行调整:

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
}

如何将连接配置为使用从 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
  • 函数签名:

    • 修改后的代码修改了 GetCatFactGetJson 函数以接受 *http.Client 参数,允许它们使用在 main 中创建的自定义 http.Client
    • 原始代码没有将 http.Client 传递给这些函数,因此它们将使用 net/http 包提供的默认 http.Client
  • 网址:

    • 修改后的代码将 GetCatFact 函数中的 URL 恢复为“https://catfact.ninja/fact”,因为服务器无论如何都会将 HTTP 请求重定向到 HTTPS。
    • 原始代码已将 URL 更改为“http://catfact.ninja/fact”,以避免 TLS 握手错误。

上面提供的代码中的 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 握手问题》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!

版本声明
本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
这两个字符串的分配是否相同?这两个字符串的分配是否相同?
上一篇
这两个字符串的分配是否相同?
设置Go HTTP服务器标头的内容类型为multipart/form-data,但在客户端获取的Content-Type为text/plain
下一篇
设置Go HTTP服务器标头的内容类型为multipart/form-data,但在客户端获取的Content-Type为text/plain
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    508次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    497次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • SEO标题协启动:AI驱动的智能对话与内容生成平台 - 提升创作效率
    协启动
    SEO摘要协启动(XieQiDong Chatbot)是由深圳协启动传媒有限公司运营的AI智能服务平台,提供多模型支持的对话服务、文档处理和图像生成工具,旨在提升用户内容创作与信息处理效率。平台支持订阅制付费,适合个人及企业用户,满足日常聊天、文案生成、学习辅助等需求。
    2次使用
  • 谱乐AI:青岛艾夫斯科技的多模型AI音乐生成工具
    谱乐AI
    谱乐AI是由青岛艾夫斯科技有限公司开发的AI音乐生成工具,采用Suno和Udio模型,支持多种音乐风格的创作。访问https://yourmusic.fun/,体验智能作曲与编曲,个性化定制音乐,提升创作效率。
    7次使用
  • Vozo AI:超真实AI视频换脸工具,提升创意内容制作
    Vozo AI
    探索Vozo AI,一款功能强大的在线AI视频换脸工具,支持跨性别、年龄和肤色换脸,适用于广告本地化、电影制作和创意内容创作,提升您的视频制作效率和效果。
    7次使用
  • AIGAZOU:免费AI图像生成工具,简洁高效,支持中文
    AIGAZOU-AI图像生成
    AIGAZOU是一款先进的免费AI图像生成工具,无需登录即可使用,支持中文提示词,生成高清图像。适用于设计、内容创作、商业和艺术领域,提供自动提示词、专家模式等多种功能。
    7次使用
  • Raphael AI:Flux.1 Dev支持的免费AI图像生成器
    Raphael AI
    探索Raphael AI,一款由Flux.1 Dev支持的免费AI图像生成器,无需登录即可无限生成高质量图像。支持多种风格,快速生成,保护隐私,适用于艺术创作、商业设计等多种场景。
    7次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码