到本地主机的简单隧道

时间:2021-07-22 13:24:50

标签: go proxy tunnel

Target <----- Internal Client -------> Proxy
Target <-----------------------------> Proxy <----> Client

目标主机:

func main() {
    f, _ := os.Open("1.mp4")

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        http.ServeContent(w, r, "1.mp4", time.Now(), f)
    })

    http.ListenAndServe("127.0.0.1:3000", nil)
}

代理服务器:

type Master struct {
    conn net.Conn
}

func (m *Master) ServeHTTP(w http.ResponseWriter, r *http.Request) {

    if err := r.Write(m.conn); err != nil {
        log.Fatal("req.Write ", err)
    }

    resp, err := http.ReadResponse(bufio.NewReader(m.conn), r)
    if err != nil {
        fmt.Printf("\nhttp.ReadResponse: ", err)
    }

    defer func() {
        if resp.Body != nil {
            Log("Close body")
            if err := resp.Body.Close(); err != nil && err != io.ErrUnexpectedEOF {
                fmt.Printf("\nresp.Body Close error: %s", err)
            }
        }
    }()

    copyHeader(w.Header(), resp.Header)
    w.WriteHeader(resp.StatusCode)

    if _, err := io.Copy(w, resp.Body); err != nil {
        if isEPIPE(err) {
            fmt.Println("\nClient closed the connection, couldn't copy response")

        } else {
            fmt.Printf("copy err: %s\n", err)
        }
    }
}

func main() {

    var wg sync.WaitGroup
    m := &Master{}
    wg.Add(1)

    go func() {
        log.Fatal(http.ListenAndServe("localhost:8000", m))
        wg.Done()
    }()

    go func() {
        Log("start tcp server...")
        ln, _ := net.Listen("tcp", ":9000")

        for {
            conn, _ := ln.Accept()
            m.conn = conn
        }
    }()

    wg.Wait()

}

用于代理的内部客户端(func 目标只是执行 io.Copy 然后关闭)

var wg sync.WaitGroup
wg.Add(2)
serverConn, _ := net.Dial("tcp", "127.0.0.1:9000")
targetConn, _ := net.Dial("tcp", "127.0.0.1:3000")

go func() {
    transfer("server -> target", targetConn, serverConn)
    wg.Done()
}()

go func() {
    transfer("target -> server", serverConn, targetConn)
    wg.Done()
}()

wg.Wait() 

发生了什么

  1. 启动目标主机:3000
  2. 启动代理 (tcp:9000) http:8000
  3. 启动客户端
  4. 转到第 8000 页(chrome)并期望获得 mp4 流

相反,服务器因错误而崩溃:

<块引用>

客户端关闭连接,无法复制响应关闭正文

http.ReadResponse: %!(EXTRA *errors.errorString=格式错误的 HTTP 响应 "\xc9 霁ۍ^\x8aX\x17G\xee\x946\x ...

<块引用>

http: panic services 127.0.0.1:50106: runtime error: invalid memory > address or nil pointer dereference

从前两行来看,原来chrome已经关闭了连接

但我就是不明白为什么和为什么 发生无效的 HTTP 响应错误 ????

任何帮助

完整的堆栈跟踪

代理服务器:

http.ReadResponse: %!(EXTRA *errors.errorString=malformed HTTP response "\xc9ޜۍ^\x8aX\x1... 2021/07/22 16:04:53 http: panic serving 127.0.0.1:50106: runtime error: invalid memory address or nil pointer dereference
goroutine 35 [running]:
net/http.(*conn).serve.func1(0xc0001300a0)
        /usr/local/go/src/net/http/server.go:1824 +0x153
panic(0x12591a0, 0x143ba40)
        /usr/local/go/src/runtime/panic.go:971 +0x499
main.(*Master).ServeHTTP.func1(0x0)
        /Users/konstantin/goprojects/go-lab/server/server.go:44 +0x37
panic(0x12591a0, 0x143ba40)
        /usr/local/go/src/runtime/panic.go:965 +0x1b9
main.(*Master).ServeHTTP(0xc000012cf0, 0x12f2af0, 0xc0002002a0, 0xc0001c2100)
        /Users/konstantin/goprojects/go-lab/server/server.go:52 +0x27b
net/http.serverHandler.ServeHTTP(0xc000200000, 0x12f2af0, 0xc0002002a0, 0xc0001c2100)
        /usr/local/go/src/net/http/server.go:2887 +0xa3
net/http.(*conn).serve(0xc0001300a0, 0x12f2f00, 0xc000128040)
        /usr/local/go/src/net/http/server.go:1952 +0x8cd
created by net/http.(*Server).Serve
        /usr/local/go/src/net/http/server.go:3013 +0x39b

0 个答案:

没有答案