2021-09-13 08:30:49 +00:00
|
|
|
package pxndscvm
|
|
|
|
|
2021-09-13 16:01:19 +00:00
|
|
|
import (
|
2021-09-13 16:32:07 +00:00
|
|
|
"context"
|
|
|
|
"net"
|
2021-09-13 16:01:19 +00:00
|
|
|
"time"
|
2021-09-13 16:32:07 +00:00
|
|
|
|
|
|
|
"h12.io/socks"
|
2021-09-13 16:01:19 +00:00
|
|
|
)
|
2021-09-13 09:37:59 +00:00
|
|
|
|
2021-09-13 08:30:49 +00:00
|
|
|
// Socks5Str gets a SOCKS5 proxy that we have fully verified (dialed and then retrieved our IP address from a what-is-my-ip endpoint.
|
2021-09-13 19:08:41 +00:00
|
|
|
// Will block if one is not available!
|
2021-09-13 08:30:49 +00:00
|
|
|
func (s *Swamp) Socks5Str() string {
|
2021-09-13 09:37:59 +00:00
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case sock := <-s.Socks5:
|
|
|
|
if !s.stillGood(sock) {
|
|
|
|
continue
|
|
|
|
}
|
2021-09-13 11:26:18 +00:00
|
|
|
s.Stats.dispense()
|
2021-09-13 09:37:59 +00:00
|
|
|
return sock.Endpoint
|
|
|
|
}
|
2021-09-13 08:30:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Socks4Str gets a SOCKS4 proxy that we have fully verified.
|
2021-09-13 19:08:41 +00:00
|
|
|
// Will block if one is not available!
|
2021-09-13 08:30:49 +00:00
|
|
|
func (s *Swamp) Socks4Str() string {
|
2021-09-13 09:37:59 +00:00
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case sock := <-s.Socks4:
|
|
|
|
if !s.stillGood(sock) {
|
|
|
|
continue
|
|
|
|
}
|
2021-09-13 11:26:18 +00:00
|
|
|
s.Stats.dispense()
|
2021-09-13 09:37:59 +00:00
|
|
|
return sock.Endpoint
|
|
|
|
}
|
2021-09-13 08:30:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Socks4aStr gets a SOCKS4 proxy that we have fully verified.
|
2021-09-13 19:08:41 +00:00
|
|
|
// Will block if one is not available!
|
2021-09-13 08:30:49 +00:00
|
|
|
func (s *Swamp) Socks4aStr() string {
|
2021-09-13 09:37:59 +00:00
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case sock := <-s.Socks4a:
|
|
|
|
if !s.stillGood(sock) {
|
|
|
|
continue
|
|
|
|
}
|
2021-09-13 16:32:07 +00:00
|
|
|
|
2021-09-13 11:26:18 +00:00
|
|
|
s.Stats.dispense()
|
2021-09-13 09:37:59 +00:00
|
|
|
return sock.Endpoint
|
|
|
|
}
|
2021-09-13 08:30:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-13 13:58:57 +00:00
|
|
|
// GetAnySOCKS retrieves any version SOCKS proxy as a Proxy type
|
2021-09-13 19:08:41 +00:00
|
|
|
// Will block if one is not available!
|
2021-09-13 13:58:57 +00:00
|
|
|
func (s *Swamp) GetAnySOCKS() Proxy {
|
2021-09-13 09:37:59 +00:00
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case sock := <-s.Socks4:
|
|
|
|
if !s.stillGood(sock) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
return sock
|
|
|
|
case sock := <-s.Socks4a:
|
|
|
|
if !s.stillGood(sock) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
return sock
|
|
|
|
case sock := <-s.Socks5:
|
|
|
|
if !s.stillGood(sock) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
return sock
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-13 11:26:18 +00:00
|
|
|
func (s *Swamp) stillGood(candidate Proxy) bool {
|
2021-09-13 16:01:19 +00:00
|
|
|
if time.Since(candidate.Verified) > s.swampopt.Stale {
|
|
|
|
s.dbgPrint("proxy stale: " + candidate.Endpoint)
|
2021-09-13 09:37:59 +00:00
|
|
|
return false
|
2021-09-13 08:30:49 +00:00
|
|
|
}
|
2021-09-13 16:01:19 +00:00
|
|
|
return true
|
2021-09-13 08:30:49 +00:00
|
|
|
}
|
2021-09-13 09:37:59 +00:00
|
|
|
|
|
|
|
// RandomUserAgent retrieves a random user agent from our list in string form
|
|
|
|
func (s *Swamp) RandomUserAgent() string {
|
|
|
|
s.mu.RLock()
|
|
|
|
defer s.mu.RUnlock()
|
2021-09-13 15:12:02 +00:00
|
|
|
return randStrChoice(s.swampopt.UserAgents)
|
2021-09-13 09:37:59 +00:00
|
|
|
}
|
2021-09-13 11:26:18 +00:00
|
|
|
|
2021-09-13 16:32:07 +00:00
|
|
|
// GetMysteryDialer will return a dialer that will use a different proxy for every request.
|
|
|
|
func (s *Swamp) GetMysteryDialer(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
|
|
var sock Proxy
|
|
|
|
sock = Proxy{Endpoint: ""}
|
|
|
|
// pull down proxies from channel until we get a proxy good enough for our spoiled asses
|
|
|
|
for {
|
|
|
|
if err := ctx.Err(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-09-13 19:08:41 +00:00
|
|
|
|
2021-09-13 16:32:07 +00:00
|
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
candidate := s.GetAnySOCKS()
|
|
|
|
if !s.stillGood(candidate) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
sock = candidate
|
|
|
|
|
|
|
|
if sock.Endpoint != "" {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2021-09-13 19:08:41 +00:00
|
|
|
|
2021-09-13 16:32:07 +00:00
|
|
|
if err := ctx.Err(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2021-09-13 19:08:41 +00:00
|
|
|
var dialSocks = socks.Dial("socks" + sock.Proto + "://" + sock.Endpoint + "?timeout=8s")
|
2021-09-13 16:32:07 +00:00
|
|
|
|
|
|
|
return dialSocks(network, addr)
|
|
|
|
}
|
|
|
|
|
2021-09-13 15:36:30 +00:00
|
|
|
// GetRandomEndpoint returns a random whatismyip style endpoint from our Swamp's options
|
|
|
|
func (s *Swamp) GetRandomEndpoint() string {
|
2021-09-13 16:32:07 +00:00
|
|
|
s.mu.RLock()
|
|
|
|
defer s.mu.RUnlock()
|
2021-09-13 15:36:30 +00:00
|
|
|
return randStrChoice(s.swampopt.CheckEndpoints)
|
|
|
|
}
|
|
|
|
|
2021-09-13 16:32:07 +00:00
|
|
|
// GetStaleTime returns the duration of time after which a proxy will be considered "stale".
|
|
|
|
func (s *Swamp) GetStaleTime() time.Duration {
|
|
|
|
s.mu.RLock()
|
|
|
|
defer s.mu.RUnlock()
|
|
|
|
return s.swampopt.Stale
|
|
|
|
}
|
|
|
|
|
2021-09-13 17:40:23 +00:00
|
|
|
// GetValidationTimeout returns the current value of ValidationTimeout (in seconds).
|
|
|
|
func (s *Swamp) GetValidationTimeout() int {
|
|
|
|
s.mu.RLock()
|
|
|
|
defer s.mu.RUnlock()
|
|
|
|
return s.swampopt.ValidationTimeout
|
|
|
|
}
|
|
|
|
|
2021-09-13 16:32:07 +00:00
|
|
|
// DebugEnabled returns the current state of our Debug switch
|
2021-09-13 11:26:18 +00:00
|
|
|
func (s *Swamp) DebugEnabled() bool {
|
2021-09-13 16:32:07 +00:00
|
|
|
s.mu.RLock()
|
|
|
|
defer s.mu.RUnlock()
|
2021-09-13 11:26:18 +00:00
|
|
|
return s.swampopt.Debug
|
|
|
|
}
|
2021-09-13 16:32:07 +00:00
|
|
|
|
|
|
|
// GetMaxWorkers returns maximum amount of workers that validate proxies concurrently. Note this is read-only during runtime.
|
|
|
|
func (s *Swamp) GetMaxWorkers() int {
|
|
|
|
s.mu.RLock()
|
|
|
|
defer s.mu.RUnlock()
|
|
|
|
return s.swampopt.MaxWorkers
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Implement ways to access worker pool (pond) statistics
|