Noooste / azuretls-client

An easy-to-use HTTP client 100% in Go to spoof TLS/JA3 and HTTP2 fingerprint
MIT License
172 stars 25 forks source link

Session can not recover from broken tcp connection of http website #104

Closed sagan closed 3 months ago

sagan commented 4 months ago

Describe the bug

Currently, each azuretls session use a permanent connection pool (session.Connections) to manage tcp / utls connections. Each host has it's own azuretls.Conn struct, which is created at the first time requesting the URL of that host. Afterwards, it never changes (unless the used explicitly call session.Connections.Remove(host), but I don't think it's the intended usage).

Inside the azuretls.Conn struct, the Conn net.Conn field is the actual tcp connection, which is also created at the first time requesting the URL:

    if conn.Conn == nil {
        if s.ProxyDialer != nil {
            if err = s.getProxyConn(req, conn, host); err != nil {
                return nil, err
            }
        } else {
            if conn.Conn, err = (&net.Dialer{Timeout: conn.TimeOut}).DialContext(s.ctx, "tcp", host); err != nil {
                return nil, err
            }
        }
    }

The Close method of azuretls.Conn will set the Conn net.Conn field to nil, allowing a new tcp connection to be created later. However, during the lifetime of a session, the Close method of azuretls.Conn is only called when a TLS dialing failed:

    case SchemeHttps, SchemeWss:
        // for secured http we need to make tls connection first
        if err = conn.makeTLS(host); err != nil {
            conn.Close()
            return

        }

For a tcp connection to a http (not https) site, the Close method of azuretls.Conn will never be executed. If an error happened in the underlying tcp connection, all further requests to the same site will fail.