为了账号安全,请及时绑定邮箱和手机立即绑定

构建 https 代理失败,出现错误 SSL_ERROR_BAD_MAC_READ

构建 https 代理失败,出现错误 SSL_ERROR_BAD_MAC_READ

Go
回首忆惘然 2023-03-07 13:40:49
我正在尝试使用 Golang 创建一个 HTTP/HTTPS 代理,就像这个链接一样。这是我的所有代码:首先从浏览器获取命令。如果它是 CONNECT 意味着 HTTPS 并制作简单的 TCP 套接字并让浏览器继续它。然后将每个连接通过管道连接在一起。package mainimport (    "bufio"    "fmt"    "net"    "strings")func main() {    fmt.Println("Start server...")    ln, _ := net.Listen("tcp", ":8000")    conn, _ := ln.Accept()    handleSocket(conn)}func handleSocket(client_to_proxy net.Conn) {    message, e := bufio.NewReader(client_to_proxy).ReadString('\n')    message = strings.ReplaceAll(message, "\r\n", "")    if e != nil {        fmt.Println("ERROR1 ", e)        return    }    splited := strings.Split(message, " ")    host := strings.Split(splited[1], ":")    if splited[0] == "CONNECT" {        proxy_to_server, e := net.Dial("tcp", splited[1])        if e != nil {            fmt.Println("ERROR2 ", e)            return        }        lenn, e := client_to_proxy.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))        if e != nil {            fmt.Println("ERROR8 ", e)            return        }        fmt.Println(lenn)        readAll(client_to_proxy, proxy_to_server)    } else if splited[0] == "GET" {        remote_conn, e := net.Dial("tcp", strings.Replace(splited[1][:len(splited[1])-1], "http://", "", 2)+":80")        if e != nil {            fmt.Println("ERROR7 ", e)            return        }        _, e = remote_conn.Write([]byte("GET / " + splited[2] + "\r\n" + "Host: " + host[0] + "\r\n\r\n"))        if e != nil {            fmt.Println("ERROR6 ", e)            return        }        writeAll(client_to_proxy, remote_conn)    }}func writeAll(client_to_proxy net.Conn, proxy_to_server net.Conn) {    buffer := make([]byte, 32*1024)    for {        readLeng, err := proxy_to_server.Read(buffer)        if err != nil {            fmt.Println("ERROR9 ", err)            return        }        if readLeng > 0 {            _, err := client_to_proxy.Write(buffer)            if err != nil {                fmt.Println("ERR4 ", err)                return            }        }    }}
查看完整描述

2 回答

?
蛊毒传说

TA贡献1895条经验 获得超3个赞

这是后来者的最终解决方案。适用于 http/https:


package main


import (

    "fmt"

    "net"

    "strings"

)


func main() {

    fmt.Println("Start server...")


    ln, _ := net.Listen("tcp", ":8000")


    for {

        conn, _ := ln.Accept()

        handleSocket(conn)

    }

}


func handleSocket(client_to_proxy net.Conn) {

    buffer := make([]byte, 32*1024)

    _, e := client_to_proxy.Read(buffer)

    if e != nil {

        fmt.Println("ERROR1 ", e)

        return

    }

    message := string(buffer)

    a := strings.Count(message, "\r\n")

    fmt.Println(message)

    fmt.Println(a)

    if e != nil {

        fmt.Println("ERROR1 ", e)

        return

    }


    splited := strings.Split(message, " ")

    //host := strings.Split(splited[1], ":")

    if splited[0] == "CONNECT" {

        //message = strings.Replace(message, "CONNECT", "GET", 1)

        proxy_to_server, e := net.Dial("tcp", splited[1])

        if e != nil {

            fmt.Println("ERROR2 ", e)

            return

        }

        //_, e = proxy_to_server.Write([]byte(message))

        //if e != nil {

        //  fmt.Println("ERROR2 ", e)

        //  return

        //}

        lenn, e := client_to_proxy.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))

        if e != nil {

            fmt.Println("ERROR8 ", e)

            return

        }

        fmt.Println(lenn)


        read443(client_to_proxy, proxy_to_server)

    } else if splited[0] == "GET" {

        host1 := strings.Replace(splited[1], "http://", "", 1)

        host2 := host1[:len(host1)-1]

        var final_host string

        if strings.LastIndexAny(host2, "/") > 0 {

            final_host = host2[:strings.LastIndexAny(host2, "/")]

        } else {

            final_host = host2

        }

        proxy_to_server, e := net.Dial("tcp", final_host+":80")

        if e != nil {

            fmt.Println("ERROR7 ", e)

            return

        }

        _, e = proxy_to_server.Write([]byte(message))

        if e != nil {

            fmt.Println("ERROR6 ", e)

            return

        }


        write80(client_to_proxy, proxy_to_server)

    }

}


