Projects STRLCPY prox5 Commits 91fc4fc6
🤬
  • ■ ■ ■ ■
    daemons.go
    skipped 34 lines
    35 35   
    36 36   sm.plot[sock] = &Proxy{
    37 37   Endpoint: sock,
    38  - proto: protoNULL,
     38 + protocol: newImmutableProto(),
    39 39   lastValidated: time.UnixMilli(0),
    40 40   timesValidated: 0,
    41 41   timesBad: 0,
    skipped 129 lines
  • ■ ■ ■ ■ ■ ■
    debug.go
    skipped 160 lines
    161 161   if success {
    162 162   buf.WriteString("verified ")
    163 163   buf.WriteString(sock.Endpoint)
    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  - }
    171  - buf.WriteString(getProtoStr(sock.proto))
     164 + buf.WriteString(" as ")
     165 + buf.WriteString(sock.protocol.Get().String())
     166 + buf.WriteString(" proxy")
    172 167   pe.dbgPrint(buf)
    173 168   return
    174 169   }
    skipped 15 lines
  • ■ ■ ■ ■ ■ ■
    getters.go
    skipped 1 lines
    2 2   
    3 3  import (
    4 4   "strconv"
    5  - "strings"
    6 5   "sync/atomic"
    7 6   "time"
    8 7   
    9 8   "git.tcp.direct/kayos/common/entropy"
    10  - 
    11  - "git.tcp.direct/kayos/prox5/internal/pools"
    12 9  )
    13  - 
    14  -// GetProto retrieves the known protocol value of the Proxy.
    15  -func (sock *Proxy) GetProto() ProxyProtocol {
    16  - return sock.proto
    17  -}
    18  - 
    19  -// GetProto safely retrieves the protocol value of the Proxy.
    20  -func (sock *Proxy) String() string {
    21  - tout := ""
    22  - if sock.parent.GetServerTimeoutStr() != "-1" {
    23  - tbuf := pools.CopABuffer.Get().(*strings.Builder)
    24  - tbuf.WriteString("?timeout=")
    25  - tbuf.WriteString(sock.parent.GetServerTimeoutStr())
    26  - tbuf.WriteString("s")
    27  - tout = tbuf.String()
    28  - pools.DiscardBuffer(tbuf)
    29  - }
    30  - buf := pools.CopABuffer.Get().(*strings.Builder)
    31  - buf.WriteString("socks")
    32  - buf.WriteString(getProtoStr(sock.GetProto()))
    33  - buf.WriteString("://")
    34  - buf.WriteString(sock.Endpoint)
    35  - if tout != "" {
    36  - buf.WriteString(tout)
    37  - }
    38  - out := buf.String()
    39  - pools.DiscardBuffer(buf)
    40  - return out
    41  -}
    42 10   
    43 11  // GetStatistics returns all current statistics.
    44 12  // * This is a pointer, do not modify it!
    skipped 115 lines
  • ■ ■ ■ ■ ■
    go.mod
    skipped 8 lines
    9 9   github.com/haxii/socks5 v1.0.0
    10 10   github.com/mattn/go-tty v0.0.4
    11 11   github.com/miekg/dns v1.1.50
     12 + github.com/ooni/oohttp v0.3.0
    12 13   github.com/panjf2000/ants/v2 v2.5.0
     14 + github.com/refraction-networking/utls v1.1.2
    13 15   github.com/yunginnanet/Rate5 v1.0.1
    14  - golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985
     16 + golang.org/x/net v0.0.0-20220812174116-3211cb980234
    15 17   inet.af/netaddr v0.0.0-20220617031823-097006376321
    16 18  )
    17 19   
    18 20  require (
     21 + github.com/andybalholm/brotli v1.0.4 // indirect
     22 + github.com/klauspost/compress v1.13.6 // indirect
    19 23   github.com/mattn/go-isatty v0.0.14 // indirect
    20 24   github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
    21 25   go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect
    22 26   go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 // indirect
     27 + golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9 // indirect
    23 28   golang.org/x/mod v0.4.2 // indirect
    24  - golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
     29 + golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
     30 + golang.org/x/text v0.3.7 // indirect
    25 31   golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect
    26 32   golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
    27 33   nullprogram.com/x/rng v1.1.0 // indirect
    skipped 2 lines
  • ■ ■ ■ ■ ■
    go.sum
    skipped 3 lines
    4 4  git.tcp.direct/kayos/go-socks5 v1.0.1/go.mod h1:I9xU/uzFAZKukMJgEgWPrfC6rDlcPQe8wXMibF3qvhE=
    5 5  git.tcp.direct/kayos/socks v0.0.0-20220828111753-f9f7cd3e7ee7 h1:zuN2VWun3lu34Lz+LAt/ZbY6YJ0SqzQf2d00YQUfNao=
    6 6  git.tcp.direct/kayos/socks v0.0.0-20220828111753-f9f7cd3e7ee7/go.mod h1:KmN5oa1od8tMHmRIr9GOqWKx9MR0oGZVtAj+ARxiPwo=
     7 +github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
     8 +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
    7 9  github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
    8 10  github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
    9 11  github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364 h1:5XxdakFhqd9dnXoAZy1Mb2R/DZ6D1e+0bGC/JhucGYI=
    10 12  github.com/haxii/socks5 v1.0.0 h1:78BIzd4lHibdRNOKdMwKCnnsgYLW9SeotqU+nMhWSSo=
    11 13  github.com/haxii/socks5 v1.0.0/go.mod h1:6O9Ba2yrLlvuSe/L1e84eZI8cPw6H+q1Ilr4hjgm4uY=
     14 +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
     15 +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
    12 16  github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
    13 17  github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
    14 18  github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
    skipped 4 lines
    19 23  github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28=
    20 24  github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
    21 25  github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
     26 +github.com/ooni/oohttp v0.3.0 h1:75OsZKelkLXl6p2UD53dTJyIv+9owWqaL6sMT26LN8w=
     27 +github.com/ooni/oohttp v0.3.0/go.mod h1:fgNDPYw+nsgEKCDBpT/4R06bgnrCRtvgNmAWOCmm4JE=
    22 28  github.com/panjf2000/ants/v2 v2.5.0 h1:1rWGWSnxCsQBga+nQbA4/iY6VMeNoOIAM0ZWh9u3q2Q=
    23 29  github.com/panjf2000/ants/v2 v2.5.0/go.mod h1:cU93usDlihJZ5CfRGNDYsiBYvoilLvBF5Qp/BT2GNRE=
    24 30  github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
    25 31  github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
    26 32  github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
    27 33  github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
     34 +github.com/refraction-networking/utls v1.1.2 h1:a7GQauRt72VG+wtNm0lnrAaCGlyX47gEi1++dSsDBpw=
     35 +github.com/refraction-networking/utls v1.1.2/go.mod h1:+D89TUtA8+NKVFj1IXWr0p3tSdX1+SqUB7rL0QnGqyg=
    28 36  github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
    29 37  github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
    30 38  github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
    skipped 7 lines
    38 46  golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
    39 47  golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
    40 48  golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
     49 +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
     50 +golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9 h1:NUzdAbFtCJSXU20AOXgeqaUwg8Ypg4MPYmL+d+rsB5c=
     51 +golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
    41 52  golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
    42 53  golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
    43 54  golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
    44 55  golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
    45 56  golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
    46 57  golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
     58 +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
    47 59  golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
    48  -golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8=
    49 60  golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
     61 +golang.org/x/net v0.0.0-20211111160137-58aab5ef257a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
     62 +golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E=
     63 +golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
    50 64  golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    51 65  golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    52 66  golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
    skipped 9 lines
    62 76  golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    63 77  golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    64 78  golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
     79 +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
    65 80  golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
    66  -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo=
    67  -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
     81 +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
     82 +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
    68 83  golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
    69 84  golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
    70 85  golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
    71 86  golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
     87 +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
     88 +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
    72 89  golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
    73 90  golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
    74 91  golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
    skipped 12 lines
  • ■ ■ ■ ■ ■ ■
    internal/randtls/shim.go
     1 +package randtls
     2 + 
     3 +import (
     4 + "context"
     5 + "crypto/tls"
     6 + "net"
     7 + 
     8 + uhttp "github.com/ooni/oohttp"
     9 + utls "github.com/refraction-networking/utls"
     10 +)
     11 + 
     12 +// See: https://github.com/ooni/oohttp/blob/main/example/example-utls/tls.go
     13 + 
     14 +type adapter struct {
     15 + *utls.UConn
     16 + conn net.Conn
     17 +}
     18 + 
     19 +// Asserts that we follow the interface.
     20 +var _ uhttp.TLSConn = &adapter{}
     21 + 
     22 +// ConnectionState implements the tls.ConnectionState interface.
     23 +func (c *adapter) ConnectionState() tls.ConnectionState {
     24 + ustate := c.UConn.ConnectionState()
     25 + return tls.ConnectionState{
     26 + Version: ustate.Version,
     27 + HandshakeComplete: ustate.HandshakeComplete,
     28 + DidResume: ustate.DidResume,
     29 + CipherSuite: ustate.CipherSuite,
     30 + NegotiatedProtocol: ustate.NegotiatedProtocol,
     31 + NegotiatedProtocolIsMutual: ustate.NegotiatedProtocolIsMutual,
     32 + ServerName: ustate.ServerName,
     33 + PeerCertificates: ustate.PeerCertificates,
     34 + VerifiedChains: ustate.VerifiedChains,
     35 + SignedCertificateTimestamps: ustate.SignedCertificateTimestamps,
     36 + OCSPResponse: ustate.OCSPResponse,
     37 + TLSUnique: ustate.TLSUnique,
     38 + }
     39 +}
     40 + 
     41 +// HandshakeContext implements TLSConn's HandshakeContext.
     42 +func (c *adapter) HandshakeContext(ctx context.Context) error {
     43 + errch := make(chan error, 1)
     44 + go func() {
     45 + errch <- c.UConn.Handshake()
     46 + }()
     47 + select {
     48 + case err := <-errch:
     49 + return err
     50 + case <-ctx.Done():
     51 + return ctx.Err()
     52 + }
     53 +}
     54 + 
     55 +// NetConn implements TLSConn's NetConn
     56 +func (c *adapter) NetConn() net.Conn {
     57 + return c.conn
     58 +}
     59 + 
     60 +// utlsFactory creates a new uTLS connection.
     61 +func utlsFactory(conn net.Conn, config *tls.Config) uhttp.TLSConn {
     62 + uConfig := &utls.Config{
     63 + RootCAs: config.RootCAs,
     64 + NextProtos: config.NextProtos,
     65 + ServerName: config.ServerName,
     66 + InsecureSkipVerify: config.InsecureSkipVerify,
     67 + DynamicRecordSizingDisabled: config.DynamicRecordSizingDisabled,
     68 + }
     69 + return &adapter{
     70 + UConn: utls.UClient(conn, uConfig, utls.HelloFirefox_55),
     71 + conn: conn,
     72 + }
     73 +}
     74 + 
  • ■ ■ ■ ■ ■ ■
    proto.go
     1 +package prox5
     2 + 
     3 +import (
     4 + "strings"
     5 + "sync"
     6 + "sync/atomic"
     7 +)
     8 + 
     9 +type ProxyProtocol int8
     10 + 
     11 +const (
     12 + // ProtoNull is a null value for ProxyProtocol.
     13 + ProtoNull ProxyProtocol = iota
     14 + ProtoSOCKS4
     15 + ProtoSOCKS4a
     16 + ProtoSOCKS5
     17 + ProtoHTTP
     18 +)
     19 + 
     20 +var protoMap = map[ProxyProtocol]string{
     21 + ProtoSOCKS5: "socks5", ProtoNull: "", ProtoSOCKS4: "socks4", ProtoSOCKS4a: "socks4a",
     22 +}
     23 + 
     24 +func (p ProxyProtocol) String() string {
     25 + return protoMap[p]
     26 +}
     27 + 
     28 +type proto struct {
     29 + proto *atomic.Value
     30 + // immutable
     31 + *sync.Once
     32 +}
     33 + 
     34 +func newImmutableProto() proto {
     35 + p := proto{
     36 + proto: &atomic.Value{},
     37 + Once: &sync.Once{},
     38 + }
     39 + p.proto.Store(ProtoNull)
     40 + return p
     41 +}
     42 + 
     43 +func (p *proto) Get() ProxyProtocol {
     44 + return p.proto.Load().(ProxyProtocol)
     45 +}
     46 + 
     47 +func (p *proto) set(proxyproto ProxyProtocol) {
     48 + p.Do(func() {
     49 + p.proto.Store(proxyproto)
     50 + })
     51 +}
     52 + 
     53 +func (p ProxyProtocol) writeProtoString(builder *strings.Builder) {
     54 + builder.WriteString(p.String())
     55 +}
     56 + 
     57 +func (p ProxyProtocol) writeProtoURI(builder *strings.Builder) {
     58 + p.writeProtoString(builder)
     59 + builder.WriteString("://")
     60 +}
     61 + 
  • ■ ■ ■ ■ ■ ■
    proxy.go
    1 1  package prox5
    2 2   
    3 3  import (
     4 + "strings"
    4 5   "time"
    5 6   
    6 7   rl "github.com/yunginnanet/Rate5"
     8 + 
     9 + "git.tcp.direct/kayos/prox5/internal/pools"
    7 10  )
    8 11   
    9 12  // https://pkg.go.dev/github.com/yunginnanet/Rate5#Policy
    skipped 12 lines
    22 25   stateLocked
    23 26  )
    24 27   
    25  -type ProxyProtocol uint8
    26  - 
    27  -const (
    28  - protoNULL ProxyProtocol = iota
    29  - ProtoSOCKS4
    30  - ProtoSOCKS4a
    31  - ProtoSOCKS5
    32  - ProtoSOCKS5h
    33  - ProtoHTTP
    34  -)
    35  - 
    36 28  // Proxy represents an individual proxy
    37 29  type Proxy struct {
    38 30   // Endpoint is the address:port of the proxy that we connect to
    39 31   Endpoint string
    40 32   // ProxiedIP is the address that we end up having when making proxied requests through this proxy
    41 33   ProxiedIP string
    42  - // proto is the version/Protocol (currently SOCKS* only) of the proxy
    43  - proto ProxyProtocol
     34 + // protocol is the version/Protocol (currently SOCKS* only) of the proxy
     35 + protocol proto
    44 36   // lastValidated is the time this proxy was last verified working
    45 37   lastValidated time.Time
    46 38   // timesValidated is the amount of times the proxy has been validated.
    skipped 11 lines
    58 50   return sock.Endpoint
    59 51  }
    60 52   
     53 +// GetProto retrieves the known protocol value of the Proxy.
     54 +func (sock *Proxy) GetProto() ProxyProtocol {
     55 + return sock.protocol.Get()
     56 +}
     57 + 
     58 +// GetProto safely retrieves the protocol value of the Proxy.
     59 +func (sock *Proxy) String() string {
     60 + tout := ""
     61 + if sock.parent.GetServerTimeoutStr() != "-1" {
     62 + tbuf := pools.CopABuffer.Get().(*strings.Builder)
     63 + tbuf.WriteString("?timeout=")
     64 + tbuf.WriteString(sock.parent.GetServerTimeoutStr())
     65 + tbuf.WriteString("s")
     66 + tout = tbuf.String()
     67 + pools.DiscardBuffer(tbuf)
     68 + }
     69 + buf := pools.CopABuffer.Get().(*strings.Builder)
     70 + buf.WriteString(sock.GetProto().String())
     71 + buf.WriteString("://")
     72 + buf.WriteString(sock.Endpoint)
     73 + if tout != "" {
     74 + buf.WriteString(tout)
     75 + }
     76 + out := buf.String()
     77 + pools.DiscardBuffer(buf)
     78 + return out
     79 +}
     80 + 
  • ■ ■ ■ ■ ■ ■
    validator_engine.go
    skipped 52 lines
    53 53   
    54 54  func (pe *ProxyEngine) bakeHTTP(hmd *HandMeDown) (client *http.Client, req *http.Request, err error) {
    55 55   builder := pools.CopABuffer.Get().(*strings.Builder)
    56  - builder.WriteString("socks")
    57  - builder.WriteString(getProtoStr(hmd.sock.proto))
     56 + builder.WriteString(hmd.protoCheck.String())
    58 57   builder.WriteString("://")
    59 58   builder.WriteString(hmd.sock.Endpoint)
    60 59   builder.WriteString("/?timeout=")
    61 60   builder.WriteString(pe.GetValidationTimeoutStr())
    62 61   builder.WriteString("s")
    63  - 
    64 62   dialSocks := socks.DialWithConn(builder.String(), hmd.conn)
    65 63   pools.DiscardBuffer(builder)
    66 64   
    skipped 6 lines
    73 71   return
    74 72   }
    75 73   
    76  - if hmd.sock.proto != ProtoHTTP {
     74 + if hmd.protoCheck != ProtoHTTP {
    77 75   transport.Dial = dialSocks
    78 76   client.Transport = transport
    79 77   return
    skipped 32 lines
    112 110  }
    113 111   
    114 112  type HandMeDown struct {
    115  - sock *Proxy
    116  - conn net.Conn
    117  - under proxy.Dialer
     113 + sock *Proxy
     114 + protoCheck ProxyProtocol
     115 + conn net.Conn
     116 + under proxy.Dialer
    118 117  }
    119 118   
    120 119  func (hmd *HandMeDown) Dial(network, addr string) (c net.Conn, err error) {
    skipped 6 lines
    127 126   return hmd.conn, nil
    128 127  }
    129 128   
    130  -func (pe *ProxyEngine) singleProxyCheck(sock *Proxy) error {
     129 +func (pe *ProxyEngine) singleProxyCheck(sock *Proxy, protocol ProxyProtocol) error {
    131 130   defer pe.anothaOne()
    132 131   split := strings.Split(sock.Endpoint, "@")
    133 132   endpoint := split[0]
    skipped 5 lines
    139 138   return err
    140 139   }
    141 140   
    142  - hmd := &HandMeDown{sock: sock, conn: conn, under: proxy.Direct}
     141 + hmd := &HandMeDown{sock: sock, conn: conn, under: proxy.Direct, protoCheck: protocol}
    143 142   
    144 143   resp, err := pe.validate(hmd)
    145 144   if err != nil {
    skipped 11 lines
    157 156   return nil
    158 157  }
    159 158   
    160  -var protoMap = map[ProxyProtocol]string{
    161  - ProtoSOCKS4: "4", ProtoSOCKS4a: "4a",
    162  - ProtoSOCKS5: "5", ProtoHTTP: "http",
    163  - ProtoSOCKS5h: "5h", protoNULL: "null",
    164  -}
    165  - 
    166  -func getProtoStr(protocol ProxyProtocol) string {
    167  - if str, ok := protoMap[protocol]; ok {
    168  - return str
    169  - }
    170  - panic(protoMap[protocol])
    171  -}
    172  - 
    173 159  func (sock *Proxy) validate() {
    174 160   if !atomic.CompareAndSwapUint32(&sock.lock, stateUnlocked, stateLocked) {
    175 161   return
    skipped 14 lines
    190 176   
    191 177   // TODO: consider giving the option for verbose logging of this stuff?
    192 178   
    193  - if sock.timesValidated == 0 || sock.proto == protoNULL {
     179 + if sock.timesValidated == 0 || sock.protocol.Get() == ProtoNull {
    194 180   // try to use the proxy with all 3 SOCKS versions
    195  - for proto := range protoMap {
     181 + for tryProto := range protoMap {
    196 182   select {
    197 183   case <-pe.ctx.Done():
    198 184   return
    199 185   default:
    200  - sock.proto = proto
    201  - if err := pe.singleProxyCheck(sock); err != nil {
     186 + if err := pe.singleProxyCheck(sock, tryProto); err != nil {
    202 187   // if the proxy is no good, we continue on to the next.
    203 188   continue
    204 189   }
     190 + sock.protocol.set(tryProto)
    205 191   break
    206 192   }
    207 193   }
    208 194   } else {
    209  - if err := pe.singleProxyCheck(sock); err != nil {
     195 + if err := pe.singleProxyCheck(sock, sock.GetProto()); err != nil {
    210 196   sock.bad()
    211 197   pe.badProx.Check(sock)
    212 198   return
    213 199   }
    214 200   }
    215 201   
    216  - switch sock.proto {
     202 + switch sock.protocol.Get() {
    217 203   case ProtoSOCKS4, ProtoSOCKS4a, ProtoSOCKS5, ProtoHTTP:
    218 204   pe.msgChecked(sock, true)
    219 205   default:
    skipped 8 lines
    228 214  }
    229 215   
    230 216  func (pe *ProxyEngine) tally(sock *Proxy) {
    231  - switch sock.proto {
     217 + switch sock.protocol.Get() {
    232 218   case ProtoSOCKS4:
    233 219   pe.stats.v4()
    234 220   pe.Valids.SOCKS4 <- sock
    skipped 14 lines
Please wait...
Page is in error, reload to recover