From 417ac556f7d094cafdf8b8bdb1dcb735edb80a03 Mon Sep 17 00:00:00 2001 From: nadoo <287492+nadoo@users.noreply.github.com> Date: Tue, 3 Nov 2020 22:52:50 +0800 Subject: [PATCH] pool: added bufio.Reader pool --- README.md | 44 ++++++++++---------- dns/client.go | 4 +- go.mod | 6 +-- go.sum | 12 +++--- pool/bufreader.go | 24 +++++++++++ pool/bytesbuffer.go | 25 +++++++++++ pool/writebuf.go | 25 ----------- proxy/conn.go | 7 +++- proxy/http/client.go | 4 +- proxy/http/server.go | 9 ++-- proxy/obfs/http.go | 4 +- proxy/obfs/tls.go | 81 +++++++++++++++++------------------- proxy/server.go | 10 ++--- proxy/socks5/packet.go | 4 +- proxy/ss/packet.go | 4 +- proxy/ssr/internal/client.go | 8 ++-- proxy/ssr/ssr.go | 1 + proxy/tls/tls.go | 4 +- proxy/trojan/client.go | 4 +- proxy/trojan/packet.go | 4 +- proxy/trojan/server.go | 4 +- proxy/vless/client.go | 6 +-- proxy/vless/packet.go | 4 +- proxy/vless/server.go | 29 ++++--------- proxy/vmess/client.go | 4 +- proxy/ws/client.go | 10 +++-- proxy/ws/server.go | 10 +++-- proxy/ws/ws.go | 1 - systemd/glider@.service | 4 +- 29 files changed, 188 insertions(+), 168 deletions(-) create mode 100644 pool/bufreader.go create mode 100644 pool/bytesbuffer.go delete mode 100644 pool/writebuf.go diff --git a/README.md b/README.md index bb60456..e25f465 100644 --- a/README.md +++ b/README.md @@ -44,28 +44,28 @@ we can set up local listeners as proxy servers, and forward requests to internet click to see details |Protocol | Listen/TCP | Listen/UDP | Forward/TCP | Forward/UDP | Description -|:-: |:-:|:-:|:-:|:-:|:- -|mixed |√|√| | |http+socks5 server -|http |√| |√| |client & server -|socks5 |√|√|√|√|client & server -|ss |√|√|√|√|client & server -|trojan |√|√|√|√|client & server -|trojanc |√|√|√|√|trojan cleartext(without tls) -|vless |√|√|√|√|client & server -|vmess | | |√| |client only -|ssr | | |√| |client only -|ssh | | |√| |client only -|socks4 | | |√| |client only -|tls |√| |√| |transport client & server -|kcp | |√|√| |transport client & server -|unix |√| |√| |transport client & server -|websocket |√| |√| |transport client & server -|simple-obfs | | |√| |transport client only -|tcptun |√| | | |transport server only -|udptun | |√| | |transport server only -|redir |√| | | |linux only -|redir6 |√| | | |linux only(ipv6) -|reject | | |√|√|reject all requests +|:- |:-:|:-:|:-:|:-:|:- +|Mixed |√|√| | |http+socks5 server +|HTTP |√| |√| |client & server +|SOCKS5 |√|√|√|√|client & server +|SS |√|√|√|√|client & server +|Trojan |√|√|√|√|client & server +|Trojanc |√|√|√|√|trojan cleartext(without tls) +|VLESS |√|√|√|√|client & server +|VMess | | |√| |client only +|SSR | | |√| |client only +|SSH | | |√| |client only +|SOCKS4 | | |√| |client only +|TLS |√| |√| |transport client & server +|KCP | |√|√| |transport client & server +|Unix |√| |√| |transport client & server +|Websocket |√| |√| |transport client & server +|Simple-Obfs | | |√| |transport client only +|TCPTun |√| | | |transport server only +|UDPTun | |√| | |transport server only +|Redir |√| | | |linux only +|Redir6 |√| | | |linux only(ipv6) +|Reject | | |√|√|reject all requests diff --git a/dns/client.go b/dns/client.go index 375c46a..11ba922 100644 --- a/dns/client.go +++ b/dns/client.go @@ -278,8 +278,8 @@ func (c *Client) AddRecord(record string) error { return err } - wb := pool.GetWriteBuffer() - defer pool.PutWriteBuffer(wb) + wb := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(wb) _, err = m.MarshalTo(wb) if err != nil { diff --git a/go.mod b/go.mod index 14a9026..f0547e3 100644 --- a/go.mod +++ b/go.mod @@ -14,9 +14,9 @@ require ( github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/xtaci/kcp-go/v5 v5.6.1 golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 - golang.org/x/net v0.0.0-20201029055024-942e2f445f3c // indirect - golang.org/x/sys v0.0.0-20201029080932-201ba4db2418 // indirect - golang.org/x/tools v0.0.0-20201029135353-690a3c245f28 // indirect + golang.org/x/net v0.0.0-20201031054903-ff519b6c9102 // indirect + golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 // indirect + golang.org/x/tools v0.0.0-20201102212025-f46e4245211d // indirect gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect ) diff --git a/go.sum b/go.sum index ca9f3f8..473a446 100644 --- a/go.sum +++ b/go.sum @@ -97,8 +97,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201029055024-942e2f445f3c h1:rpcgRPA7OvNEOdprt2Wx8/Re2cBTd8NPo/lvo3AyMqk= -golang.org/x/net v0.0.0-20201029055024-942e2f445f3c/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102 h1:42cLlJJdEh+ySyeUUbEQ5bsTiq8voBeTuweGVkY6Puw= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -116,8 +116,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201029080932-201ba4db2418 h1:HlFl4V6pEMziuLXyRkm5BIYq1y1GAbb02pRlWvI54OM= -golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 h1:a/mKvvZr9Jcc8oKfcmgzyp7OwF73JPWsQLvH1z2Kxck= +golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -125,8 +125,8 @@ golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201029135353-690a3c245f28 h1:KmEPH4S/AVTMSlbgNWC4xKvfsqvw/dNDUo/bGDqbDdo= -golang.org/x/tools v0.0.0-20201029135353-690a3c245f28/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201102212025-f46e4245211d h1:qbdJV2Z36oENmeAcKxD4qJx1FRdKoCzNewsdABS63dY= +golang.org/x/tools v0.0.0-20201102212025-f46e4245211d/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/pool/bufreader.go b/pool/bufreader.go new file mode 100644 index 0000000..bd0cbc6 --- /dev/null +++ b/pool/bufreader.go @@ -0,0 +1,24 @@ +package pool + +import ( + "bufio" + "io" + "sync" +) + +var bufReaderPool sync.Pool + +// GetBufReader returns a *bufio.Reader from pool. +func GetBufReader(r io.Reader) *bufio.Reader { + if v := bufReaderPool.Get(); v != nil { + br := v.(*bufio.Reader) + br.Reset(r) + return br + } + return bufio.NewReader(r) +} + +// PutBufReader puts a *bufio.Reader into pool. +func PutBufReader(br *bufio.Reader) { + bufReaderPool.Put(br) +} diff --git a/pool/bytesbuffer.go b/pool/bytesbuffer.go new file mode 100644 index 0000000..f3895eb --- /dev/null +++ b/pool/bytesbuffer.go @@ -0,0 +1,25 @@ +package pool + +import ( + "bytes" + "sync" +) + +var bytesBufPool = sync.Pool{ + New: func() interface{} { return &bytes.Buffer{} }, +} + +// GetBytesBuffer returns a bytes.buffer from pool. +func GetBytesBuffer() *bytes.Buffer { + return bytesBufPool.Get().(*bytes.Buffer) +} + +// PutBytesBuffer puts a bytes.buffer into pool. +func PutBytesBuffer(buf *bytes.Buffer) { + if buf.Cap() > 64<<10 { + return + } + + buf.Reset() + bytesBufPool.Put(buf) +} diff --git a/pool/writebuf.go b/pool/writebuf.go deleted file mode 100644 index 8ba4289..0000000 --- a/pool/writebuf.go +++ /dev/null @@ -1,25 +0,0 @@ -package pool - -import ( - "bytes" - "sync" -) - -var writeBufPool = sync.Pool{ - New: func() interface{} { return &bytes.Buffer{} }, -} - -// GetWriteBuffer returns a bytes.buffer from pool. -func GetWriteBuffer() *bytes.Buffer { - return writeBufPool.Get().(*bytes.Buffer) -} - -// PutWriteBuffer puts a bytes.buffer into pool. -func PutWriteBuffer(buf *bytes.Buffer) { - if buf.Cap() > 64<<10 { - return - } - - buf.Reset() - writeBufPool.Put(buf) -} diff --git a/proxy/conn.go b/proxy/conn.go index f3a51ea..5bbdf05 100644 --- a/proxy/conn.go +++ b/proxy/conn.go @@ -32,7 +32,7 @@ func NewConn(c net.Conn) *Conn { if conn, ok := c.(*Conn); ok { return conn } - return &Conn{bufio.NewReader(c), c} + return &Conn{pool.GetBufReader(c), c} } // Reader returns the internal bufio.Reader. @@ -73,6 +73,11 @@ func Relay(left, right net.Conn) error { return nil } +func (c *Conn) Close() error { + pool.PutBufReader(c.r) + return c.Conn.Close() +} + // Copy copies from src to dst. func Copy(dst io.Writer, src io.Reader) (written int64, err error) { dst = underlyingWriter(dst) diff --git a/proxy/http/client.go b/proxy/http/client.go index 5a07039..a2011b1 100644 --- a/proxy/http/client.go +++ b/proxy/http/client.go @@ -32,7 +32,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, error) { return nil, err } - buf := pool.GetWriteBuffer() + buf := pool.GetBytesBuffer() buf.WriteString("CONNECT " + addr + " HTTP/1.1\r\n") buf.WriteString("Host: " + addr + "\r\n") buf.WriteString("Proxy-Connection: Keep-Alive\r\n") @@ -45,7 +45,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, error) { // header ended buf.WriteString("\r\n") _, err = rc.Write(buf.Bytes()) - pool.PutWriteBuffer(buf) + pool.PutBytesBuffer(buf) if err != nil { return nil, err } diff --git a/proxy/http/server.go b/proxy/http/server.go index 9d62fe7..6478d05 100644 --- a/proxy/http/server.go +++ b/proxy/http/server.go @@ -1,7 +1,6 @@ package http import ( - "bufio" "fmt" "io" "net" @@ -114,8 +113,8 @@ func (s *HTTP) servHTTP(req *request, c *proxy.Conn) { } defer rc.Close() - buf := pool.GetWriteBuffer() - defer pool.PutWriteBuffer(buf) + buf := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(buf) // send request to remote server req.WriteBuf(buf) @@ -133,7 +132,9 @@ func (s *HTTP) servHTTP(req *request, c *proxy.Conn) { } }() - r := bufio.NewReader(rc) + r := pool.GetBufReader(rc) + defer pool.PutBufReader(r) + tpr := textproto.NewReader(r) line, err := tpr.ReadLine() if err != nil { diff --git a/proxy/obfs/http.go b/proxy/obfs/http.go index 9d5eb26..6f8388c 100644 --- a/proxy/obfs/http.go +++ b/proxy/obfs/http.go @@ -43,8 +43,8 @@ func (p *HTTPObfs) NewConn(c net.Conn) (net.Conn, error) { } func (c *HTTPObfsConn) writeHeader() (int, error) { - buf := pool.GetWriteBuffer() - defer pool.PutWriteBuffer(buf) + buf := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(buf) buf.WriteString("GET " + c.obfsURI + " HTTP/1.1\r\n") buf.WriteString("Host: " + c.obfsHost + "\r\n") diff --git a/proxy/obfs/tls.go b/proxy/obfs/tls.go index d443ae6..e436518 100644 --- a/proxy/obfs/tls.go +++ b/proxy/obfs/tls.go @@ -42,18 +42,13 @@ type TLSObfsConn struct { net.Conn reqSent bool reader *bufio.Reader - buf []byte + buf [lenSize]byte leftBytes int } // NewConn returns a new obfs connection func (p *TLSObfs) NewConn(c net.Conn) (net.Conn, error) { - cc := &TLSObfsConn{ - Conn: c, - TLSObfs: p, - buf: make([]byte, lenSize), - } - + cc := &TLSObfsConn{Conn: c, TLSObfs: p} return cc, nil } @@ -63,8 +58,8 @@ func (c *TLSObfsConn) Write(b []byte) (int, error) { return c.handshake(b) } - buf := pool.GetWriteBuffer() - defer pool.PutWriteBuffer(buf) + buf := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(buf) n := len(b) for i := 0; i < n; i += chunkSize { @@ -128,10 +123,18 @@ func (c *TLSObfsConn) Read(b []byte) (int, error) { } func (c *TLSObfsConn) handshake(b []byte) (int, error) { - buf := pool.GetWriteBuffer() + buf := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(buf) + + bufExt := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(bufExt) + + bufHello := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(bufHello) // prepare extension & clientHello content - bufExt, bufHello := extension(b, c.obfsHost), clientHello() + extension(b, c.obfsHost, bufExt) + clientHello(bufHello) // prepare lengths extLen := bufExt.Len() @@ -166,7 +169,7 @@ func (c *TLSObfsConn) handshake(b []byte) (int, error) { buf.Write(bufExt.Bytes()) _, err := c.Conn.Write(buf.Bytes()) - pool.PutWriteBuffer(buf) + if err != nil { return 0, err } @@ -174,9 +177,7 @@ func (c *TLSObfsConn) handshake(b []byte) (int, error) { return len(b), nil } -func clientHello() *bytes.Buffer { - var buf bytes.Buffer - +func clientHello(buf *bytes.Buffer) { // Version: TLS 1.2 (0x0303) buf.Write([]byte{0x03, 0x03}) @@ -187,7 +188,7 @@ func clientHello() *bytes.Buffer { // clients do not send current time, and server do not check it, // golang tls client and chrome browser send random bytes instead. // - binary.Write(&buf, binary.BigEndian, uint32(time.Now().Unix())) + binary.Write(buf, binary.BigEndian, uint32(time.Now().Unix())) random := make([]byte, 28) // The above 2 lines of codes was added to make it compatible with some server implementation, // if we don't need the compatibility, just use the following code instead. @@ -205,7 +206,7 @@ func clientHello() *bytes.Buffer { // https://github.com/shadowsocks/simple-obfs/blob/7659eeccf473aa41eb294e92c32f8f60a8747325/src/obfs_tls.c#L57 // Cipher Suites Length: 56 - binary.Write(&buf, binary.BigEndian, uint16(56)) + binary.Write(buf, binary.BigEndian, uint16(56)) // Cipher Suites (28 suites) buf.Write([]byte{ 0xc0, 0x2c, 0xc0, 0x30, 0x00, 0x9f, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x2b, 0xc0, 0x2f, @@ -218,56 +219,50 @@ func clientHello() *bytes.Buffer { buf.WriteByte(0x01) // Compression Methods (1 method) buf.WriteByte(0x00) - - return &buf } -func extension(b []byte, server string) *bytes.Buffer { - var buf bytes.Buffer - +func extension(b []byte, server string, buf *bytes.Buffer) { // Extension: SessionTicket TLS buf.Write([]byte{0x00, 0x23}) // type // NOTE: send some data in sessionticket, the server will treat it as data too - binary.Write(&buf, binary.BigEndian, uint16(len(b))) // length + binary.Write(buf, binary.BigEndian, uint16(len(b))) // length buf.Write(b) // Extension: server_name - buf.Write([]byte{0x00, 0x00}) // type - binary.Write(&buf, binary.BigEndian, uint16(len(server)+5)) // length - binary.Write(&buf, binary.BigEndian, uint16(len(server)+3)) // Server Name list length - buf.WriteByte(0x00) // Server Name Type: host_name (0) - binary.Write(&buf, binary.BigEndian, uint16(len(server))) // Server Name length + buf.Write([]byte{0x00, 0x00}) // type + binary.Write(buf, binary.BigEndian, uint16(len(server)+5)) // length + binary.Write(buf, binary.BigEndian, uint16(len(server)+3)) // Server Name list length + buf.WriteByte(0x00) // Server Name Type: host_name (0) + binary.Write(buf, binary.BigEndian, uint16(len(server))) // Server Name length buf.WriteString(server) // https://github.com/shadowsocks/simple-obfs/blob/7659eeccf473aa41eb294e92c32f8f60a8747325/src/obfs_tls.c#L88 // Extension: ec_point_formats (len=4) - buf.Write([]byte{0x00, 0x0b}) // type - binary.Write(&buf, binary.BigEndian, uint16(4)) // length - buf.WriteByte(0x03) // format length + buf.Write([]byte{0x00, 0x0b}) // type + binary.Write(buf, binary.BigEndian, uint16(4)) // length + buf.WriteByte(0x03) // format length buf.Write([]byte{0x01, 0x00, 0x02}) // Extension: supported_groups (len=10) - buf.Write([]byte{0x00, 0x0a}) // type - binary.Write(&buf, binary.BigEndian, uint16(10)) // length - binary.Write(&buf, binary.BigEndian, uint16(8)) // Supported Groups List Length: 8 + buf.Write([]byte{0x00, 0x0a}) // type + binary.Write(buf, binary.BigEndian, uint16(10)) // length + binary.Write(buf, binary.BigEndian, uint16(8)) // Supported Groups List Length: 8 buf.Write([]byte{0x00, 0x1d, 0x00, 0x17, 0x00, 0x19, 0x00, 0x18}) // Extension: signature_algorithms (len=32) - buf.Write([]byte{0x00, 0x0d}) // type - binary.Write(&buf, binary.BigEndian, uint16(32)) // length - binary.Write(&buf, binary.BigEndian, uint16(30)) // Signature Hash Algorithms Length: 30 + buf.Write([]byte{0x00, 0x0d}) // type + binary.Write(buf, binary.BigEndian, uint16(32)) // length + binary.Write(buf, binary.BigEndian, uint16(30)) // Signature Hash Algorithms Length: 30 buf.Write([]byte{ 0x06, 0x01, 0x06, 0x02, 0x06, 0x03, 0x05, 0x01, 0x05, 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, }) // Extension: encrypt_then_mac (len=0) - buf.Write([]byte{0x00, 0x16}) // type - binary.Write(&buf, binary.BigEndian, uint16(0)) // length + buf.Write([]byte{0x00, 0x16}) // type + binary.Write(buf, binary.BigEndian, uint16(0)) // length // Extension: extended_master_secret (len=0) - buf.Write([]byte{0x00, 0x17}) // type - binary.Write(&buf, binary.BigEndian, uint16(0)) // length - - return &buf + buf.Write([]byte{0x00, 0x17}) // type + binary.Write(buf, binary.BigEndian, uint16(0)) // length } diff --git a/proxy/server.go b/proxy/server.go index f0ec22a..9b0e37f 100644 --- a/proxy/server.go +++ b/proxy/server.go @@ -6,7 +6,7 @@ import ( "strings" ) -// Server interface +// Server interface. type Server interface { // ListenAndServe sets up a listener and serve on it ListenAndServe() @@ -15,20 +15,20 @@ type Server interface { Serve(c net.Conn) } -// ServerCreator is a function to create proxy servers +// ServerCreator is a function to create proxy servers. type ServerCreator func(s string, proxy Proxy) (Server, error) var ( serverCreators = make(map[string]ServerCreator) ) -// RegisterServer is used to register a proxy server +// RegisterServer is used to register a proxy server. func RegisterServer(name string, c ServerCreator) { serverCreators[strings.ToLower(name)] = c } -// ServerFromURL calls the registered creator to create proxy servers -// dialer is the default upstream dialer so cannot be nil, we can use Default when calling this function +// ServerFromURL calls the registered creator to create proxy servers. +// dialer is the default upstream dialer so cannot be nil, we can use Default when calling this function. func ServerFromURL(s string, p Proxy) (Server, error) { if p == nil { return nil, errors.New("ServerFromURL: dialer cannot be nil") diff --git a/proxy/socks5/packet.go b/proxy/socks5/packet.go index 604e942..8fc2be2 100644 --- a/proxy/socks5/packet.go +++ b/proxy/socks5/packet.go @@ -97,8 +97,8 @@ func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) { return pc.PacketConn.WriteTo(b, addr) } - buf := pool.GetWriteBuffer() - defer pool.PutWriteBuffer(buf) + buf := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(buf) buf.Write([]byte{0, 0, 0}) tgtLen, _ := buf.Write(pc.tgtAddr) diff --git a/proxy/ss/packet.go b/proxy/ss/packet.go index 88762f9..a9b02ce 100644 --- a/proxy/ss/packet.go +++ b/proxy/ss/packet.go @@ -67,8 +67,8 @@ func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) { return pc.PacketConn.WriteTo(b, addr) } - buf := pool.GetWriteBuffer() - defer pool.PutWriteBuffer(buf) + buf := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(buf) tgtLen, _ := buf.Write(pc.tgtAddr) buf.Write(b) diff --git a/proxy/ssr/internal/client.go b/proxy/ssr/internal/client.go index 1ac0580..bf36fef 100644 --- a/proxy/ssr/internal/client.go +++ b/proxy/ssr/internal/client.go @@ -44,16 +44,16 @@ func NewSSTCPConn(c net.Conn, cipher *cipher.StreamCipher) *SSTCPConn { Conn: c, StreamCipher: cipher, readBuf: pool.GetBuffer(bufSize), - decryptedBuf: pool.GetWriteBuffer(), - underPostdecryptBuf: pool.GetWriteBuffer(), + decryptedBuf: pool.GetBytesBuffer(), + underPostdecryptBuf: pool.GetBytesBuffer(), writeBuf: pool.GetBuffer(bufSize), } } func (c *SSTCPConn) Close() error { pool.PutBuffer(c.readBuf) - pool.PutWriteBuffer(c.decryptedBuf) - pool.PutWriteBuffer(c.underPostdecryptBuf) + pool.PutBytesBuffer(c.decryptedBuf) + pool.PutBytesBuffer(c.underPostdecryptBuf) pool.PutBuffer(c.writeBuf) return c.Conn.Close() } diff --git a/proxy/ssr/ssr.go b/proxy/ssr/ssr.go index 30ed906..99970e7 100644 --- a/proxy/ssr/ssr.go +++ b/proxy/ssr/ssr.go @@ -10,6 +10,7 @@ import ( "github.com/nadoo/glider/log" "github.com/nadoo/glider/proxy" "github.com/nadoo/glider/proxy/socks" + "github.com/nadoo/glider/proxy/ssr/internal" "github.com/nadoo/glider/proxy/ssr/internal/cipher" "github.com/nadoo/glider/proxy/ssr/internal/obfs" diff --git a/proxy/tls/tls.go b/proxy/tls/tls.go index d67edd1..bd4d43d 100644 --- a/proxy/tls/tls.go +++ b/proxy/tls/tls.go @@ -33,7 +33,7 @@ func init() { proxy.RegisterServer("tls", NewTLSServer) } -// NewTLS returns a tls proxy struct. +// NewTLS returns a tls struct. func NewTLS(s string, d proxy.Dialer, p proxy.Proxy) (*TLS, error) { u, err := url.Parse(s) if err != nil { @@ -64,7 +64,7 @@ func NewTLS(s string, d proxy.Dialer, p proxy.Proxy) (*TLS, error) { return t, nil } -// NewTLSDialer returns a tls proxy dialer. +// NewTLSDialer returns a tls dialer. func NewTLSDialer(s string, d proxy.Dialer) (proxy.Dialer, error) { p, err := NewTLS(s, d, nil) if err != nil { diff --git a/proxy/trojan/client.go b/proxy/trojan/client.go index 4c03744..31953b0 100644 --- a/proxy/trojan/client.go +++ b/proxy/trojan/client.go @@ -69,8 +69,8 @@ func (s *Trojan) dial(network, addr string) (net.Conn, error) { rc = tlsConn } - buf := pool.GetWriteBuffer() - defer pool.PutWriteBuffer(buf) + buf := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(buf) buf.Write(s.pass[:]) buf.WriteString("\r\n") diff --git a/proxy/trojan/packet.go b/proxy/trojan/packet.go index c3dc9af..559cdae 100644 --- a/proxy/trojan/packet.go +++ b/proxy/trojan/packet.go @@ -67,8 +67,8 @@ func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) { // WriteTo implements the necessary function of net.PacketConn. func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) { - buf := pool.GetWriteBuffer() - defer pool.PutWriteBuffer(buf) + buf := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(buf) tgtLen, _ := buf.Write(pc.tgtAddr) binary.Write(buf, binary.BigEndian, uint16(len(b))) diff --git a/proxy/trojan/server.go b/proxy/trojan/server.go index 52669f6..4902a91 100644 --- a/proxy/trojan/server.go +++ b/proxy/trojan/server.go @@ -93,8 +93,8 @@ func (s *Trojan) Serve(c net.Conn) { c = tlsConn } - headBuf := pool.GetWriteBuffer() - defer pool.PutWriteBuffer(headBuf) + headBuf := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(headBuf) cmd, target, err := s.readHeader(io.TeeReader(c, headBuf)) if err != nil { diff --git a/proxy/vless/client.go b/proxy/vless/client.go index 3a8e0a7..bd6f54f 100644 --- a/proxy/vless/client.go +++ b/proxy/vless/client.go @@ -59,12 +59,12 @@ func NewClientConn(c net.Conn, uuid [16]byte, network, target string) (*ClientCo return nil, err } - buf := pool.GetWriteBuffer() - defer pool.PutWriteBuffer(buf) + buf := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(buf) buf.WriteByte(Version) // ver buf.Write(uuid[:]) // uuid - buf.WriteByte(0) // addLen + buf.WriteByte(0) // addonLen cmd := CmdTCP if network == "udp" { diff --git a/proxy/vless/packet.go b/proxy/vless/packet.go index 04c1bfa..9e2aa12 100644 --- a/proxy/vless/packet.go +++ b/proxy/vless/packet.go @@ -39,8 +39,8 @@ func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) { // WriteTo implements the necessary function of net.PacketConn. func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) { - buf := pool.GetWriteBuffer() - defer pool.PutWriteBuffer(buf) + buf := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(buf) binary.Write(buf, binary.BigEndian, uint16(len(b))) buf.Write(b) diff --git a/proxy/vless/server.go b/proxy/vless/server.go index 4da94bd..2af9073 100644 --- a/proxy/vless/server.go +++ b/proxy/vless/server.go @@ -48,8 +48,8 @@ func (s *VLess) Serve(c net.Conn) { c.SetKeepAlive(true) } - headBuf := pool.GetWriteBuffer() - defer pool.PutWriteBuffer(headBuf) + headBuf := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(headBuf) cmd, target, err := s.readHeader(io.TeeReader(c, headBuf)) if err != nil { @@ -116,35 +116,25 @@ func (s *VLess) serveFallback(c net.Conn, tgt string, headBuf *bytes.Buffer) { } func (s *VLess) readHeader(r io.Reader) (CmdType, string, error) { - buf := pool.GetBuffer(16) + // ver: 1, uuid: 16, addonLen: 1 + buf := pool.GetBuffer(18) defer pool.PutBuffer(buf) - // ver - if _, err := io.ReadFull(r, buf[:1]); err != nil { - return CmdErr, "", fmt.Errorf("get version error: %v", err) + if _, err := io.ReadFull(r, buf[:18]); err != nil { + return CmdErr, "", fmt.Errorf("read header error: %v", err) } if buf[0] != Version { return CmdErr, "", fmt.Errorf("version %d not supported", buf[0]) } - // uuid - if _, err := io.ReadFull(r, buf[:16]); err != nil { - return CmdErr, "", fmt.Errorf("get uuid error: %v", err) - } - - if !bytes.Equal(s.uuid[:], buf) { + if !bytes.Equal(s.uuid[:], buf[1:17]) { return CmdErr, "", fmt.Errorf("auth failed, client id: %02x", buf[:16]) } - // addLen - if _, err := io.ReadFull(r, buf[:1]); err != nil { - return CmdErr, "", fmt.Errorf("get addon length error: %v", err) - } - // ignore addons - if addLen := int64(buf[0]); addLen > 0 { - proxy.CopyN(ioutil.Discard, r, addLen) + if addonLen := int64(buf[17]); addonLen > 0 { + proxy.CopyN(ioutil.Discard, r, addonLen) } // cmd @@ -154,7 +144,6 @@ func (s *VLess) readHeader(r io.Reader) (CmdType, string, error) { // target target, err := ReadAddrString(r) - return CmdType(buf[0]), target, err } diff --git a/proxy/vmess/client.go b/proxy/vmess/client.go index cc48e56..d823192 100644 --- a/proxy/vmess/client.go +++ b/proxy/vmess/client.go @@ -159,8 +159,8 @@ func (c *Conn) Auth() error { // Request sends request to server. func (c *Conn) Request() error { - buf := pool.GetWriteBuffer() - defer pool.PutWriteBuffer(buf) + buf := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(buf) // Request buf.WriteByte(1) // Ver diff --git a/proxy/ws/client.go b/proxy/ws/client.go index e17248f..16cf470 100644 --- a/proxy/ws/client.go +++ b/proxy/ws/client.go @@ -1,7 +1,6 @@ package ws import ( - "bufio" "errors" "io" "net" @@ -60,8 +59,8 @@ func (s *WS) NewClientConn(rc net.Conn) (*ClientConn, error) { func (c *ClientConn) Handshake(host, path string) error { clientKey := generateClientKey() - buf := pool.GetWriteBuffer() - defer pool.PutWriteBuffer(buf) + buf := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(buf) buf.WriteString("GET " + path + " HTTP/1.1\r\n") buf.WriteString("Host: " + host + "\r\n") @@ -77,7 +76,10 @@ func (c *ClientConn) Handshake(host, path string) error { return err } - tpr := textproto.NewReader(bufio.NewReader(c.Conn)) + br := pool.GetBufReader(c.Conn) + defer pool.PutBufReader(br) + + tpr := textproto.NewReader(br) line, err := tpr.ReadLine() if err != nil { return err diff --git a/proxy/ws/server.go b/proxy/ws/server.go index 1acce82..2bd2b7d 100644 --- a/proxy/ws/server.go +++ b/proxy/ws/server.go @@ -1,7 +1,6 @@ package ws import ( - "bufio" "errors" "io" "net" @@ -93,7 +92,10 @@ func (s *WS) NewServerConn(rc net.Conn) (*ServerConn, error) { // Handshake handshakes with the client. func (c *ServerConn) Handshake(host, path string) error { - tpr := textproto.NewReader(bufio.NewReader(c.Conn)) + br := pool.GetBufReader(c.Conn) + defer pool.PutBufReader(br) + + tpr := textproto.NewReader(br) line, err := tpr.ReadLine() if err != nil { return err @@ -117,8 +119,8 @@ func (c *ServerConn) Handshake(host, path string) error { clientKey := reqHeader.Get("Sec-WebSocket-Key") serverKey := computeServerKey(clientKey) - buf := pool.GetWriteBuffer() - defer pool.PutWriteBuffer(buf) + buf := pool.GetBytesBuffer() + defer pool.PutBytesBuffer(buf) buf.WriteString("HTTP/1.1 101 Switching Protocols\r\n") buf.WriteString("Upgrade: websocket\r\n") diff --git a/proxy/ws/ws.go b/proxy/ws/ws.go index 236feb3..f35e439 100644 --- a/proxy/ws/ws.go +++ b/proxy/ws/ws.go @@ -1,4 +1,3 @@ -// Package ws implements a simple websocket client. package ws import ( diff --git a/systemd/glider@.service b/systemd/glider@.service index 46b6d1b..4a6bbe0 100644 --- a/systemd/glider@.service +++ b/systemd/glider@.service @@ -7,10 +7,12 @@ Type=simple User=nobody Restart=always LimitNOFILE=102400 +Environment="GODEBUG=madvdontneed=1" -# NOTE: change to your glider path +# NOTE: CHANGE to your glider path ExecStart=/usr/bin/glider -config /etc/glider/%i.conf +# NOTE: # work with systemd v229 or later, so glider can listen on port below 1024 with none-root user # CAP_NET_ADMIN: ipset # CAP_NET_BIND_SERVICE: bind ports under 1024