func write80(client_to_proxy net.Conn, proxy_to_server net.Conn) {

    buffer := make([]byte, 64*1024)


    readLeng, err := proxy_to_server.Read(buffer)

    if err != nil {

        fmt.Println("ERROR9 ", err)

        return

    }

    fmt.Println("WRIIIIIIIIIIIIIIIIIIIIIIT from server:")

    fmt.Println(string(buffer[:readLeng]))

    if readLeng > 0 {

        _, err := client_to_proxy.Write(buffer[:readLeng])

        if err != nil {

            fmt.Println("ERR4 ", err)

            return

        }

    }


    go read80(client_to_proxy, proxy_to_server)

    for {

        readLeng, err := proxy_to_server.Read(buffer)

        if err != nil {

            fmt.Println("ERROR10 ", err)

            return

        }

        fmt.Println("WRIIIIIIIIIIIIIIIIIIIIIIT from server:")

        fmt.Println(string(buffer[:readLeng]))

        if readLeng > 0 {

            _, err := client_to_proxy.Write(buffer[:readLeng])

            if err != nil {

                fmt.Println("ERR4 ", err)

                return

            }

        }

    }

}


func read80(client_to_proxy net.Conn, proxy_to_server net.Conn) {

    buffer := make([]byte, 32*1024)


    for {

        readLeng, err := client_to_proxy.Read(buffer)

        if err != nil {

            return

        }

        fmt.Println("REEEEEEEEEEEEEEEEEEEEEEED from client:")

        fmt.Println(string(buffer[:readLeng]))

        if readLeng > 0 {

            _, err := proxy_to_server.Write(buffer[:readLeng])

            if err != nil {

                fmt.Println("ERR5 ", err)

                return

            }

        }

    }

}


func write443(client_to_proxy net.Conn, proxy_to_server net.Conn) {

    buffer := make([]byte, 32*1024)

    for {

        readLeng, err := proxy_to_server.Read(buffer)

        if err != nil {

            fmt.Println("ERROR10 ", err)

            return

        }

        fmt.Println("WRIIIIIIIIIIIIIIIIIIIIIIT from server:")

        fmt.Println(string(buffer[:readLeng]))

        if readLeng > 0 {

            _, err := client_to_proxy.Write(buffer[:readLeng])

            if err != nil {

                fmt.Println("ERR4 ", err)

                return

            }

        }

    }

}


func read443(client_to_proxy net.Conn, proxy_to_server net.Conn) {

    buffer := make([]byte, 32*1024)


    readLeng, err := client_to_proxy.Read(buffer)

    if err != nil {

        return

    }

    fmt.Println("REEEEEEEEEEEEEEEEEEEEEEED from client:")

    fmt.Println(string(buffer[:readLeng]))

    if readLeng > 0 {

        _, err := proxy_to_server.Write(buffer[:readLeng])

        if err != nil {

            fmt.Println("ERR5 ", err)

            return

        }

    }


    go write443(client_to_proxy, proxy_to_server)


    for {

        readLeng, err := client_to_proxy.Read(buffer)

        if err != nil {

            return

        }

        fmt.Println("REEEEEEEEEEEEEEEEEEEEEEED from client:")

        fmt.Println(string(buffer[:readLeng]))

        if readLeng > 0 {

            _, err := proxy_to_server.Write(buffer[:readLeng])

            if err != nil {

                fmt.Println("ERR5 ", err)

                return

            }

        }

    }

}



查看完整回答
反对 回复 2023-03-07
?
江户川乱折腾

TA贡献1851条经验 获得超5个赞

与所有 HTTP 请求一样,CONNECT 请求以多行请求标头开头,该标头以仅包含 \r\n 的行结尾。但你只读了它的第一行:

message, e := bufio.NewReader(client_to_proxy).ReadString('\n')

请求的其余部分被发送到服务器,这可能会返回一些错误,因为这不是 TLS 握手的预期开始。TLS 握手的开始仅出现在请求标头之后。服务器返回的错误然后被转发到客户端并被解释为 TLS 消息——这被视为损坏的消息,因此是“坏 mac”。

   readAll(client_to_proxy, proxy_to_server)

无需将所有剩余数据(即除了请求的第一行之外的所有内容)转发到服务器,您需要首先读取完整的请求标头,然后才在客户端和服务器之间转发所有内容。


查看完整回答
反对 回复 2023-03-07
  • 2 回答
  • 0 关注
  • 288 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信