Projects STRLCPY prox5 Commits c3e3694a
🤬
  • ■ ■ ■ ■ ■ ■
    conductor.go
    skipped 2 lines
    3 3  import (
    4 4   "context"
    5 5   "errors"
    6  - "strings"
    7 6   "sync/atomic"
    8 7  )
    9 8   
    skipped 20 lines
    30 29   
    31 30  /*
    32 31  Pause will cease the creation of any new proxy validation operations.
    33  - * You will be able to start the proxy pool again with Swamp.Resume(), it will have the same Statistics, options, and ratelimits.
    34  - * During pause you are still able to dispense proxies.
    35  - * Options may be changed and proxy lists may be loaded when paused.
    36  - * Pausing an already paused ProxyEngine is a nonop.
     32 + - You will be able to start the proxy pool again with Swamp.Resume(), it will have the same Statistics, options, and ratelimits.
     33 + - During pause you are still able to dispense proxies.
     34 + - Options may be changed and proxy lists may be loaded when paused.
     35 + - Pausing an already paused ProxyEngine is a nonop.
    37 36  */
    38 37  func (pe *ProxyEngine) Pause() error {
    39 38   if !pe.IsRunning() {
    40 39   return errors.New("not running")
    41 40   }
    42 41   
    43  - buf := copABuffer.Get().(*strings.Builder)
    44  - buf.WriteString("pausing...")
    45  - pe.dbgPrint(buf)
     42 + pe.dbgPrint(simpleString("pausing proxy pool"))
    46 43   
    47 44   pe.quit()
    48 45   
    skipped 28 lines
  • ■ ■ ■ ■ ■
    daemons.go
    skipped 6 lines
    7 7   "sync"
    8 8   "sync/atomic"
    9 9   "time"
     10 + 
     11 + "git.tcp.direct/kayos/prox5/internal/pools"
    10 12  )
    11 13   
    12 14  func (pe *ProxyEngine) svcUp() {
    skipped 135 lines
    148 150   default:
    149 151   time.Sleep(25 * time.Millisecond)
    150 152   count := pe.recycling()
    151  - buf := copABuffer.Get().(*strings.Builder)
     153 + buf := pools.CopABuffer.Get().(*strings.Builder)
    152 154   buf.WriteString("recycled ")
    153 155   buf.WriteString(strconv.Itoa(count))
    154 156   buf.WriteString(" proxies from our map")
    skipped 10 lines
  • ■ ■ ■ ■ ■ ■
    debug.go
    skipped 3 lines
    4 4   "fmt"
    5 5   "strings"
    6 6   "sync"
     7 + "sync/atomic"
     8 + 
     9 + "git.tcp.direct/kayos/prox5/internal/pools"
     10 +)
     11 + 
     12 +var (
     13 + debugStatus *uint32
     14 + debugHardLock = &sync.RWMutex{}
    7 15  )
    8 16   
    9 17  func init() {
    10  - debugMutex = &sync.RWMutex{}
     18 + dd := debugDisabled
     19 + debugStatus = &dd
    11 20  }
    12 21   
    13  -var (
    14  - useDebugChannel = false
    15  - debugChan chan string
    16  - debugMutex *sync.RWMutex
     22 +const (
     23 + debugEnabled uint32 = iota
     24 + debugDisabled
    17 25  )
    18 26   
    19  -type DebugPrinter interface {
    20  - Print(str string)
    21  - Printf(format string, items ...any)
     27 +type SocksLogger struct {
     28 + parent *ProxyEngine
     29 +}
     30 + 
     31 +// Printf is used to handle socks server logging.
     32 +func (s SocksLogger) Printf(format string, a ...interface{}) {
     33 + buf := pools.CopABuffer.Get().(*strings.Builder)
     34 + buf.WriteString(fmt.Sprintf(format, a...))
     35 + s.parent.dbgPrint(buf)
    22 36  }
    23 37   
    24 38  type basicPrinter struct{}
    skipped 6 lines
    31 45   println(fmt.Sprintf("prox5: "+format, items))
    32 46  }
    33 47   
    34  -// DebugChannel will return a channel which will receive debug messages once debug is enabled.
    35  -// This will alter the flow of debug messages, they will no longer print to console, they will be pushed into this channel.
    36  -// Make sure you pull from the channel eventually to avoid build up of blocked goroutines.
    37  -func (pe *ProxyEngine) DebugChannel() chan string {
    38  - debugChan = make(chan string, 1000000)
    39  - useDebugChannel = true
    40  - return debugChan
    41  -}
    42  - 
    43 48  // DebugEnabled returns the current state of our debug switch.
    44 49  func (pe *ProxyEngine) DebugEnabled() bool {
    45  - return pe.swampopt.debug
    46  -}
    47  - 
    48  -// DisableDebugChannel redirects debug messages back to the console.
    49  -// DisableProxyChannel does not disable debug, use DisableDebug().
    50  -func (pe *ProxyEngine) DisableDebugChannel() {
    51  - debugMutex.Lock()
    52  - defer debugMutex.Unlock()
    53  - useDebugChannel = false
     50 + debugHardLock.RLock()
     51 + defer debugHardLock.RUnlock()
     52 + return atomic.CompareAndSwapUint32(debugStatus, debugEnabled, debugEnabled)
    54 53  }
    55 54   
    56 55  // EnableDebug enables printing of verbose messages during operation
    57 56  func (pe *ProxyEngine) EnableDebug() {
    58  - pe.swampopt.debug = true
     57 + atomic.StoreUint32(debugStatus, debugEnabled)
    59 58  }
    60 59   
    61 60  // DisableDebug enables printing of verbose messages during operation.
    62 61  // WARNING: if you are using a DebugChannel, you must read all of the messages in the channel's cache or this will block.
    63 62  func (pe *ProxyEngine) DisableDebug() {
    64  - pe.swampopt.debug = false
     63 + atomic.StoreUint32(debugStatus, debugDisabled)
    65 64  }
    66 65   
    67 66  func simpleString(s string) *strings.Builder {
    68  - buf := copABuffer.Get().(*strings.Builder)
     67 + buf := pools.CopABuffer.Get().(*strings.Builder)
    69 68   buf.WriteString(s)
    70 69   return buf
    71 70  }
    72 71   
    73 72  func (pe *ProxyEngine) dbgPrint(builder *strings.Builder) {
    74  - defer discardBuffer(builder)
    75  - if !pe.swampopt.debug {
     73 + defer pools.DiscardBuffer(builder)
     74 + if !pe.DebugEnabled() {
    76 75   return
    77 76   }
    78  - if !useDebugChannel {
    79  - pe.Debug.Print(builder.String())
     77 + pe.DebugLogger.Print(builder.String())
     78 + return
     79 +}
     80 + 
     81 +func (pe *ProxyEngine) msgUnableToReach(socksString, target string, err error) {
     82 + if !pe.DebugEnabled() {
    80 83   return
    81 84   }
    82  - select {
    83  - case debugChan <- builder.String():
    84  - return
    85  - default:
    86  - buf := copABuffer.Get().(*strings.Builder)
    87  - buf.WriteString("overflow: ")
    88  - buf.WriteString(builder.String())
    89  - pe.Debug.Print(buf.String())
    90  - discardBuffer(buf)
     85 + buf := pools.CopABuffer.Get().(*strings.Builder)
     86 + buf.WriteString("unable to reach ")
     87 + if pe.swampopt.redact {
     88 + buf.WriteString("[redacted]")
     89 + } else {
     90 + buf.WriteString(target)
    91 91   }
    92  -}
    93  - 
    94  -func (pe *ProxyEngine) msgUnableToReach(socksString string) {
    95  - buf := copABuffer.Get().(*strings.Builder)
    96  - buf.WriteString("unable to reach [redacted] with ")
     92 + buf.WriteString(" with ")
    97 93   buf.WriteString(socksString)
     94 + if !pe.swampopt.redact {
     95 + buf.WriteString(": ")
     96 + buf.WriteString(err.Error())
     97 + }
    98 98   buf.WriteString(", cycling...")
    99 99   pe.dbgPrint(buf)
    100 100  }
    101 101   
    102 102  func (pe *ProxyEngine) msgUsingProxy(socksString string) {
    103  - buf := copABuffer.Get().(*strings.Builder)
     103 + if !pe.DebugEnabled() {
     104 + return
     105 + }
     106 + buf := pools.CopABuffer.Get().(*strings.Builder)
    104 107   buf.WriteString("MysteryDialer using socks: ")
    105 108   buf.WriteString(socksString)
    106 109   pe.dbgPrint(buf)
    107 110  }
    108 111   
    109 112  func (pe *ProxyEngine) msgFailedMiddleware(socksString string) {
    110  - buf := copABuffer.Get().(*strings.Builder)
     113 + if !pe.DebugEnabled() {
     114 + return
     115 + }
     116 + buf := pools.CopABuffer.Get().(*strings.Builder)
    111 117   buf.WriteString("failed middleware check, ")
    112 118   buf.WriteString(socksString)
    113 119   buf.WriteString(", cycling...")
    skipped 1 lines
    115 121  }
    116 122   
    117 123  func (pe *ProxyEngine) msgTry(socksString string) {
    118  - buf := copABuffer.Get().(*strings.Builder)
     124 + if !pe.DebugEnabled() {
     125 + return
     126 + }
     127 + buf := pools.CopABuffer.Get().(*strings.Builder)
    119 128   buf.WriteString("try dial with: ")
    120 129   buf.WriteString(socksString)
    121 130   pe.dbgPrint(buf)
    122 131  }
    123 132   
    124 133  func (pe *ProxyEngine) msgCantGetLock(socksString string, putback bool) {
    125  - buf := copABuffer.Get().(*strings.Builder)
     134 + if !pe.DebugEnabled() {
     135 + return
     136 + }
     137 + buf := pools.CopABuffer.Get().(*strings.Builder)
    126 138   buf.WriteString("can't get lock for ")
    127 139   buf.WriteString(socksString)
    128 140   if putback {
    skipped 3 lines
    132 144  }
    133 145   
    134 146  func (pe *ProxyEngine) msgGotLock(socksString string) {
    135  - buf := copABuffer.Get().(*strings.Builder)
     147 + if !pe.DebugEnabled() {
     148 + return
     149 + }
     150 + buf := pools.CopABuffer.Get().(*strings.Builder)
    136 151   buf.WriteString("got lock for ")
    137 152   buf.WriteString(socksString)
    138 153   pe.dbgPrint(buf)
    139 154  }
    140 155   
    141 156  func (pe *ProxyEngine) msgChecked(sock *Proxy, success bool) {
    142  - buf := copABuffer.Get().(*strings.Builder)
     157 + if !pe.DebugEnabled() {
     158 + return
     159 + }
     160 + buf := pools.CopABuffer.Get().(*strings.Builder)
    143 161   if success {
    144 162   buf.WriteString("verified ")
    145 163   buf.WriteString(sock.Endpoint)
    146  - buf.WriteString(" as SOCKS")
     164 + if sock.proto != ProtoHTTP {
     165 + buf.WriteString(" as SOCKS")
     166 + } else {
     167 + buf.WriteString(" as HTTP proxy")
     168 + pe.dbgPrint(buf)
     169 + return
     170 + }
    147 171   buf.WriteString(getProtoStr(sock.proto))
    148 172   pe.dbgPrint(buf)
    149 173   return
    skipped 4 lines
    154 178  }
    155 179   
    156 180  func (pe *ProxyEngine) msgBadProxRate(sock *Proxy) {
    157  - buf := copABuffer.Get().(*strings.Builder)
     181 + if !pe.DebugEnabled() {
     182 + return
     183 + }
     184 + buf := pools.CopABuffer.Get().(*strings.Builder)
    158 185   buf.WriteString("badProx ratelimited: ")
    159 186   buf.WriteString(sock.Endpoint)
    160 187   pe.dbgPrint(buf)
    skipped 2 lines
  • ■ ■ ■ ■ ■ ■
    defs.go
    skipped 8 lines
    9 9   
    10 10   "github.com/panjf2000/ants/v2"
    11 11   rl "github.com/yunginnanet/Rate5"
     12 + 
     13 + "git.tcp.direct/kayos/prox5/internal/pools"
     14 + "git.tcp.direct/kayos/prox5/logger"
    12 15  )
    13 16   
    14 17  type ProxyChannels struct {
    skipped 9 lines
    24 27   
    25 28  // ProxyEngine represents a proxy pool
    26 29  type ProxyEngine struct {
    27  - Valids ProxyChannels
    28  - 
    29  - socksServerLogger socksLogger
    30  - Debug DebugPrinter
     30 + Valids ProxyChannels
     31 + DebugLogger logger.Logger
    31 32   
    32 33   // stats holds the statistics for our swamp
    33 34   stats *statistics
    skipped 7 lines
    41 42   useProx *rl.Limiter
    42 43   badProx *rl.Limiter
    43 44   
    44  - socks5ServerAuth socksCreds
    45  - 
    46 45   dispenseMiddleware func(*Proxy) (*Proxy, bool)
    47 46   
    48 47   ctx context.Context
    skipped 11 lines
    60 59  }
    61 60   
    62 61  var (
    63  - defaultStaleTime = 1 * time.Hour
    64  - defWorkers = 100
    65  - defBailout = 5
     62 + defaultStaleTime = 1 * time.Hour
     63 + defaultWorkerCount = 50
     64 + defaultBailout = 15
     65 + defaultRemoveAfter = 25
    66 66   // Note: I've chosen to use https here exclusively assuring all validated proxies are SSL capable.
    67 67   defaultChecks = []string{
    68 68   "https://wtfismyip.com/text",
    skipped 10 lines
    79 79  // Returns a pointer to our default options (modified and accessed later through concurrent safe getters and setters)
    80 80  func defOpt() *config {
    81 81   sm := &config{
    82  - useProxConfig: defUseProx,
    83  - badProxConfig: defBadProx,
     82 + useProxConfig: defaultUseProxyRatelimiter,
     83 + badProxConfig: defaultBadProxyRateLimiter,
    84 84   
    85 85   checkEndpoints: defaultChecks,
    86 86   userAgents: defaultUserAgents,
    87 87   RWMutex: &sync.RWMutex{},
     88 + removeafter: defaultRemoveAfter,
     89 + recycle: true,
     90 + debug: true,
     91 + dialerBailout: defaultBailout,
     92 + stale: defaultStaleTime,
     93 + maxWorkers: defaultWorkerCount,
     94 + redact: true,
    88 95   }
    89  - 
    90  - sm.Lock()
    91  - defer sm.Unlock()
    92  - 
    93  - sm.removeafter = 5
    94  - sm.recycle = true
    95  - sm.debug = false
    96 96   sm.validationTimeout = time.Duration(12) * time.Second
    97 97   sm.serverTimeout = time.Duration(180) * time.Second
    98  - 
    99  - sm.dialerBailout = defBailout
    100  - sm.stale = defaultStaleTime
    101  - sm.maxWorkers = defWorkers
    102  - 
    103 98   return sm
    104 99  }
    105 100   
    skipped 3 lines
    109 104   // stale is the amount of time since verification that qualifies a proxy going stale.
    110 105   // if a stale proxy is drawn during the use of our getter functions, it will be skipped.
    111 106   stale time.Duration
    112  - 
    113 107   // userAgents contains a list of userAgents to be randomly drawn from for proxied requests, this should be supplied via SetUserAgents
    114 108   userAgents []string
    115  - 
    116 109   // debug when enabled will print results as they come in
    117 110   debug bool
    118  - 
    119 111   // checkEndpoints includes web services that respond with (just) the WAN IP of the connection for validation purposes
    120 112   checkEndpoints []string
    121  - 
    122 113   // maxWorkers determines the maximum amount of workers used for checking proxies
    123 114   maxWorkers int
    124  - 
    125 115   // validationTimeout defines the timeout for proxy validation operations.
    126 116   // This will apply for both the initial quick check (dial), and the second check (HTTP GET).
    127 117   validationTimeout time.Duration
    128  - 
    129 118   // serverTimeout defines the timeout for outgoing connections made with the MysteryDialer.
    130 119   serverTimeout time.Duration
    131  - 
     120 + // dialerBailout defines the amount of times a dial atttempt can fail before giving up and returning an error.
    132 121   dialerBailout int
    133  - 
     122 + // redact when enabled will redact the target string from the debug output
     123 + redact bool
    134 124   // recycle determines whether or not we recycle proxies pack into the pending channel after we dispense them
    135 125   recycle bool
    136 126   // remove proxy from recycling after being marked bad this many times
    137 127   removeafter int
     128 + // shuffle determines whether or not we shuffle proxies before we validate and dispense them.
     129 + shuffle bool
    138 130   
    139 131   // TODO: make getters and setters for these
    140 132   useProxConfig rl.Policy
    skipped 6 lines
    147 139  // After calling this you may use the various "setters" to change the options before calling ProxyEngine.Start().
    148 140  func NewProxyEngine() *ProxyEngine {
    149 141   pe := &ProxyEngine{
    150  - stats: &statistics{birthday: time.Now()},
    151  - Debug: basicPrinter{},
     142 + stats: &statistics{birthday: time.Now()},
     143 + DebugLogger: basicPrinter{},
    152 144   
    153 145   swampopt: defOpt(),
    154 146   
    skipped 15 lines
    170 162   pe.dispenseMiddleware = func(p *Proxy) (*Proxy, bool) {
    171 163   return p, true
    172 164   }
    173  - 
    174 165   pe.ctx, pe.quit = context.WithCancel(context.Background())
    175  - 
    176  - atomic.StoreUint32(&pe.Status, uint32(StateNew))
    177  - 
    178 166   pe.swampmap = newSwampMap(pe)
    179 167   
    180  - pe.socksServerLogger = socksLogger{parent: pe}
    181  - 
     168 + atomic.StoreUint32(&pe.Status, uint32(StateNew))
    182 169   atomic.StoreInt32(&pe.runningdaemons, 0)
    183 170   
    184 171   pe.useProx = rl.NewCustomLimiter(pe.swampopt.useProxConfig)
    skipped 6 lines
    191 178   }))
    192 179   
    193 180   if err != nil {
    194  - buf := copABuffer.Get().(*strings.Builder)
     181 + buf := pools.CopABuffer.Get().(*strings.Builder)
    195 182   buf.WriteString("CRITICAL: ")
    196 183   buf.WriteString(err.Error())
    197 184   pe.dbgPrint(buf)
    skipped 43 lines
  • ■ ■ ■ ■ ■ ■
    dispense.go
    skipped 5 lines
    6 6   "time"
    7 7   
    8 8   "git.tcp.direct/kayos/common/entropy"
     9 + 
     10 + "git.tcp.direct/kayos/prox5/internal/pools"
    9 11  )
    10 12   
    11 13  // Socks5Str gets a SOCKS5 proxy that we have fully verified (dialed and then retrieved our IP address from a what-is-my-ip endpoint.
    skipped 91 lines
    103 105   defer atomic.StoreUint32(&sock.lock, stateUnlocked)
    104 106   
    105 107   if atomic.LoadInt64(&sock.timesBad) > int64(pe.GetRemoveAfter()) && pe.GetRemoveAfter() != -1 {
    106  - buf := copABuffer.Get().(*strings.Builder)
     108 + buf := pools.CopABuffer.Get().(*strings.Builder)
    107 109   buf.WriteString("deleting from map (too many failures): ")
    108 110   buf.WriteString(sock.Endpoint)
    109 111   pe.dbgPrint(buf)
    skipped 3 lines
    113 115   }
    114 116   
    115 117   if pe.badProx.Peek(sock) {
    116  - buf := copABuffer.Get().(*strings.Builder)
     118 + buf := pools.CopABuffer.Get().(*strings.Builder)
    117 119   buf.WriteString("badProx dial ratelimited: ")
    118 120   buf.WriteString(sock.Endpoint)
    119 121   pe.dbgPrint(buf)
    skipped 1 lines
    121 123   }
    122 124   
    123 125   if time.Since(sock.lastValidated) > pe.swampopt.stale {
    124  - buf := copABuffer.Get().(*strings.Builder)
     126 + buf := pools.CopABuffer.Get().(*strings.Builder)
    125 127   buf.WriteString("proxy stale: ")
    126 128   buf.WriteString(sock.Endpoint)
    127 129   pe.dbgPrint(buf)
    skipped 7 lines
  • ■ ■ ■ ■ ■ ■
    example/go.mod
    1  -module p5example
    2  - 
    3  -go 1.18
    4  - 
    5  -require (
    6  - git.tcp.direct/kayos/prox5 v0.5.3-0.20220709184754-7ecedfdd0c63
    7  - github.com/haxii/socks5 v1.0.0
    8  - github.com/mattn/go-tty v0.0.4
    9  -)
    10  - 
    11  -require (
    12  - git.tcp.direct/kayos/common v0.7.0 // indirect
    13  - git.tcp.direct/kayos/go-socks5 v1.0.1 // indirect
    14  - github.com/mattn/go-isatty v0.0.14 // indirect
    15  - github.com/miekg/dns v1.1.50 // indirect
    16  - github.com/panjf2000/ants/v2 v2.5.0 // indirect
    17  - github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
    18  - github.com/yunginnanet/Rate5 v1.0.1 // indirect
    19  - go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect
    20  - go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 // indirect
    21  - golang.org/x/mod v0.4.2 // indirect
    22  - golang.org/x/net v0.0.0-20220630215102-69896b714898 // indirect
    23  - golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
    24  - golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect
    25  - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
    26  - h12.io/socks v1.0.3 // indirect
    27  - inet.af/netaddr v0.0.0-20220617031823-097006376321 // indirect
    28  - nullprogram.com/x/rng v1.1.0 // indirect
    29  -)
    30  - 
  • ■ ■ ■ ■ ■ ■
    example/go.sum
    1  -git.tcp.direct/kayos/common v0.7.0 h1:KZDwoCzUiwQaYSWESr080N8wUVyLD27QYgzXgc7LiAQ=
    2  -git.tcp.direct/kayos/common v0.7.0/go.mod h1:7tMZBVNPLFSZk+JXTA6pgXWpf/XHqYRfT7Q3OziI++Y=
    3  -git.tcp.direct/kayos/go-socks5 v1.0.1 h1:Pe9PlSXofibIJyWkrr9rwWcgyfUxSdUcDCQ//6fAi0U=
    4  -git.tcp.direct/kayos/go-socks5 v1.0.1/go.mod h1:I9xU/uzFAZKukMJgEgWPrfC6rDlcPQe8wXMibF3qvhE=
    5  -git.tcp.direct/kayos/prox5 v0.5.3-0.20220709184754-7ecedfdd0c63 h1:eidAXI7o5gIf4linhOIFEtSiYQQOsqHLcMqhBrF9vgA=
    6  -git.tcp.direct/kayos/prox5 v0.5.3-0.20220709184754-7ecedfdd0c63/go.mod h1:/44/UlcKPOXZ/jr+NdftkZvLkW0k4QokPXqAdQ2O3BQ=
    7  -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
    8  -github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
    9  -github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364 h1:5XxdakFhqd9dnXoAZy1Mb2R/DZ6D1e+0bGC/JhucGYI=
    10  -github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364/go.mod h1:eDJQioIyy4Yn3MVivT7rv/39gAJTrA7lgmYr8EW950c=
    11  -github.com/haxii/socks5 v1.0.0 h1:78BIzd4lHibdRNOKdMwKCnnsgYLW9SeotqU+nMhWSSo=
    12  -github.com/haxii/socks5 v1.0.0/go.mod h1:6O9Ba2yrLlvuSe/L1e84eZI8cPw6H+q1Ilr4hjgm4uY=
    13  -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
    14  -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
    15  -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
    16  -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
    17  -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
    18  -github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
    19  -github.com/mattn/go-tty v0.0.4 h1:NVikla9X8MN0SQAqCYzpGyXv0jY7MNl3HOWD2dkle7E=
    20  -github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28=
    21  -github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
    22  -github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
    23  -github.com/panjf2000/ants/v2 v2.5.0 h1:1rWGWSnxCsQBga+nQbA4/iY6VMeNoOIAM0ZWh9u3q2Q=
    24  -github.com/panjf2000/ants/v2 v2.5.0/go.mod h1:cU93usDlihJZ5CfRGNDYsiBYvoilLvBF5Qp/BT2GNRE=
    25  -github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
    26  -github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
    27  -github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
    28  -github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
    29  -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
    30  -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
    31  -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
    32  -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
    33  -github.com/yunginnanet/Rate5 v1.0.1 h1:OePwNrj9/A/flmhyr/gKI5RYgrW6d1oWCqrZRXUev3k=
    34  -github.com/yunginnanet/Rate5 v1.0.1/go.mod h1:f0r66kVQZojRqUgVdLC/CKexMlF0nUDAmd01tBeF4Ms=
    35  -go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE=
    36  -go4.org/intern v0.0.0-20211027215823-ae77deb06f29/go.mod h1:cS2ma+47FKrLPdXFpr7CuxiTW3eyJbWew4qx0qtQWDA=
    37  -go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
    38  -go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 h1:FyBZqvoA/jbNzuAWLQE2kG820zMAkcilx6BMjGbL/E4=
    39  -go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
    40  -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
    41  -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
    42  -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
    43  -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
    44  -golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
    45  -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
    46  -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
    47  -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
    48  -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
    49  -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
    50  -golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
    51  -golang.org/x/net v0.0.0-20220630215102-69896b714898 h1:K7wO6V1IrczY9QOQ2WkVpw4JQSwCd52UsxVEirZUfiw=
    52  -golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
    53  -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    54  -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    55  -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
    56  -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    57  -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
    58  -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
    59  -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    60  -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    61  -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    62  -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    63  -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    64  -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    65  -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    66  -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    67  -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
    68  -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
    69  -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
    70  -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
    71  -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
    72  -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
    73  -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
    74  -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
    75  -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
    76  -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
    77  -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
    78  -golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 h1:BonxutuHCTL0rBDnZlKjpGIQFTjyUVTexFOdWkB6Fg0=
    79  -golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
    80  -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
    81  -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
    82  -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
    83  -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
    84  -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
    85  -h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo=
    86  -h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck=
    87  -inet.af/netaddr v0.0.0-20220617031823-097006376321 h1:B4dC8ySKTQXasnjDTMsoCMf1sQG4WsMej0WXaHxunmU=
    88  -inet.af/netaddr v0.0.0-20220617031823-097006376321/go.mod h1:OIezDfdzOgFhuw4HuWapWq2e9l0H9tK4F1j+ETRtF3k=
    89  -nullprogram.com/x/rng v1.1.0 h1:SMU7DHaQSWtKJNTpNFIFt8Wd/KSmOuSDPXrMFp/UMro=
    90  -nullprogram.com/x/rng v1.1.0/go.mod h1:glGw6V87vyfawxCzqOABL3WfL95G65az9Z2JZCylCkg=
    91  - 
  • ■ ■ ■ ■ ■
    example/main.go
    skipped 5 lines
    6 6   "strconv"
    7 7   "time"
    8 8   
    9  - "git.tcp.direct/kayos/prox5"
    10 9   "github.com/haxii/socks5"
    11 10   "github.com/mattn/go-tty"
     11 + 
     12 + "git.tcp.direct/kayos/prox5"
    12 13  )
    13 14   
    14 15  var (
    skipped 8 lines
    23 24   
    24 25  // Printf is used to handle socks server logging.
    25 26  func (s socksLogger) Printf(format string, a ...interface{}) {
    26  - println(fmt.Sprintf(format, a))
     27 + println(fmt.Sprintf(format, a...))
    27 28  }
    28 29   
    29 30  func StartUpstreamProxy(listen string) {
    skipped 128 lines
  • ■ ■ ■ ■ ■ ■
    getters.go
    skipped 6 lines
    7 7   "time"
    8 8   
    9 9   "git.tcp.direct/kayos/common/entropy"
     10 + 
     11 + "git.tcp.direct/kayos/prox5/internal/pools"
    10 12  )
    11 13   
    12 14  // GetProto retrieves the known protocol value of the Proxy.
    skipped 5 lines
    18 20  func (sock *Proxy) String() string {
    19 21   tout := ""
    20 22   if sock.parent.GetServerTimeoutStr() != "-1" {
    21  - tbuf := copABuffer.Get().(*strings.Builder)
     23 + tbuf := pools.CopABuffer.Get().(*strings.Builder)
    22 24   tbuf.WriteString("?timeout=")
    23 25   tbuf.WriteString(sock.parent.GetServerTimeoutStr())
    24 26   tbuf.WriteString("s")
    25 27   tout = tbuf.String()
    26  - discardBuffer(tbuf)
     28 + pools.DiscardBuffer(tbuf)
    27 29   }
    28  - buf := copABuffer.Get().(*strings.Builder)
     30 + buf := pools.CopABuffer.Get().(*strings.Builder)
    29 31   buf.WriteString("socks")
    30 32   buf.WriteString(getProtoStr(sock.GetProto()))
    31 33   buf.WriteString("://")
    skipped 2 lines
    34 36   buf.WriteString(tout)
    35 37   }
    36 38   out := buf.String()
    37  - discardBuffer(buf)
     39 + pools.DiscardBuffer(buf)
    38 40   return out
    39 41  }
    40 42   
    skipped 75 lines
    116 118  }
    117 119   
    118 120  // GetWorkers retrieves pond worker statistics:
    119  -// * return MaxWorkers, RunningWorkers, IdleWorkers
     121 +// - return MaxWorkers, RunningWorkers, IdleWorkers
    120 122  func (pe *ProxyEngine) GetWorkers() (maxWorkers, runningWorkers, idleWorkers int) {
    121 123   pe.mu.RLock()
    122 124   defer pe.mu.RUnlock()
    skipped 1 lines
    124 126  }
    125 127   
    126 128  // GetRemoveAfter retrieves the removeafter policy, the amount of times a recycled proxy is marked as bad until it is removed entirely.
    127  -// * returns -1 if recycling is disabled.
     129 +// - returns -1 if recycling is disabled.
    128 130  func (pe *ProxyEngine) GetRemoveAfter() int {
    129 131   pe.mu.RLock()
    130 132   defer pe.mu.RUnlock()
    skipped 18 lines
    149 151   return pe.dispenseMiddleware
    150 152  }
    151 153   
     154 +func (pe *ProxyEngine) GetShuffleStatus() bool {
     155 + pe.mu.RLock()
     156 + defer pe.mu.RUnlock()
     157 + return pe.swampopt.shuffle
     158 +}
     159 + 
  • ■ ■ ■ ■ ■ ■
    go.mod
    skipped 4 lines
    5 5  require (
    6 6   git.tcp.direct/kayos/common v0.7.0
    7 7   git.tcp.direct/kayos/go-socks5 v1.0.1
     8 + git.tcp.direct/kayos/socks v0.0.0-20220828111753-f9f7cd3e7ee7
     9 + github.com/haxii/socks5 v1.0.0
     10 + github.com/mattn/go-tty v0.0.4
    8 11   github.com/miekg/dns v1.1.50
    9 12   github.com/panjf2000/ants/v2 v2.5.0
    10 13   github.com/yunginnanet/Rate5 v1.0.1
    11  - h12.io/socks v1.0.3
     14 + golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985
    12 15   inet.af/netaddr v0.0.0-20220617031823-097006376321
    13 16  )
    14 17   
    15 18  require (
     19 + github.com/mattn/go-isatty v0.0.14 // indirect
    16 20   github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
    17 21   go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect
    18 22   go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 // indirect
    19 23   golang.org/x/mod v0.4.2 // indirect
    20  - golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 // indirect
    21 24   golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
    22 25   golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect
    23 26   golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
    skipped 3 lines
  • ■ ■ ■ ■ ■
    go.sum
    skipped 1 lines
    2 2  git.tcp.direct/kayos/common v0.7.0/go.mod h1:7tMZBVNPLFSZk+JXTA6pgXWpf/XHqYRfT7Q3OziI++Y=
    3 3  git.tcp.direct/kayos/go-socks5 v1.0.1 h1:Pe9PlSXofibIJyWkrr9rwWcgyfUxSdUcDCQ//6fAi0U=
    4 4  git.tcp.direct/kayos/go-socks5 v1.0.1/go.mod h1:I9xU/uzFAZKukMJgEgWPrfC6rDlcPQe8wXMibF3qvhE=
     5 +git.tcp.direct/kayos/socks v0.0.0-20220828111753-f9f7cd3e7ee7 h1:zuN2VWun3lu34Lz+LAt/ZbY6YJ0SqzQf2d00YQUfNao=
     6 +git.tcp.direct/kayos/socks v0.0.0-20220828111753-f9f7cd3e7ee7/go.mod h1:KmN5oa1od8tMHmRIr9GOqWKx9MR0oGZVtAj+ARxiPwo=
    5 7  github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
    6 8  github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
    7 9  github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364 h1:5XxdakFhqd9dnXoAZy1Mb2R/DZ6D1e+0bGC/JhucGYI=
    8  -github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364/go.mod h1:eDJQioIyy4Yn3MVivT7rv/39gAJTrA7lgmYr8EW950c=
     10 +github.com/haxii/socks5 v1.0.0 h1:78BIzd4lHibdRNOKdMwKCnnsgYLW9SeotqU+nMhWSSo=
     11 +github.com/haxii/socks5 v1.0.0/go.mod h1:6O9Ba2yrLlvuSe/L1e84eZI8cPw6H+q1Ilr4hjgm4uY=
     12 +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
     13 +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
     14 +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
     15 +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
     16 +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
     17 +github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
     18 +github.com/mattn/go-tty v0.0.4 h1:NVikla9X8MN0SQAqCYzpGyXv0jY7MNl3HOWD2dkle7E=
     19 +github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28=
    9 20  github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
    10 21  github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
    11 22  github.com/panjf2000/ants/v2 v2.5.0 h1:1rWGWSnxCsQBga+nQbA4/iY6VMeNoOIAM0ZWh9u3q2Q=
    12 23  github.com/panjf2000/ants/v2 v2.5.0/go.mod h1:cU93usDlihJZ5CfRGNDYsiBYvoilLvBF5Qp/BT2GNRE=
    13 24  github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
    14 25  github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
    15  -github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
    16  -github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
     26 +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
    17 27  github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
    18 28  github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
    19 29  github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
    skipped 22 lines
    42 52  golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
    43 53  golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    44 54  golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
     55 +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
    45 56  golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
     57 +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
     58 +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    46 59  golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    47 60  golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    48 61  golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    skipped 17 lines
    66 79  golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
    67 80  golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
    68 81  gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
    69  -h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo=
    70  -h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck=
    71 82  inet.af/netaddr v0.0.0-20220617031823-097006376321 h1:B4dC8ySKTQXasnjDTMsoCMf1sQG4WsMej0WXaHxunmU=
    72 83  inet.af/netaddr v0.0.0-20220617031823-097006376321/go.mod h1:OIezDfdzOgFhuw4HuWapWq2e9l0H9tK4F1j+ETRtF3k=
    73 84  nullprogram.com/x/rng v1.1.0 h1:SMU7DHaQSWtKJNTpNFIFt8Wd/KSmOuSDPXrMFp/UMro=
    skipped 2 lines
  • ■ ■ ■ ■ ■ ■
    internal/pools/strings.go
     1 +package pools
     2 + 
     3 +import (
     4 + "strings"
     5 + "sync"
     6 +)
     7 + 
     8 +var CopABuffer = &sync.Pool{New: func() interface{} { return &strings.Builder{} }}
     9 + 
     10 +func DiscardBuffer(buf *strings.Builder) {
     11 + buf.Reset()
     12 + CopABuffer.Put(buf)
     13 +}
     14 + 
  • ■ ■ ■ ■ ■ ■
    logger/logger.go
     1 +package logger
     2 + 
     3 +type Logger interface {
     4 + Print(str string)
     5 + Printf(format string, a ...interface{})
     6 +}
     7 + 
  • ■ ■ ■ ■ ■ ■
    mystery_dialer.go
    skipped 4 lines
    5 5   "fmt"
    6 6   "net"
    7 7   "strings"
    8  - "sync"
    9 8   "sync/atomic"
    10 9   "time"
    11 10   
    12  - "h12.io/socks"
    13  -)
    14  - 
    15  -var copABuffer = &sync.Pool{New: func() interface{} { return &strings.Builder{} }}
     11 + "git.tcp.direct/kayos/socks"
    16 12   
    17  -func discardBuffer(buf *strings.Builder) {
    18  - buf.Reset()
    19  - copABuffer.Put(buf)
    20  -}
     13 + "git.tcp.direct/kayos/prox5/internal/pools"
     14 +)
    21 15   
    22 16  // DialContext is a simple stub adapter to implement a net.Dialer.
    23 17  func (pe *ProxyEngine) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
    skipped 16 lines
    40 34  }
    41 35   
    42 36  func (pe *ProxyEngine) addTimeout(socksString string) string {
    43  - tout := copABuffer.Get().(*strings.Builder)
     37 + tout := pools.CopABuffer.Get().(*strings.Builder)
    44 38   tout.WriteString(socksString)
    45 39   tout.WriteString("?timeout=")
    46 40   tout.WriteString(pe.GetServerTimeoutStr())
    47 41   tout.WriteRune('s')
    48 42   socksString = tout.String()
    49  - discardBuffer(tout)
     43 + pools.DiscardBuffer(tout)
    50 44   return socksString
    51 45  }
    52 46   
    skipped 21 lines
    74 68   
    75 69  // MysteryDialer is a dialer function that will use a different proxy for every request.
    76 70  func (pe *ProxyEngine) MysteryDialer(ctx context.Context, network, addr string) (net.Conn, error) {
    77  - var (
    78  - socksString string
    79  - count int
    80  - )
    81 71   // pull down proxies from channel until we get a proxy good enough for our spoiled asses
    82  - 
     72 + var count = 0
    83 73   for {
    84 74   max := pe.GetDialerBailout()
    85 75   if count > max {
    skipped 13 lines
    99 89   break
    100 90   }
    101 91   }
    102  - if pe.GetServerTimeoutStr() != "-1" {
    103  - socksString = pe.addTimeout(socksString)
    104  - }
     92 + socksString := sock.String()
    105 93   var ok bool
    106 94   if sock, ok = pe.dispenseMiddleware(sock); !ok {
     95 + atomic.StoreUint32(&sock.lock, stateUnlocked)
    107 96   pe.msgFailedMiddleware(socksString)
    108 97   continue
    109 98   }
    skipped 3 lines
    113 102   conn, err := dialSocks(network, addr)
    114 103   if err != nil {
    115 104   count++
    116  - pe.msgUnableToReach(socksString)
     105 + pe.msgUnableToReach(socksString, addr, err)
    117 106   continue
    118 107   }
    119 108   pe.msgUsingProxy(socksString)
    skipped 4 lines
  • ■ ■ ■ ■ ■ ■
    mystery_resolver.go
     1 +package prox5
     2 + 
     3 +/*
     4 +import (
     5 + "context"
     6 + "net"
     7 + 
     8 + "inet.af/netaddr"
     9 +)
     10 + 
     11 +type dnsCacheEntry []netaddr.IP
     12 + 
     13 +var dnsCache = make(map[string]dnsCacheEntry)
     14 + 
     15 +func (pe *ProxyEngine) Resolve(ctx context.Context, name string) (context.Context, net.IP, error) {
     16 + var result net.IP
     17 + for {
     18 + select {
     19 + case <-ctx.Done():
     20 + return ctx, nil, ctx.Err()
     21 + }
     22 + }
     23 +}
     24 +*/
     25 + 
  • ■ ■ ■ ■ ■ ■
    proxy.go
    skipped 6 lines
    7 7  )
    8 8   
    9 9  // https://pkg.go.dev/github.com/yunginnanet/Rate5#Policy
    10  -var defUseProx = rl.Policy{
    11  - Window: 60,
    12  - Burst: 2,
     10 +var defaultUseProxyRatelimiter = rl.Policy{
     11 + Window: 55,
     12 + Burst: 55,
    13 13  }
    14 14   
    15  -var defBadProx = rl.Policy{
    16  - Window: 60,
    17  - Burst: 3,
     15 +var defaultBadProxyRateLimiter = rl.Policy{
     16 + Window: 55,
     17 + Burst: 25,
    18 18  }
    19 19   
    20 20  const (
    skipped 8 lines
    29 29   ProtoSOCKS4
    30 30   ProtoSOCKS4a
    31 31   ProtoSOCKS5
     32 + ProtoSOCKS5h
    32 33   ProtoHTTP
    33 34  )
    34 35   
    skipped 25 lines
  • ■ ■ ■ ■ ■
    setters.go
    skipped 1 lines
    2 2   
    3 3  import (
    4 4   "time"
     5 + 
     6 + "git.tcp.direct/kayos/prox5/logger"
    5 7  )
    6 8   
    7 9  // AddUserAgents appends to the list of useragents we randomly choose from during proxied requests
    skipped 67 lines
    75 77  }
    76 78   
    77 79  // SetRemoveAfter sets the removeafter policy, the amount of times a recycled proxy is marked as bad before it is removed entirely.
    78  -// * Default is 5
    79  -// * To disable deleting entirely, set this value to -1
    80  -// * Only applies when recycling is enabled
     80 +// - Default is 10
     81 +// - To disable deleting entirely, set this value to -1
     82 +// - Only applies when recycling is enabled
    81 83  func (pe *ProxyEngine) SetRemoveAfter(timesfailed int) {
    82 84   pe.swampopt.Lock()
    83 85   defer pe.swampopt.Unlock()
    skipped 1 lines
    85 87  }
    86 88   
    87 89  // SetDialerBailout sets the amount of times the MysteryDialer will dial out and fail before it bails out.
    88  -// * The dialer will attempt to redial a destination with a different proxy a specified amount of times before it gives up
     90 +// - The dialer will attempt to redial a destination with a different proxy a specified amount of times before it gives up
    89 91  func (pe *ProxyEngine) SetDialerBailout(dialattempts int) {
    90 92   pe.swampopt.Lock()
    91 93   defer pe.swampopt.Unlock()
    skipped 9 lines
    101 103   pe.dispenseMiddleware = f
    102 104  }
    103 105   
     106 +// SetDebugLogger sets the debug logger for the ProxyEngine. See the Logger interface for implementation details.
     107 +func (pe *ProxyEngine) SetDebugLogger(l logger.Logger) {
     108 + debugHardLock.Lock()
     109 + pe.mu.Lock()
     110 + pe.DebugLogger = l
     111 + pe.mu.Unlock()
     112 + debugHardLock.Unlock()
     113 +}
     114 + 
     115 +func (pe *ProxyEngine) SetShuffle(shuffle bool) {
     116 + pe.mu.Lock()
     117 + defer pe.mu.Unlock()
     118 + pe.swampopt.shuffle = shuffle
     119 +}
     120 + 
  • ■ ■ ■ ■ ■ ■
    socks5_server.go
    1 1  package prox5
    2 2   
    3 3  import (
    4  - "fmt"
    5 4   "strings"
    6 5   
    7 6   "git.tcp.direct/kayos/go-socks5"
    8  -)
    9  - 
    10  -type socksLogger struct {
    11  - parent *ProxyEngine
    12  -}
    13 7   
    14  -// Printf is used to handle socks server logging.
    15  -func (s socksLogger) Printf(format string, a ...interface{}) {
    16  - buf := copABuffer.Get().(*strings.Builder)
    17  - buf.WriteString(fmt.Sprintf(format, a...))
    18  - s.parent.dbgPrint(buf)
    19  -}
     8 + "git.tcp.direct/kayos/prox5/internal/pools"
     9 +)
    20 10   
    21 11  type socksCreds struct {
    22 12   username string
    skipped 12 lines
    35 25  // listen is standard Go listen string, e.g: "127.0.0.1:1080".
    36 26  // username and password are used for authenticatig to the SOCKS5 server.
    37 27  func (pe *ProxyEngine) StartSOCKS5Server(listen, username, password string) error {
    38  - pe.socks5ServerAuth = socksCreds{username: username, password: password}
    39 28   
    40 29   conf := &socks5.Config{
    41  - Credentials: pe.socks5ServerAuth,
    42  - Logger: pe.socksServerLogger,
     30 + Credentials: socksCreds{username: username, password: password},
     31 + Logger: pe.DebugLogger,
    43 32   Dial: pe.MysteryDialer,
     33 + // Resolver: pe.MysteryResolver,
    44 34   }
    45 35   
    46  - buf := copABuffer.Get().(*strings.Builder)
     36 + buf := pools.CopABuffer.Get().(*strings.Builder)
    47 37   buf.WriteString("listening for SOCKS5 connections on ")
    48 38   buf.WriteString(listen)
    49 39   pe.dbgPrint(buf)
    skipped 9 lines
  • ■ ■ ■ ■ ■ ■
    validator_engine.go
    skipped 3 lines
    4 4   "bytes"
    5 5   "crypto/tls"
    6 6   "errors"
    7  - "fmt"
    8 7   "io"
    9 8   "net"
    10 9   "net/http"
    skipped 2 lines
    13 12   "sync/atomic"
    14 13   "time"
    15 14   
    16  - "h12.io/socks"
     15 + "git.tcp.direct/kayos/socks"
     16 + "golang.org/x/net/proxy"
     17 + 
     18 + "git.tcp.direct/kayos/prox5/internal/pools"
    17 19  )
    18 20   
    19 21  func (pe *ProxyEngine) prepHTTP() (*http.Client, *http.Transport, *http.Request, error) {
    skipped 14 lines
    34 36   var transporter = &http.Transport{
    35 37   DisableKeepAlives: true,
    36 38   TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, //nolint:gosec
    37  - TLSHandshakeTimeout: pe.swampopt.validationTimeout,
     39 + TLSHandshakeTimeout: pe.GetValidationTimeout(),
    38 40   }
    39 41   
    40 42   return client, transporter, req, err
    skipped 8 lines
    49 51   sock.lastValidated = time.Now()
    50 52  }
    51 53   
    52  -func (pe *ProxyEngine) bakeHTTP(sock *Proxy) (client *http.Client, req *http.Request, err error) {
    53  - dialSocks := socks.Dial(fmt.Sprintf(
    54  - "socks%s://%s/?timeout=%ss",
    55  - getProtoStr(sock.proto),
    56  - sock.Endpoint,
    57  - pe.GetValidationTimeoutStr()),
    58  - )
     54 +func (pe *ProxyEngine) bakeHTTP(hmd *HandMeDown) (client *http.Client, req *http.Request, err error) {
     55 + builder := pools.CopABuffer.Get().(*strings.Builder)
     56 + builder.WriteString("socks")
     57 + builder.WriteString(getProtoStr(hmd.sock.proto))
     58 + builder.WriteString("://")
     59 + builder.WriteString(hmd.sock.Endpoint)
     60 + builder.WriteString("/?timeout=")
     61 + builder.WriteString(pe.GetValidationTimeoutStr())
     62 + builder.WriteString("s")
     63 + 
     64 + dialSocks := socks.DialWithConn(builder.String(), hmd.conn)
     65 + pools.DiscardBuffer(builder)
     66 + 
    59 67   var (
    60 68   purl *url.URL
    61 69   transport *http.Transport
    skipped 3 lines
    65 73   return
    66 74   }
    67 75   
    68  - if sock.proto != ProtoHTTP {
    69  - transport.Dial = dialSocks //nolint:staticcheck
     76 + if hmd.sock.proto != ProtoHTTP {
     77 + transport.Dial = dialSocks
    70 78   client.Transport = transport
    71 79   return
    72 80   }
    73  - if purl, err = url.Parse("http://" + sock.Endpoint); err != nil {
     81 + if purl, err = url.Parse("http://" + hmd.sock.Endpoint); err != nil {
    74 82   return
    75 83   }
    76 84   transport.Proxy = http.ProxyURL(purl)
    77 85   return
    78 86  }
    79 87   
    80  -func (pe *ProxyEngine) checkHTTP(sock *Proxy) (string, error) {
     88 +func (pe *ProxyEngine) validate(hmd *HandMeDown) (string, error) {
    81 89   var (
    82 90   client *http.Client
    83 91   req *http.Request
    84 92   err error
    85 93   )
    86 94   
    87  - client, req, err = pe.bakeHTTP(sock)
     95 + client, req, err = pe.bakeHTTP(hmd)
    88 96   if err != nil {
    89 97   return "", err
    90 98   }
    skipped 12 lines
    103 111   pe.stats.Checked++
    104 112  }
    105 113   
     114 +type HandMeDown struct {
     115 + sock *Proxy
     116 + conn net.Conn
     117 + under proxy.Dialer
     118 +}
     119 + 
     120 +func (hmd *HandMeDown) Dial(network, addr string) (c net.Conn, err error) {
     121 + if hmd.conn.LocalAddr().Network() != network {
     122 + return hmd.under.Dial(network, addr)
     123 + }
     124 + if hmd.conn.RemoteAddr().String() != addr {
     125 + return hmd.under.Dial(network, addr)
     126 + }
     127 + return hmd.conn, nil
     128 +}
     129 + 
    106 130  func (pe *ProxyEngine) singleProxyCheck(sock *Proxy) error {
    107 131   defer pe.anothaOne()
    108 132   split := strings.Split(sock.Endpoint, "@")
    skipped 1 lines
    110 134   if len(split) == 2 {
    111 135   endpoint = split[1]
    112 136   }
    113  - if _, err := net.DialTimeout("tcp", endpoint,
    114  - pe.swampopt.validationTimeout); err != nil {
    115  - pe.badProx.Check(sock)
     137 + conn, err := net.DialTimeout("tcp", endpoint, pe.GetValidationTimeout())
     138 + if err != nil {
    116 139   return err
    117 140   }
    118 141   
    119  - resp, err := pe.checkHTTP(sock)
     142 + hmd := &HandMeDown{sock: sock, conn: conn, under: proxy.Direct}
     143 + 
     144 + resp, err := pe.validate(hmd)
    120 145   if err != nil {
    121 146   pe.badProx.Check(sock)
    122 147   return err
    skipped 10 lines
    133 158  }
    134 159   
    135 160  var protoMap = map[ProxyProtocol]string{
    136  - ProtoSOCKS4: "4a", ProtoSOCKS4a: "4",
     161 + ProtoSOCKS4: "4", ProtoSOCKS4a: "4a",
    137 162   ProtoSOCKS5: "5", ProtoHTTP: "http",
     163 + ProtoSOCKS5h: "5h",
    138 164  }
    139 165   
    140 166  func getProtoStr(protocol ProxyProtocol) string {
    skipped 72 lines
Please wait...
Page is in error, reload to recover