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

我正在尝试使用 Golang 创建一个 HTTP/HTTPS 代理,就像这个链接一样。这是我的所有代码:首先从浏览器获取命令。如果它是 CONNECT 意味着 HTTPS 并制作简单的 TCP 套接字并让浏览器继续它。然后将每个连接通过管道连接在一起。


package main


import (

    "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

            }

        }

    }

}

回首忆惘然
浏览 289回答 2
2回答

蛊毒传说

这是后来者的最终解决方案。适用于 http/https:package mainimport (    "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            }        }    }}

江户川乱折腾

与所有 HTTP 请求一样,CONNECT 请求以多行请求标头开头,该标头以仅包含 \r\n 的行结尾。但你只读了它的第一行:message, e := bufio.NewReader(client_to_proxy).ReadString('\n')请求的其余部分被发送到服务器,这可能会返回一些错误,因为这不是 TLS 握手的预期开始。TLS 握手的开始仅出现在请求标头之后。服务器返回的错误然后被转发到客户端并被解释为 TLS 消息——这被视为损坏的消息,因此是“坏 mac”。   readAll(client_to_proxy, proxy_to_server)无需将所有剩余数据(即除了请求的第一行之外的所有内容)转发到服务器,您需要首先读取完整的请求标头,然后才在客户端和服务器之间转发所有内容。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go