Stupid dumb optimized

This commit is contained in:
kayos@tcp.direct 2022-07-24 23:23:12 -07:00
commit 144fe6b376
Signed by: kayos
GPG Key ID: 4B841471B4BEE979
15 changed files with 333 additions and 67 deletions

@ -3,6 +3,7 @@ package prox5
import (
"context"
"errors"
"strings"
"sync/atomic"
)
@ -39,7 +40,9 @@ func (pe *ProxyEngine) Pause() error {
return errors.New("not running")
}
pe.dbgPrint("pausing...")
buf := copABuffer.Get().(*strings.Builder)
buf.WriteString("pausing...")
pe.dbgPrint(buf)
pe.quit()

@ -3,6 +3,7 @@ package prox5
import (
"errors"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
@ -76,10 +77,10 @@ func (pe *ProxyEngine) mapBuilder() {
pe.pool.Reboot()
}
pe.dbgPrint("map builder started")
pe.dbgPrint(simpleString("map builder started"))
go func() {
defer pe.dbgPrint("map builder paused")
defer pe.dbgPrint(simpleString("map builder paused"))
for {
select {
case <-pe.ctx.Done():
@ -128,8 +129,8 @@ func (pe *ProxyEngine) jobSpawner() {
pe.pool.Reboot()
}
pe.dbgPrint("job spawner started")
defer pe.dbgPrint("job spawner paused")
pe.dbgPrint(simpleString("job spawner started"))
defer pe.dbgPrint(simpleString("job spawner paused"))
q := make(chan bool)
@ -142,12 +143,16 @@ func (pe *ProxyEngine) jobSpawner() {
return
case sock := <-pe.Pending:
if err := pe.pool.Submit(sock.validate); err != nil {
pe.dbgPrint(err.Error())
pe.dbgPrint(simpleString(err.Error()))
}
default:
time.Sleep(25 * time.Millisecond)
count := pe.recycling()
pe.dbgPrint("recycled " + strconv.Itoa(count) + " proxies from our map")
buf := copABuffer.Get().(*strings.Builder)
buf.WriteString("recycled ")
buf.WriteString(strconv.Itoa(count))
buf.WriteString(" proxies from our map")
pe.dbgPrint(buf)
}
}
}()

@ -2,6 +2,7 @@ package prox5
import (
"fmt"
"strings"
"sync"
)
@ -63,18 +64,29 @@ func (pe *ProxyEngine) DisableDebug() {
pe.swampopt.debug = false
}
func (pe *ProxyEngine) dbgPrint(str string) {
func simpleString(s string) *strings.Builder {
buf := copABuffer.Get().(*strings.Builder)
buf.WriteString(s)
return buf
}
func (pe *ProxyEngine) dbgPrint(builder *strings.Builder) {
defer discardBuffer(builder)
if !pe.swampopt.debug {
return
}
if !useDebugChannel {
pe.Debug.Print(str)
pe.Debug.Print(builder.String())
return
}
select {
case debugChan <- str:
case debugChan <- builder.String():
return
default:
pe.Debug.Print("overflow: " + str)
buf := copABuffer.Get().(*strings.Builder)
buf.WriteString("overflow: ")
buf.WriteString(builder.String())
pe.Debug.Print(buf.String())
discardBuffer(buf)
}
}

@ -2,6 +2,7 @@ package prox5
import (
"context"
"strings"
"sync"
"sync/atomic"
"time"
@ -190,7 +191,10 @@ func NewProxyEngine() *ProxyEngine {
}))
if err != nil {
pe.dbgPrint("CRITICAL: " + err.Error())
buf := copABuffer.Get().(*strings.Builder)
buf.WriteString("CRITICAL: ")
buf.WriteString(err.Error())
pe.dbgPrint(buf)
panic(err)
}

@ -1,6 +1,7 @@
package prox5
import (
"strings"
"sync/atomic"
"time"
@ -103,19 +104,28 @@ func (pe *ProxyEngine) stillGood(sock *Proxy) bool {
defer atomic.StoreUint32(&sock.lock, stateUnlocked)
if atomic.LoadInt64(&sock.timesBad) > int64(pe.GetRemoveAfter()) && pe.GetRemoveAfter() != -1 {
pe.dbgPrint("deleting from map (too many failures): " + sock.Endpoint)
buf := copABuffer.Get().(*strings.Builder)
buf.WriteString("deleting from map (too many failures): ")
buf.WriteString(sock.Endpoint)
pe.dbgPrint(buf)
if err := pe.swampmap.delete(sock.Endpoint); err != nil {
pe.dbgPrint(err.Error())
pe.dbgPrint(simpleString(err.Error()))
}
}
if pe.badProx.Peek(sock) {
pe.dbgPrint("badProx dial ratelimited: " + sock.Endpoint)
buf := copABuffer.Get().(*strings.Builder)
buf.WriteString("badProx dial ratelimited: ")
buf.WriteString(sock.Endpoint)
pe.dbgPrint(buf)
return false
}
if time.Since(sock.lastValidated) > pe.swampopt.stale {
pe.dbgPrint("proxy stale: " + sock.Endpoint)
buf := copABuffer.Get().(*strings.Builder)
buf.WriteString("proxy stale: ")
buf.WriteString(sock.Endpoint)
pe.dbgPrint(buf)
go pe.stats.stale()
return false
}

29
example/go.mod Normal file

@ -0,0 +1,29 @@
module p5example
go 1.18
require (
git.tcp.direct/kayos/prox5 v0.5.3-0.20220709184754-7ecedfdd0c63
github.com/haxii/socks5 v1.0.0
github.com/mattn/go-tty v0.0.4
)
require (
git.tcp.direct/kayos/common v0.7.0 // indirect
git.tcp.direct/kayos/go-socks5 v1.0.1 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/miekg/dns v1.1.50 // indirect
github.com/panjf2000/ants/v2 v2.5.0 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/yunginnanet/Rate5 v1.0.1 // indirect
go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect
go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 // indirect
golang.org/x/mod v0.4.2 // indirect
golang.org/x/net v0.0.0-20220630215102-69896b714898 // indirect
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
h12.io/socks v1.0.3 // indirect
inet.af/netaddr v0.0.0-20220617031823-097006376321 // indirect
nullprogram.com/x/rng v1.1.0 // indirect
)

90
example/go.sum Normal file

@ -0,0 +1,90 @@
git.tcp.direct/kayos/common v0.7.0 h1:KZDwoCzUiwQaYSWESr080N8wUVyLD27QYgzXgc7LiAQ=
git.tcp.direct/kayos/common v0.7.0/go.mod h1:7tMZBVNPLFSZk+JXTA6pgXWpf/XHqYRfT7Q3OziI++Y=
git.tcp.direct/kayos/go-socks5 v1.0.1 h1:Pe9PlSXofibIJyWkrr9rwWcgyfUxSdUcDCQ//6fAi0U=
git.tcp.direct/kayos/go-socks5 v1.0.1/go.mod h1:I9xU/uzFAZKukMJgEgWPrfC6rDlcPQe8wXMibF3qvhE=
git.tcp.direct/kayos/prox5 v0.5.3-0.20220709184754-7ecedfdd0c63 h1:eidAXI7o5gIf4linhOIFEtSiYQQOsqHLcMqhBrF9vgA=
git.tcp.direct/kayos/prox5 v0.5.3-0.20220709184754-7ecedfdd0c63/go.mod h1:/44/UlcKPOXZ/jr+NdftkZvLkW0k4QokPXqAdQ2O3BQ=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364 h1:5XxdakFhqd9dnXoAZy1Mb2R/DZ6D1e+0bGC/JhucGYI=
github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364/go.mod h1:eDJQioIyy4Yn3MVivT7rv/39gAJTrA7lgmYr8EW950c=
github.com/haxii/socks5 v1.0.0 h1:78BIzd4lHibdRNOKdMwKCnnsgYLW9SeotqU+nMhWSSo=
github.com/haxii/socks5 v1.0.0/go.mod h1:6O9Ba2yrLlvuSe/L1e84eZI8cPw6H+q1Ilr4hjgm4uY=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-tty v0.0.4 h1:NVikla9X8MN0SQAqCYzpGyXv0jY7MNl3HOWD2dkle7E=
github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28=
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
github.com/panjf2000/ants/v2 v2.5.0 h1:1rWGWSnxCsQBga+nQbA4/iY6VMeNoOIAM0ZWh9u3q2Q=
github.com/panjf2000/ants/v2 v2.5.0/go.mod h1:cU93usDlihJZ5CfRGNDYsiBYvoilLvBF5Qp/BT2GNRE=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yunginnanet/Rate5 v1.0.1 h1:OePwNrj9/A/flmhyr/gKI5RYgrW6d1oWCqrZRXUev3k=
github.com/yunginnanet/Rate5 v1.0.1/go.mod h1:f0r66kVQZojRqUgVdLC/CKexMlF0nUDAmd01tBeF4Ms=
go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE=
go4.org/intern v0.0.0-20211027215823-ae77deb06f29/go.mod h1:cS2ma+47FKrLPdXFpr7CuxiTW3eyJbWew4qx0qtQWDA=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 h1:FyBZqvoA/jbNzuAWLQE2kG820zMAkcilx6BMjGbL/E4=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220630215102-69896b714898 h1:K7wO6V1IrczY9QOQ2WkVpw4JQSwCd52UsxVEirZUfiw=
golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 h1:BonxutuHCTL0rBDnZlKjpGIQFTjyUVTexFOdWkB6Fg0=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo=
h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck=
inet.af/netaddr v0.0.0-20220617031823-097006376321 h1:B4dC8ySKTQXasnjDTMsoCMf1sQG4WsMej0WXaHxunmU=
inet.af/netaddr v0.0.0-20220617031823-097006376321/go.mod h1:OIezDfdzOgFhuw4HuWapWq2e9l0H9tK4F1j+ETRtF3k=
nullprogram.com/x/rng v1.1.0 h1:SMU7DHaQSWtKJNTpNFIFt8Wd/KSmOuSDPXrMFp/UMro=
nullprogram.com/x/rng v1.1.0/go.mod h1:glGw6V87vyfawxCzqOABL3WfL95G65az9Z2JZCylCkg=

@ -6,20 +6,47 @@ import (
"strconv"
"time"
"github.com/mattn/go-tty"
"git.tcp.direct/kayos/prox5"
"github.com/haxii/socks5"
"github.com/mattn/go-tty"
)
var swamp *prox5.ProxyEngine
var quit chan bool
var t *tty.TTY
var (
swamp *prox5.ProxyEngine
quit chan bool
t *tty.TTY
)
type socksLogger struct{}
var socklog = socksLogger{}
// Printf is used to handle socks server logging.
func (s socksLogger) Printf(format string, a ...interface{}) {
println(fmt.Sprintf(format, a))
}
func StartUpstreamProxy(listen string) {
conf := &socks5.Config{Dial: swamp.DialContext, Logger: socklog}
server, err := socks5.New(conf)
if err != nil {
println(err.Error())
return
}
socklog.Printf("starting proxy server on %s", listen)
if err := server.ListenAndServe("tcp", listen); err != nil {
println(err.Error())
return
}
}
func init() {
quit = make(chan bool)
swamp = prox5.NewProxyEngine()
swamp.SetMaxWorkers(5)
swamp.EnableDebug()
go StartUpstreamProxy("127.0.0.1:1555")
count := swamp.LoadProxyTXT(os.Args[1])
if count < 1 {

@ -2,6 +2,7 @@ package prox5
import (
"strconv"
"strings"
"sync/atomic"
"time"
@ -13,6 +14,30 @@ func (sock *Proxy) GetProto() ProxyProtocol {
return sock.proto
}
// GetProto safely retrieves the protocol value of the Proxy.
func (sock *Proxy) String() string {
tout := ""
if sock.parent.GetServerTimeoutStr() != "-1" {
tbuf := copABuffer.Get().(*strings.Builder)
tbuf.WriteString("?timeout=")
tbuf.WriteString(sock.parent.GetServerTimeoutStr())
tbuf.WriteString("s")
tout = tbuf.String()
discardBuffer(tbuf)
}
buf := copABuffer.Get().(*strings.Builder)
buf.WriteString("socks")
buf.WriteString(getProtoStr(sock.GetProto()))
buf.WriteString("://")
buf.WriteString(sock.Endpoint)
if tout != "" {
buf.WriteString(tout)
}
out := buf.String()
discardBuffer(buf)
return out
}
// GetStatistics returns all current statistics.
// * This is a pointer, do not modify it!
func (pe *ProxyEngine) GetStatistics() *statistics {

6
go.mod

@ -3,9 +3,8 @@ module git.tcp.direct/kayos/prox5
go 1.18
require (
git.tcp.direct/kayos/common v0.6.0
git.tcp.direct/kayos/common v0.7.0
git.tcp.direct/kayos/go-socks5 v1.0.1
github.com/mattn/go-tty v0.0.4
github.com/miekg/dns v1.1.50
github.com/panjf2000/ants/v2 v2.5.0
github.com/yunginnanet/Rate5 v1.0.1
@ -14,13 +13,12 @@ require (
)
require (
github.com/mattn/go-isatty v0.0.10 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect
go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 // indirect
golang.org/x/mod v0.4.2 // indirect
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 // indirect
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
nullprogram.com/x/rng v1.1.0 // indirect

18
go.sum

@ -1,18 +1,11 @@
git.tcp.direct/kayos/common v0.6.0 h1:x3qXJxGalhv3y4bX191Lx8R73Se1UzPgAP3fL2gqhyA=
git.tcp.direct/kayos/common v0.6.0/go.mod h1:jG1yXbN+5PrRZwGe32qIGWgLC4x5JWdyNBbMj1gIWB0=
git.tcp.direct/kayos/common v0.7.0 h1:KZDwoCzUiwQaYSWESr080N8wUVyLD27QYgzXgc7LiAQ=
git.tcp.direct/kayos/common v0.7.0/go.mod h1:7tMZBVNPLFSZk+JXTA6pgXWpf/XHqYRfT7Q3OziI++Y=
git.tcp.direct/kayos/go-socks5 v1.0.1 h1:Pe9PlSXofibIJyWkrr9rwWcgyfUxSdUcDCQ//6fAi0U=
git.tcp.direct/kayos/go-socks5 v1.0.1/go.mod h1:I9xU/uzFAZKukMJgEgWPrfC6rDlcPQe8wXMibF3qvhE=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364 h1:5XxdakFhqd9dnXoAZy1Mb2R/DZ6D1e+0bGC/JhucGYI=
github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364/go.mod h1:eDJQioIyy4Yn3MVivT7rv/39gAJTrA7lgmYr8EW950c=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-tty v0.0.4 h1:NVikla9X8MN0SQAqCYzpGyXv0jY7MNl3HOWD2dkle7E=
github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28=
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
github.com/panjf2000/ants/v2 v2.5.0 h1:1rWGWSnxCsQBga+nQbA4/iY6VMeNoOIAM0ZWh9u3q2Q=
@ -49,10 +42,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -60,8 +50,8 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=

@ -96,19 +96,19 @@ func (pe *ProxyEngine) filter(in string) (filtered string, ok bool) {
func (pe *ProxyEngine) LoadProxyTXT(seedFile string) (count int) {
f, err := os.Open(seedFile)
if err != nil {
pe.dbgPrint(err.Error())
pe.dbgPrint(simpleString(err.Error()))
return 0
}
defer func() {
if err := f.Close(); err != nil {
pe.dbgPrint(err.Error())
pe.dbgPrint(simpleString(err.Error()))
}
}()
bs, err := io.ReadAll(f)
if err != nil {
pe.dbgPrint(err.Error())
pe.dbgPrint(simpleString(err.Error()))
return 0
}
sockstr := string(bs)

@ -2,22 +2,43 @@ package prox5
import (
"context"
"errors"
"fmt"
"net"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
"h12.io/socks"
)
// DialContext is a simple stub adapter to implement a net.Dialer.
func (s *ProxyEngine) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
return s.MysteryDialer(ctx, network, addr)
var copABuffer = &sync.Pool{New: func() interface{} { return &strings.Builder{} }}
func discardBuffer(buf *strings.Builder) {
buf.Reset()
copABuffer.Put(buf)
}
// DialContext is a simple stub adapter to implement a net.Dialer.
func (s *ProxyEngine) Dial(network, addr string) (net.Conn, error) {
return s.DialContext(context.Background(), network, addr)
func (pe *ProxyEngine) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
return pe.MysteryDialer(ctx, network, addr)
}
// Dial is a simple stub adapter to implement a net.Dialer.
func (pe *ProxyEngine) Dial(network, addr string) (net.Conn, error) {
return pe.MysteryDialer(context.Background(), network, addr)
}
// DialTimeout is a simple stub adapter to implement a net.Dialer with a timeout.
func (pe *ProxyEngine) DialTimeout(network, addr string, timeout time.Duration) (net.Conn, error) {
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(timeout))
go func() {
select {
case <-ctx.Done():
cancel()
}
}()
return pe.MysteryDialer(ctx, network, addr)
}
// MysteryDialer is a dialer function that will use a different proxy for every request.
@ -27,31 +48,60 @@ func (pe *ProxyEngine) MysteryDialer(ctx context.Context, network, addr string)
count int
)
// pull down proxies from channel until we get a proxy good enough for our spoiled asses
for {
max := pe.GetDialerBailout()
if count > max {
return nil, errors.New("giving up after " + strconv.Itoa(max) + " tries")
return nil, fmt.Errorf("giving up after %d tries", max)
}
if err := ctx.Err(); err != nil {
return nil, err
return nil, fmt.Errorf("context error: %v", err)
}
var sock *Proxy
popSockAndLockIt:
for {
sock = pe.GetAnySOCKS(false)
if !atomic.CompareAndSwapUint32(&sock.lock, stateUnlocked, stateLocked) {
continue
socksString = sock.String()
select {
case <-ctx.Done():
return nil, fmt.Errorf("context done: %v", ctx.Err())
default:
buf := copABuffer.Get().(*strings.Builder)
if atomic.CompareAndSwapUint32(&sock.lock, stateUnlocked, stateLocked) {
buf.WriteString("got lock for ")
buf.WriteString(socksString)
break popSockAndLockIt
}
select {
case pe.Pending <- sock:
buf.WriteString("can't get lock, putting back ")
buf.WriteString(socksString)
pe.dbgPrint(buf)
continue
default:
buf.WriteString("can't get lock, can't put back ")
buf.WriteString(socksString)
continue
}
}
break
}
pe.dbgPrint("dialer trying: " + sock.Endpoint + "...")
tout := ""
buf := copABuffer.Get().(*strings.Builder)
buf.WriteString("try dial with: ")
buf.WriteString(sock.Endpoint)
pe.dbgPrint(buf)
if pe.GetServerTimeoutStr() != "-1" {
tout = "?timeout=" + pe.GetServerTimeoutStr() + "s"
tout := copABuffer.Get().(*strings.Builder)
tout.WriteString("?timeout=")
tout.WriteString(pe.GetServerTimeoutStr())
tout.WriteRune('s')
}
socksString = "socks" + getProtoStr(sock.proto) + "://" + sock.Endpoint + tout
var ok bool
if sock, ok = pe.dispenseMiddleware(sock); !ok {
pe.dbgPrint("failed middleware check, " + socksString + ", cycling...")
buf := copABuffer.Get().(*strings.Builder)
buf.WriteString("failed middleware check, ")
buf.WriteString(sock.String())
buf.WriteString(", cycling...")
pe.dbgPrint(buf)
continue
}
atomic.StoreUint32(&sock.lock, stateUnlocked)
@ -59,10 +109,17 @@ func (pe *ProxyEngine) MysteryDialer(ctx context.Context, network, addr string)
conn, err := dialSocks(network, addr)
if err != nil {
count++
pe.dbgPrint("unable to reach [redacted] with " + socksString + ", cycling...")
buf := copABuffer.Get().(*strings.Builder)
buf.WriteString("unable to reach [redacted] with ")
buf.WriteString(socksString)
buf.WriteString(", cycling...")
pe.dbgPrint(buf)
continue
}
pe.dbgPrint("MysteryDialer using socks: " + socksString)
buf = copABuffer.Get().(*strings.Builder)
buf.WriteString("MysteryDialer using socks: ")
buf.WriteString(socksString)
pe.dbgPrint(buf)
return conn, nil
}
}

@ -2,8 +2,8 @@ package prox5
import (
"fmt"
"git.tcp.direct/kayos/go-socks5"
"strings"
)
type socksLogger struct {
@ -12,7 +12,9 @@ type socksLogger struct {
// Printf is used to handle socks server logging.
func (s socksLogger) Printf(format string, a ...interface{}) {
s.parent.dbgPrint(fmt.Sprintf(format, a...))
buf := copABuffer.Get().(*strings.Builder)
buf.WriteString(fmt.Sprintf(format, a...))
s.parent.dbgPrint(buf)
}
type socksCreds struct {
@ -40,7 +42,10 @@ func (pe *ProxyEngine) StartSOCKS5Server(listen, username, password string) erro
Dial: pe.MysteryDialer,
}
pe.dbgPrint("listening for SOCKS5 connections on " + listen)
buf := copABuffer.Get().(*strings.Builder)
buf.WriteString("listening for SOCKS5 connections on ")
buf.WriteString(listen)
pe.dbgPrint(buf)
server, err := socks5.New(conf)
if err != nil {

@ -156,7 +156,10 @@ func (sock *Proxy) validate() {
// determined as bad, won't try again until it expires from that cache
if s.badProx.Peek(sock) {
s.dbgPrint("badProx ratelimited: " + sock.Endpoint)
buf := copABuffer.Get().(*strings.Builder)
buf.WriteString("badProx ratelimited: ")
buf.WriteString(sock.Endpoint)
s.dbgPrint(buf)
return
}
@ -179,10 +182,18 @@ func (sock *Proxy) validate() {
switch sock.proto {
case ProtoSOCKS4, ProtoSOCKS4a, ProtoSOCKS5, ProtoHTTP:
s.dbgPrint("verified " + sock.Endpoint + " as SOCKS" + getProtoStr(sock.proto))
buf := copABuffer.Get().(*strings.Builder)
buf.WriteString("verified ")
buf.WriteString(sock.Endpoint)
buf.WriteString(" as SOCKS")
buf.WriteString(getProtoStr(sock.proto))
s.dbgPrint(buf)
break
default:
s.dbgPrint("failed to verify: " + sock.Endpoint)
buf := copABuffer.Get().(*strings.Builder)
buf.WriteString("failed to verify: ")
buf.WriteString(sock.Endpoint)
s.dbgPrint(buf)
sock.bad()
s.badProx.Check(sock)
return