Skip to content

Instantly share code, notes, and snippets.

@AmirSoleimani
Last active July 3, 2021 23:22
Show Gist options
  • Save AmirSoleimani/bfc29e3936af5a7221680fbb8f11682c to your computer and use it in GitHub Desktop.
Save AmirSoleimani/bfc29e3936af5a7221680fbb8f11682c to your computer and use it in GitHub Desktop.
NordVPN Proxy and HTTP Request
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"time"
"golang.org/x/net/proxy"
)
const (
NordServerListEndpoint = "https://nordvpn.com/api/server"
NordSocks5Port = "1080"
)
var (
NordUser = os.Getenv("NORD_EMAIL")
NordPassword = os.Getenv("NORD_PASSWORD")
NordProxyServers = []NordServer{}
)
type NordServer struct {
IPAddress string `json:"ip_address"`
Domain string `json:"domain"`
Country string `json:"country"`
Features struct {
Socks bool `json:"socks"`
} `json:"features"`
}
const TestURL = "https://ifconfig.me"
var (
ProxyRound int
httpTransportCache = map[string]*http.Transport{}
)
func main() {
var err error
NordProxyServers, err = GetServerList()
if err != nil {
log.Fatal(err)
}
for i := 0; i < 50; i++ {
proxyServer := NordProxyServers[ProxyRound%len(NordProxyServers)]
ProxyRound++
// setup a http client
cachedHttpTransport, exist := httpTransportCache[proxyServer.Domain]
if !exist {
// create a socks5 dialer
dialer, err := proxy.SOCKS5("tcp", proxyServer.Domain+":"+NordSocks5Port, &proxy.Auth{
User: NordUser,
Password: NordPassword,
}, proxy.Direct)
if err != nil {
fmt.Fprintln(os.Stderr, "can't connect to the proxy:", err)
continue
}
cachedHttpTransport = &http.Transport{}
if contextDialer, ok := dialer.(proxy.ContextDialer); ok {
cachedHttpTransport.DialContext = contextDialer.DialContext
}
httpTransportCache[proxyServer.Domain] = cachedHttpTransport
}
IP, err := GetMyIP(cachedHttpTransport.Clone())
if err != nil {
fmt.Fprintln(os.Stderr, "can't get the IP address:", err)
continue
}
fmt.Printf("IP:%s ProxyDomain:%s ProxyCountry:%s\n", string(IP), proxyServer.Domain, proxyServer.Domain)
}
}
func GetMyIP(httpTransport *http.Transport) ([]byte, error) {
defer httpTransport.CloseIdleConnections()
httpClient := &http.Client{
Transport: httpTransport,
Timeout: 15 * time.Second,
}
// Do request
resp, err := httpClient.Get(TestURL)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return ioutil.ReadAll(resp.Body)
}
func GetServerList() ([]NordServer, error) {
resp, err := http.Get(NordServerListEndpoint)
if err != nil {
return nil, err
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("Response status code is %d", resp.StatusCode)
}
respByte, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
result := []NordServer{}
err = json.Unmarshal(respByte, &result)
if err != nil {
return nil, err
}
output := []NordServer{}
for _, s := range result {
if s.Features.Socks {
output = append(output, s)
}
}
return output, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment