2021-09-14 07:28:10 +00:00
|
|
|
package pxndscvm
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"crypto/tls"
|
|
|
|
"errors"
|
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
|
|
|
"net"
|
|
|
|
"net/http"
|
2021-09-24 19:07:56 +00:00
|
|
|
// "net/url"
|
2021-09-20 05:57:42 +00:00
|
|
|
"sync/atomic"
|
2021-09-14 07:28:10 +00:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"golang.org/x/net/proxy"
|
|
|
|
"h12.io/socks"
|
|
|
|
)
|
|
|
|
|
2021-09-24 00:15:15 +00:00
|
|
|
func (s *Swamp) prepHTTP() (*http.Client, *http.Transport, *http.Request, error) {
|
2021-09-14 07:28:10 +00:00
|
|
|
req, err := http.NewRequest("GET", s.GetRandomEndpoint(), bytes.NewBuffer([]byte("")))
|
|
|
|
if err != nil {
|
2021-09-24 00:15:15 +00:00
|
|
|
return nil, nil, nil, err
|
2021-09-14 07:28:10 +00:00
|
|
|
}
|
|
|
|
headers := make(map[string]string)
|
|
|
|
headers["User-Agent"] = s.RandomUserAgent()
|
|
|
|
headers["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
|
|
|
|
headers["Accept-Language"] = "en-US,en;q=0.5"
|
|
|
|
headers["'Accept-Encoding'"] = "gzip, deflate, br"
|
|
|
|
headers["Connection"] = "keep-alive"
|
|
|
|
for header, value := range headers {
|
|
|
|
req.Header.Set(header, value)
|
|
|
|
}
|
2021-09-23 16:06:49 +00:00
|
|
|
var client *http.Client
|
|
|
|
var transporter = &http.Transport{
|
|
|
|
DisableKeepAlives: true,
|
|
|
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
2021-09-24 19:07:56 +00:00
|
|
|
TLSHandshakeTimeout: s.swampopt.validationTimeout.Load().(time.Duration),
|
2021-09-23 16:06:49 +00:00
|
|
|
}
|
2021-09-24 19:07:56 +00:00
|
|
|
|
2021-09-24 00:15:15 +00:00
|
|
|
return client, transporter, req, err
|
|
|
|
}
|
|
|
|
|
2021-09-24 19:07:56 +00:00
|
|
|
func (sock *Proxy) bad() {
|
|
|
|
sock.timesBad.Store(sock.timesBad.Load().(int) + 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (sock *Proxy) good() {
|
|
|
|
sock.timesValidated.Store(sock.timesValidated.Load().(int) + 1)
|
|
|
|
sock.lastValidated.Store(time.Now())
|
|
|
|
}
|
|
|
|
|
2021-09-24 00:15:15 +00:00
|
|
|
func (s *Swamp) checkHTTP(sock *Proxy) (string, error) {
|
|
|
|
var (
|
2021-09-24 19:07:56 +00:00
|
|
|
client *http.Client
|
2021-09-24 00:15:15 +00:00
|
|
|
transporter *http.Transport
|
2021-09-24 19:07:56 +00:00
|
|
|
req *http.Request
|
|
|
|
err error
|
2021-09-24 00:15:15 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
if client, transporter, req, err = s.prepHTTP(); err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2021-09-23 16:06:49 +00:00
|
|
|
|
2021-09-24 00:15:15 +00:00
|
|
|
var t int
|
2021-09-24 21:06:08 +00:00
|
|
|
switch sock.Proto.Load().(string) {
|
2021-09-24 00:15:15 +00:00
|
|
|
case "5":
|
|
|
|
t = socks.SOCKS5
|
|
|
|
case "4":
|
|
|
|
t = socks.SOCKS4
|
|
|
|
case "4a":
|
|
|
|
t = socks.SOCKS4A
|
|
|
|
}
|
2021-09-14 07:28:10 +00:00
|
|
|
|
2021-09-24 00:15:15 +00:00
|
|
|
var dialSocks = socks.DialSocksProxy(t, sock.Endpoint)
|
|
|
|
var transportDialer = dialSocks
|
2021-09-24 21:06:08 +00:00
|
|
|
if sock.Proto.Load().(string) == "none" {
|
2021-09-23 16:06:49 +00:00
|
|
|
transportDialer = proxy.Direct.Dial
|
|
|
|
}
|
|
|
|
|
2021-09-24 21:06:08 +00:00
|
|
|
// if sock.Proto.Load().(string) != "http" {
|
2021-09-24 00:15:15 +00:00
|
|
|
transporter.Dial = transportDialer
|
|
|
|
|
2021-09-24 19:07:56 +00:00
|
|
|
// } else {
|
2021-09-24 00:15:15 +00:00
|
|
|
// if purl, err := url.Parse("http://" + sock.Endpoint); err == nil {
|
|
|
|
// transporter.Proxy = http.ProxyURL(purl)
|
|
|
|
// } else {
|
|
|
|
// return "", err
|
|
|
|
// }
|
2021-09-24 19:07:56 +00:00
|
|
|
// }
|
2021-09-14 07:28:10 +00:00
|
|
|
|
|
|
|
client = &http.Client{
|
2021-09-23 16:06:49 +00:00
|
|
|
Transport: transporter,
|
2021-09-24 19:07:56 +00:00
|
|
|
Timeout: s.swampopt.validationTimeout.Load().(time.Duration),
|
2021-09-14 07:28:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
resp, err := client.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
defer func(Body io.ReadCloser) {
|
|
|
|
err := Body.Close()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}(resp.Body)
|
|
|
|
|
|
|
|
rbody, err := ioutil.ReadAll(resp.Body)
|
|
|
|
return string(rbody), err
|
|
|
|
}
|
|
|
|
|
2021-09-20 05:57:42 +00:00
|
|
|
func (s *Swamp) singleProxyCheck(sock *Proxy) error {
|
2021-09-23 07:38:00 +00:00
|
|
|
s.Stats.Checked++
|
2021-09-24 19:07:56 +00:00
|
|
|
if _, err := net.DialTimeout("tcp", sock.Endpoint, s.swampopt.validationTimeout.Load().(time.Duration)); err != nil {
|
2021-09-18 13:47:19 +00:00
|
|
|
s.badProx.Check(sock)
|
2021-09-14 07:28:10 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
resp, err := s.checkHTTP(sock)
|
|
|
|
if err != nil {
|
2021-09-18 13:47:19 +00:00
|
|
|
s.badProx.Check(sock)
|
2021-09-14 07:28:10 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if newip := net.ParseIP(resp); newip == nil {
|
2021-09-18 13:47:19 +00:00
|
|
|
s.badProx.Check(sock)
|
2021-09-14 07:28:10 +00:00
|
|
|
return errors.New("bad response from http request: " + resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
sock.ProxiedIP = resp
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-09-20 08:49:06 +00:00
|
|
|
func (sock *Proxy) validate() {
|
2021-09-24 00:15:15 +00:00
|
|
|
var sversions = []string{"4", "5", "4a"}
|
2021-09-14 07:28:10 +00:00
|
|
|
|
2021-09-20 08:49:06 +00:00
|
|
|
s := sock.parent
|
|
|
|
if s.useProx.Check(sock) {
|
|
|
|
s.dbgPrint(ylw + "useProx ratelimited: " + sock.Endpoint + rst)
|
|
|
|
atomic.StoreUint32(&sock.lock, stateUnlocked)
|
|
|
|
return
|
|
|
|
}
|
2021-09-14 07:28:10 +00:00
|
|
|
|
2021-09-20 08:49:06 +00:00
|
|
|
// determined as bad, won't try again until it expires from that cache
|
|
|
|
if s.badProx.Peek(sock) {
|
|
|
|
s.dbgPrint(ylw + "badProx ratelimited: " + sock.Endpoint + rst)
|
|
|
|
atomic.StoreUint32(&sock.lock, stateUnlocked)
|
|
|
|
return
|
|
|
|
}
|
2021-09-14 07:28:10 +00:00
|
|
|
|
2021-09-20 08:49:06 +00:00
|
|
|
// try to use the proxy with all 3 SOCKS versions
|
|
|
|
var good = false
|
|
|
|
for _, sver := range sversions {
|
|
|
|
if s.Status == Paused {
|
|
|
|
return
|
2021-09-14 07:28:10 +00:00
|
|
|
}
|
2021-09-23 16:06:49 +00:00
|
|
|
|
2021-09-24 21:06:08 +00:00
|
|
|
sock.Proto.Store(sver)
|
2021-09-20 08:49:06 +00:00
|
|
|
if err := s.singleProxyCheck(sock); err == nil {
|
2021-09-24 19:07:56 +00:00
|
|
|
// if sock.Proto != "http" {
|
2021-09-24 00:15:15 +00:00
|
|
|
s.dbgPrint(grn + "verified " + sock.Endpoint + " as SOCKS" + sver + rst)
|
2021-09-24 19:07:56 +00:00
|
|
|
// } else {
|
|
|
|
// s.dbgPrint(ylw + "verified " + sock.Endpoint + " as http (not usable yet)" + rst)
|
|
|
|
// }
|
2021-09-20 08:49:06 +00:00
|
|
|
good = true
|
|
|
|
break
|
2021-09-14 07:28:10 +00:00
|
|
|
}
|
2021-09-20 08:49:06 +00:00
|
|
|
}
|
2021-09-14 07:28:10 +00:00
|
|
|
|
2021-09-20 08:49:06 +00:00
|
|
|
if !good {
|
2021-09-23 16:06:49 +00:00
|
|
|
s.dbgPrint(red + "failed to verify: " + sock.Endpoint)
|
2021-09-24 19:07:56 +00:00
|
|
|
sock.bad()
|
2021-09-20 08:49:06 +00:00
|
|
|
s.badProx.Check(sock)
|
2021-09-20 05:57:42 +00:00
|
|
|
atomic.StoreUint32(&sock.lock, stateUnlocked)
|
2021-09-20 08:49:06 +00:00
|
|
|
return
|
|
|
|
}
|
2021-09-14 07:28:10 +00:00
|
|
|
|
2021-09-24 19:07:56 +00:00
|
|
|
sock.good()
|
2021-09-20 08:49:06 +00:00
|
|
|
atomic.StoreUint32(&sock.lock, stateUnlocked)
|
|
|
|
|
2021-09-24 21:06:08 +00:00
|
|
|
switch sock.Proto.Load().(string) {
|
2021-09-20 08:49:06 +00:00
|
|
|
case "4":
|
2021-09-24 00:15:15 +00:00
|
|
|
go func() {
|
|
|
|
s.Stats.v4()
|
|
|
|
s.ValidSocks4 <- sock
|
|
|
|
}()
|
|
|
|
return
|
2021-09-20 08:49:06 +00:00
|
|
|
case "4a":
|
2021-09-24 00:15:15 +00:00
|
|
|
go func() {
|
|
|
|
s.Stats.v4a()
|
|
|
|
s.ValidSocks4a <- sock
|
|
|
|
}()
|
|
|
|
return
|
2021-09-20 08:49:06 +00:00
|
|
|
case "5":
|
2021-09-24 00:15:15 +00:00
|
|
|
go func() {
|
|
|
|
s.Stats.v5()
|
|
|
|
s.ValidSocks5 <- sock
|
|
|
|
}()
|
|
|
|
return
|
|
|
|
default:
|
|
|
|
return
|
2021-09-14 07:28:10 +00:00
|
|
|
}
|
|
|
|
}
|