Noooste / azuretls-client

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

Session is not concurrency safe when used to access http URLs #103

Closed sagan closed 2 months ago

sagan commented 2 months ago

Describe the bug

There is race condition if azuretls session is used by multiple goroutines to access http (not https) URLs, as long as multiple URLs have the same host.

To Reproduce

Just use the test/connection_test.go file, modify func concurrency(session *azuretls.Session, wg *sync.WaitGroup, ok *int64) bool function, change the test url from https://example.com/ to http://example.com/, then run the TestHighConcurrency test.

Alternatively, use the following test snippet:

package main

import (
    "log"
    "time"

    "github.com/Noooste/azuretls-client"
)

const TEST_URL = "http://example.com/"
const NUM_GOROUTINE = 3
const INTERVAL = time.Millisecond * 1000

func main() {
    session := azuretls.NewSession()
    for i := 0; i < NUM_GOROUTINE; i++ {
        go test(i, session, TEST_URL, INTERVAL)
    }
    select {}
}

func test(index int, session *azuretls.Session, url string, interval time.Duration) {
    i := 0
    for {
        i++
        _, err := session.Get(url)
        if err != nil {
            log.Fatalf("fail: %v", err)
        }
        log.Printf("goroutine %d: %d requests sent", index, i)
        if interval > 0 {
            time.Sleep(interval)
        }
    }
}

Output:


2024/06/25 14:26:56 goroutine 1: 1 requests sent
2024/06/25 14:26:56 goroutine 0: 1 requests sent
2024/06/25 14:26:56 goroutine 2: 1 requests sent
2024/06/25 14:26:57 fail: read tcp 127.0.0.1:58686->93.184.215.14:80: use of closed network connection
exit status 1
`

The race condition is easy to produce, even with only 2 or 3 goroutines and interval of 1s.
Noooste commented 2 months ago

Thanks for reporting this, I will patch this bug asap!