pool: added bufio.Reader pool

This commit is contained in:
nadoo 2020-11-03 22:52:50 +08:00
parent c15c55fe05
commit 417ac556f7
29 changed files with 188 additions and 168 deletions

View File

@ -44,28 +44,28 @@ we can set up local listeners as proxy servers, and forward requests to internet
<summary>click to see details</summary>
|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
</details>

View File

@ -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 {

6
go.mod
View File

@ -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
)

12
go.sum
View File

@ -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=

24
pool/bufreader.go Normal file
View File

@ -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)
}

25
pool/bytesbuffer.go Normal file
View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)

View File

@ -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
}

View File

@ -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 {

View File

@ -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")

View File

@ -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
}

View File

@ -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")

View File

@ -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)

View File

@ -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)

View File

@ -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()
}

View File

@ -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"

View File

@ -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 {

View File

@ -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")

View File

@ -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)))

View File

@ -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 {

View File

@ -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" {

View File

@ -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)

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -1,4 +1,3 @@
// Package ws implements a simple websocket client.
package ws
import (

View File

@ -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