From 76fddcc29c4f7d940149b67b206195616f49fd07 Mon Sep 17 00:00:00 2001 From: nadoo <287492+nadoo@users.noreply.github.com> Date: Wed, 22 Apr 2020 19:37:10 +0800 Subject: [PATCH] dns: use pool buffer if possible --- dns/server.go | 12 +++++++++--- go.mod | 4 ++-- go.sum | 8 ++++---- proxy/socks4/socks4.go | 30 ++++++++++++++++-------------- proxy/socks5/packet.go | 17 +++++++++++++---- proxy/socks5/socks5.go | 8 ++++++-- proxy/ss/packet.go | 9 +++++++-- proxy/ss/ss.go | 10 ++++++---- 8 files changed, 63 insertions(+), 35 deletions(-) diff --git a/dns/server.go b/dns/server.go index acec2fc..def7aaa 100644 --- a/dns/server.go +++ b/dns/server.go @@ -8,6 +8,7 @@ import ( "time" "github.com/nadoo/glider/common/log" + "github.com/nadoo/glider/common/pool" "github.com/nadoo/glider/proxy" ) @@ -59,7 +60,8 @@ func (s *Server) ListenAndServeUDP(wg *sync.WaitGroup) { log.F("[dns] listening UDP on %s", s.addr) for { - reqBytes := make([]byte, 2+UDPMaxLen) + reqBytes := pool.GetBuffer(2 + UDPMaxLen) + n, caddr, err := c.ReadFrom(reqBytes[2:]) if err != nil { log.F("[dns] local read error: %v", err) @@ -75,6 +77,8 @@ func (s *Server) ListenAndServeUDP(wg *sync.WaitGroup) { go func() { respBytes, err := s.Client.Exchange(reqBytes[:2+n], caddr.String(), false) + defer pool.PutBuffer(reqBytes) + if err != nil { log.F("[dns] error in exchange: %s", err) return @@ -125,7 +129,9 @@ func (s *Server) ServeTCP(c net.Conn) { return } - reqBytes := make([]byte, reqLen+2) + reqBytes := pool.GetBuffer(int(reqLen) + 2) + defer pool.PutBuffer(reqBytes) + _, err := io.ReadFull(c, reqBytes[2:]) if err != nil { log.F("[dns-tcp] error in read reqBytes %s", err) @@ -140,7 +146,7 @@ func (s *Server) ServeTCP(c net.Conn) { return } - if err := binary.Write(c, binary.BigEndian, respBytes); err != nil { + if _, err := c.Write(respBytes); err != nil { log.F("[dns-tcp] error in local write respBytes: %s", err) return } diff --git a/go.mod b/go.mod index 6c8870d..7e660b3 100644 --- a/go.mod +++ b/go.mod @@ -10,8 +10,8 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/tjfoc/gmsm v1.3.0 // indirect github.com/xtaci/kcp-go/v5 v5.5.12 - golang.org/x/crypto v0.0.0-20200420104511-884d27f42877 - golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect + golang.org/x/crypto v0.0.0-20200420201142-3c4aac89819a + golang.org/x/net v0.0.0-20200421231249-e086a090c8fd // indirect golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f // indirect ) diff --git a/go.sum b/go.sum index 1ff026e..9cb5a00 100644 --- a/go.sum +++ b/go.sum @@ -58,13 +58,13 @@ golang.org/x/crypto v0.0.0-20191010185427-af544f31c8ac/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200420104511-884d27f42877 h1:IhZPbxNd1UjBCaD5AfpSSbJTRlp+ZSuyuH5uoksNS04= -golang.org/x/crypto v0.0.0-20200420104511-884d27f42877/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200420201142-3c4aac89819a h1:y6sBfNd1b9Wy08a6K1Z1DZc4aXABUN5TKjkYhz7UKmo= +golang.org/x/crypto v0.0.0-20200420201142-3c4aac89819a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd h1:QPwSajcTUrFriMF1nJ3XzgoqakqQEsnZf9LdXdi2nkI= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/proxy/socks4/socks4.go b/proxy/socks4/socks4.go index 3f311f4..7a269c5 100644 --- a/proxy/socks4/socks4.go +++ b/proxy/socks4/socks4.go @@ -12,6 +12,7 @@ import ( "strconv" "github.com/nadoo/glider/common/log" + "github.com/nadoo/glider/common/pool" "github.com/nadoo/glider/proxy" ) @@ -66,12 +67,12 @@ func (s *SOCKS4) Dial(network, addr string) (net.Conn, error) { switch network { case "tcp", "tcp4": default: - return nil, errors.New("[socks4]: no support for connection type " + network) + return nil, errors.New("[socks4] no support for connection type " + network) } c, err := s.dialer.Dial(network, s.addr) if err != nil { - log.F("[socks4]: dial to %s error: %s", s.addr, err) + log.F("[socks4] dial to %s error: %s", s.addr, err) return nil, err } @@ -85,7 +86,7 @@ func (s *SOCKS4) Dial(network, addr string) (net.Conn, error) { // DialUDP connects to the given address via the proxy. func (s *SOCKS4) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) { - return nil, nil, errors.New("DialUDP are not supported by Socks4") + return nil, nil, errors.New("[socks4] DialUDP are not supported by Socks4") } func (s *SOCKS4) lookupIP(host string) (ip net.IP, err error) { @@ -94,12 +95,12 @@ func (s *SOCKS4) lookupIP(host string) (ip net.IP, err error) { return } if len(ips) == 0 { - err = errors.New("Cannot resolve host: " + host) + err = errors.New("[socks4] Cannot resolve host: " + host) return } ip = ips[0].To4() if len(ip) != net.IPv4len { - err = errors.New("IPv6 is not supported by socks4") + err = errors.New("[socks4] IPv6 is not supported by socks4") return } return @@ -116,10 +117,10 @@ func (s *SOCKS4) connect(conn net.Conn, target string) error { port, err := strconv.Atoi(portStr) if err != nil { - return errors.New("proxy: failed to parse port number: " + portStr) + return errors.New("[socks4] failed to parse port number: " + portStr) } if port < 1 || port > 0xffff { - return errors.New("proxy: port number out of range: " + portStr) + return errors.New("[socks4] port number out of range: " + portStr) } ip, err := s.lookupIP(host) @@ -137,27 +138,28 @@ func (s *SOCKS4) connect(conn net.Conn, target string) error { 0, // user id } - resp := make([]byte, 8) + resp := pool.GetBuffer(8) + defer pool.PutBuffer(resp) if _, err := conn.Write(buf); err != nil { - return errors.New("proxy: failed to write greeting to socks4 proxy at " + s.addr + ": " + err.Error()) + return errors.New("[socks4] failed to write greeting to socks4 proxy at " + s.addr + ": " + err.Error()) } if _, err := io.ReadFull(conn, resp); err != nil { - return errors.New("proxy: failed to read greeting from socks4 proxy at " + s.addr + ": " + err.Error()) + return errors.New("[socks4] failed to read greeting from socks4 proxy at " + s.addr + ": " + err.Error()) } switch resp[1] { case 0x5a: // request granted case 0x5b: - err = errors.New("Socks connection request rejected or failed") + err = errors.New("[socks4] connection request rejected or failed") case 0x5c: - err = errors.New("Socks connection request request failed because client is not running identd (or not reachable from the server)") + err = errors.New("[socks4] connection request request failed because client is not running identd (or not reachable from the server)") case 0x5d: - err = errors.New("Socks connection request request failed because client's identd could not confirm the user ID in the request") + err = errors.New("[socks4] connection request request failed because client's identd could not confirm the user ID in the request") default: - err = errors.New("Socks connection request failed, unknown error") + err = errors.New("[socks4] connection request failed, unknown error") } return err diff --git a/proxy/socks5/packet.go b/proxy/socks5/packet.go index 93e1bb7..432f364 100644 --- a/proxy/socks5/packet.go +++ b/proxy/socks5/packet.go @@ -5,6 +5,7 @@ import ( "net" "github.com/nadoo/glider/common/log" + "github.com/nadoo/glider/common/pool" "github.com/nadoo/glider/common/socks" ) @@ -31,7 +32,8 @@ func NewPktConn(c net.PacketConn, writeAddr net.Addr, tgtAddr socks.Addr, tgtHea if ctrlConn != nil { go func() { - buf := make([]byte, 1) + buf := pool.GetBuffer(1) + defer pool.PutBuffer(buf) for { _, err := ctrlConn.Read(buf) if err, ok := err.(net.Error); ok && err.Timeout() { @@ -52,7 +54,9 @@ func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) { return pc.PacketConn.ReadFrom(b) } - buf := make([]byte, len(b)) + buf := pool.GetBuffer(len(b)) + defer pool.PutBuffer(buf) + n, raddr, err := pc.PacketConn.ReadFrom(buf) if err != nil { return n, raddr, err @@ -92,8 +96,13 @@ func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) { return pc.PacketConn.WriteTo(b, addr) } - buf := append([]byte{0, 0, 0}, pc.tgtAddr...) - buf = append(buf, b[:]...) + buf := pool.GetBuffer(3 + len(pc.tgtAddr) + len(b)) + defer pool.PutBuffer(buf) + + copy(buf, []byte{0, 0, 0}) + copy(buf[3:], pc.tgtAddr) + copy(buf[3+len(pc.tgtAddr):], b) + return pc.PacketConn.WriteTo(buf, pc.writeAddr) } diff --git a/proxy/socks5/socks5.go b/proxy/socks5/socks5.go index 5e754e0..398d10a 100644 --- a/proxy/socks5/socks5.go +++ b/proxy/socks5/socks5.go @@ -20,6 +20,7 @@ import ( "github.com/nadoo/glider/common/conn" "github.com/nadoo/glider/common/log" + "github.com/nadoo/glider/common/pool" "github.com/nadoo/glider/common/socks" "github.com/nadoo/glider/proxy" ) @@ -114,7 +115,8 @@ func (s *Socks5) Serve(c net.Conn) { if err != nil { // UDP: keep the connection until disconnect then free the UDP socket if err == socks.Errors[9] { - buf := make([]byte, 1) + buf := pool.GetBuffer(1) + defer pool.PutBuffer(buf) // block here for { _, err := c.Read(buf) @@ -252,7 +254,9 @@ func (s *Socks5) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.A // send VER, NMETHODS, METHODS c.Write([]byte{Version, 1, 0}) - buf := make([]byte, socks.MaxAddrLen) + buf := pool.GetBuffer(socks.MaxAddrLen) + defer pool.PutBuffer(buf) + // read VER METHOD if _, err := io.ReadFull(c, buf[:2]); err != nil { return nil, nil, err diff --git a/proxy/ss/packet.go b/proxy/ss/packet.go index a89f61f..27d4ad4 100644 --- a/proxy/ss/packet.go +++ b/proxy/ss/packet.go @@ -4,6 +4,7 @@ import ( "errors" "net" + "github.com/nadoo/glider/common/pool" "github.com/nadoo/glider/common/socks" ) @@ -33,7 +34,9 @@ func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) { return pc.PacketConn.ReadFrom(b) } - buf := make([]byte, len(b)) + buf := pool.GetBuffer(len(b)) + defer pool.PutBuffer(buf) + n, raddr, err := pc.PacketConn.ReadFrom(buf) if err != nil { return n, raddr, err @@ -63,7 +66,9 @@ func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) { return pc.PacketConn.WriteTo(b, addr) } - buf := make([]byte, len(pc.tgtAddr)+len(b)) + buf := pool.GetBuffer(len(pc.tgtAddr) + len(b)) + pool.PutBuffer(buf) + copy(buf, pc.tgtAddr) copy(buf[len(pc.tgtAddr):], b) diff --git a/proxy/ss/ss.go b/proxy/ss/ss.go index 5516bee..14fbeff 100644 --- a/proxy/ss/ss.go +++ b/proxy/ss/ss.go @@ -12,6 +12,7 @@ import ( "github.com/nadoo/glider/common/conn" "github.com/nadoo/glider/common/log" + "github.com/nadoo/glider/common/pool" "github.com/nadoo/glider/common/socks" "github.com/nadoo/glider/proxy" ) @@ -121,17 +122,18 @@ func (s *SS) Serve(c net.Conn) { } defer rc.Close() - req := make([]byte, conn.UDPBufSize) - n, err := c.Read(req) + buf := pool.GetBuffer(conn.UDPBufSize) + defer pool.PutBuffer(buf) + + n, err := c.Read(buf) if err != nil { log.F("[ss-uottun] error in ioutil.ReadAll: %s\n", err) return } tgtAddr, _ := net.ResolveUDPAddr("udp", tgt.String()) - rc.WriteTo(req[:n], tgtAddr) + rc.WriteTo(buf[:n], tgtAddr) - buf := make([]byte, conn.UDPBufSize) n, _, err = rc.ReadFrom(buf) if err != nil { log.F("[ss-uottun] read error: %v", err)