【问题标题】:how browser knows end of reading data浏览器如何知道读取数据结束
【发布时间】:2022-11-11 04:19:06
【问题描述】:

我正在尝试使用 Golang 制作 https 代理。我一开始就知道,浏览器将带有结尾的标头发送到\r\n 和套接字块read(),直到读取这些字符。但是当它被加密(ssl/tls)和 HTTP 1.1(保持连接活跃)

  • 浏览器如何知道读取数据结束?
  • 他们是否逐字节读取并在末尾读取一些特殊字符(这对于大数据来说是不是一个好方法?)?
  • 或者他们先发送数据大小(如 tcp 套接字主题中所建议的那样)?
  • 作为代理,当流式传输或加载简单的 html 页面时,如何理解数据结束?

这只是代码的一部分,当我在本地网络中运行它时它可以工作,但在服务器(vps)中会阻止读取,直到连接关闭。完整代码here

func write(client_to_proxy net.Conn, browser_to_client net.Conn) {
    defer client_to_proxy.Close()
    buffer := make([]byte, 1024)

    reader := bufio.NewReader(browser_to_client)

    for {
        length, err := reader.Read(buffer)
        if length > 0 {
            fmt.Println(time.Now().Format(time.Stamp) + " READ from client to browser: " + strconv.Itoa(length))
            //fmt.Println(string(buffer[:readLeng]))

            writeLength, err := client_to_proxy.Write(buffer[:length])
            if writeLength > 0 {
                fmt.Println(time.Now().Format(time.Stamp) + " WRITE from client to browser: " + strconv.Itoa(writeLength))
            }
            if err != nil {
                fmt.Println("ERR6 ", err)
                return
            }
        }
        if err != nil {
            fmt.Println("ERR5 ", err)
            return
        }
    }
}

func read(client_to_proxy net.Conn, browser_to_client net.Conn) {
    defer browser_to_client.Close()
    buffer := make([]byte, 1024)

    reader := bufio.NewReader(client_to_proxy)
    length, err := reader.Read(buffer)

    fmt.Println(time.Now().Format(time.Stamp) + " READ from proxy to client: " + strconv.Itoa(length))
    fmt.Println(string(buffer))

    if length > 0 {
        writeLength, err := browser_to_client.Write(buffer[:length])
        fmt.Println(time.Now().Format(time.Stamp) + " WRITE from client to browser: " + strconv.Itoa(writeLength))
        if err != nil {
            fmt.Println("ERR7 ", err)
            return
        }
    }
    if err != nil {
        return
    }

    go write(client_to_proxy, browser_to_client)

    for {
        length, err := reader.Read(buffer)
        fmt.Println(time.Now().Format(time.Stamp) + " READ from proxy to client: " + strconv.Itoa(length))
        //fmt.Println(string(buffer[:length]))
        if length > 0 {
            writeLength, err := browser_to_client.Write(buffer[:length])
            fmt.Println(time.Now().Format(time.Stamp) + " WRITE from client to browser: " + strconv.Itoa(writeLength))
            if err != nil {
                fmt.Println("ERR8 ", err)
                return
            }
        }
        if err != nil {
            return
        }
    }
}

编辑1:我使用客户端和服务器 go 应用程序,例如浏览器->客户端->代理->so.com 然后 so.com->prxoy->客户端->浏览器 我不想要加密数据!我的问题出在“客户端”应用程序上,我不知道应该读取多少字节才能解锁read()

【问题讨论】:

  • 您似乎对 HTTPS 的工作原理有误解。 HTTPS 不仅仅是加密的 HTTP 请求和响应。这是一个加密连接,通过它发送标准 HTTP 请求和响应。
  • @Flimzy 我知道 https 是什么,我不想解密连接,我只是想知道数据的结尾来解锁 read() 并将其发送到浏览器。我添加了我完整的 github 代码
  • 关键是,您无法在 TLS 级别知道这一点。
  • @forootan 代理只是一个传递。浏览器告诉代理要连接到哪个服务器,然后代理传递浏览器发送的任何数据,反之亦然,服务器发送回的任何数据。如果数据使用 TLS 加密,则代理无法知道数据中的内容,因为只有浏览器和服务器才能解密它。代理所能做的就是来回传递原始字节,直到 TCP 连接关闭。不多也不少。

标签: go sockets https tcp proxy


【解决方案1】:

浏览器如何知道读取数据结束?

通过执行标准。

对于 HTTP/1.1,请参阅 RFC 7230 section 3.3 Message Body Length 了解详细信息,如何确定正文的长度。提示:基于 HTTP 标头的信息,例如 Content-length 和 Transfer-Encoding。

作为代理,在流式传输或加载简单的 html 页面时如何理解数据的结尾?

代理对纯 HTTP 消息的行为相同。

HTTPS 流量通过使用隧道的代理在客户端和服务器之间进行端到端加密传递。此隧道是通过 CONNECT 请求创建的,该请求仅在 TCP 连接关闭时结束。代理无法洞察连接,因此也无法确定加密流量中各种请求和响应的 HTTP 消息头和正文在哪里。

【讨论】:

  • 但是在https中,所有数据都被加密了,甚至是标头
  • @forootan:带有代理的 https 是使用提到的 CONNECT 请求完成的。
  • @forootan:我已经明确表示代理不了解 HTTPS,因此也不了解请求和响应、标头和正文。
  • 好的,我明白你的意思谢谢。浏览器读取标题。像视频这样的流数据呢?但是仍然有问题并且不知道代理读取的数据大小。你有什么建议吗?
  • @forootan:“像视频一样流数据”- 谷歌建议你的意思是“像视频这样的流数据” - 这些没有什么特别之处,它们也遵循我从标准中引用的内容。“但仍然有问题,不知道代理读取的数据大小。”- 我不知道你有什么具体问题,所以除了阅读这个答案和标准的部分之外,我无法提出任何建议。我都在里面
【解决方案2】:

感谢 Steffen Ullrich,浏览器和服务器,首先发送带有 的标头。所以他们可以逐行阅读标题。并且有一些东西可以告诉其余数据(正文)的大小,并且浏览器读取灵魂。这些标头使用服务器公钥加密,并且。所以他们知道应该读取多少数据。 但是作为代理,我们应该将彼此(套接字)通过管道连接在一起,并在 Golang 中使用io.copy(src, dst) 完成。所以不需要知道之间传输的数据大小和其他 tcp 问题。也使它工作得更快,因为它发生在较低级别的网络中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-03
    • 1970-01-01
    • 1970-01-01
    • 2012-03-22
    • 2014-09-14
    • 1970-01-01
    • 2012-12-13
    • 2021-01-24
    相关资源
    最近更新 更多