mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 01:15:41 +08:00
pool: added bufio.Reader pool
This commit is contained in:
parent
c15c55fe05
commit
417ac556f7
44
README.md
44
README.md
@ -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>
|
||||
|
||||
|
@ -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
6
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
|
||||
)
|
||||
|
||||
|
12
go.sum
12
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=
|
||||
|
24
pool/bufreader.go
Normal file
24
pool/bufreader.go
Normal 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
25
pool/bytesbuffer.go
Normal 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)
|
||||
}
|
@ -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)
|
||||
}
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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 {
|
||||
|
@ -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")
|
||||
|
@ -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)))
|
||||
|
@ -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 {
|
||||
|
@ -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" {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -1,4 +1,3 @@
|
||||
// Package ws implements a simple websocket client.
|
||||
package ws
|
||||
|
||||
import (
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user