general: optimize domain parts operations

This commit is contained in:
nadoo 2020-08-16 12:00:46 +08:00
parent 3a6fd63bc0
commit a118ec5837
14 changed files with 51 additions and 65 deletions

View File

@ -233,21 +233,18 @@ func (c *Client) exchangeUDP(rc net.Conn, reqBytes []byte) ([]byte, error) {
// SetServers sets upstream dns servers for the given domain. // SetServers sets upstream dns servers for the given domain.
func (c *Client) SetServers(domain string, servers []string) { func (c *Client) SetServers(domain string, servers []string) {
c.upStreamMap[domain] = NewUPStream(servers) c.upStreamMap[strings.ToLower(domain)] = NewUPStream(servers)
} }
// UpStream returns upstream dns server for the given domain. // UpStream returns upstream dns server for the given domain.
func (c *Client) UpStream(domain string) *UPStream { func (c *Client) UpStream(domain string) *UPStream {
domainParts := strings.Split(domain, ".") domain = strings.ToLower(domain)
length := len(domainParts) for i := len(domain); i != -1; {
for i := length - 1; i >= 0; i-- { i = strings.LastIndexByte(domain[:i], '.')
domain := strings.Join(domainParts[i:length], ".") if upstream, ok := c.upStreamMap[domain[i+1:]]; ok {
if upstream, ok := c.upStreamMap[domain]; ok {
return upstream return upstream
} }
} }
return c.upStream return c.upStream
} }

4
go.mod
View File

@ -10,8 +10,8 @@ require (
github.com/xtaci/kcp-go/v5 v5.5.15 github.com/xtaci/kcp-go/v5 v5.5.15
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc // indirect golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc // indirect
golang.org/x/sys v0.0.0-20200812155832-6a926be9bd1d // indirect golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed // indirect
golang.org/x/tools v0.0.0-20200813231717-0a73ddcff9b8 // indirect golang.org/x/tools v0.0.0-20200815165600-90abf76919f3 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
) )

8
go.sum
View File

@ -115,15 +115,15 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9 h1:yi1hN8dcqI9l8klZfy4B8mJvFmmAxJEePIQQFNSd7Cs= golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9 h1:yi1hN8dcqI9l8klZfy4B8mJvFmmAxJEePIQQFNSd7Cs=
golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200812155832-6a926be9bd1d h1:QQrM/CCYEzTs91GZylDCQjGHudbPTxF/1fvXdVh5lMo= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed h1:J22ig1FUekjjkmZUM7pTKixYm8DvrYsvrBZdunYeIuQ=
golang.org/x/sys v0.0.0-20200812155832-6a926be9bd1d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c h1:iHhCR0b26amDCiiO+kBguKZom9aMF+NrFxh9zeKR/XU= golang.org/x/tools v0.0.0-20200425043458-8463f397d07c h1:iHhCR0b26amDCiiO+kBguKZom9aMF+NrFxh9zeKR/XU=
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 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-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200813231717-0a73ddcff9b8 h1:+hbnCVs7yJ18cZmTc/aRTUmFIr+z6I1lnMjyeMJJGEM= golang.org/x/tools v0.0.0-20200815165600-90abf76919f3 h1:0aScV/0rLmANzEYIhjCOi2pTvDyhZNduBUMD2q3iqs4=
golang.org/x/tools v0.0.0-20200813231717-0a73ddcff9b8/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200815165600-90abf76919f3/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=

View File

@ -128,18 +128,13 @@ func (m *Manager) AddDomainIP(domain, ip string) error {
if domain == "" || ip == "" { if domain == "" || ip == "" {
return errors.New("please specify the domain and ip address") return errors.New("please specify the domain and ip address")
} }
domain = strings.ToLower(domain)
domainParts := strings.Split(domain, ".") for i := len(domain); i != -1; {
length := len(domainParts) i = strings.LastIndexByte(domain[:i], '.')
for i := length - 1; i >= 0; i-- { if ipset, ok := m.domainSet.Load(domain[i+1:]); ok {
domain := strings.Join(domainParts[i:length], ".")
// find in domainMap
if ipset, ok := m.domainSet.Load(domain); ok {
AddToSet(m.fd, m.lsa, ipset.(string), ip) AddToSet(m.fd, m.lsa, ipset.(string), ip)
} }
} }
return nil return nil
} }

View File

@ -34,7 +34,7 @@ import (
_ "github.com/nadoo/glider/proxy/ws" _ "github.com/nadoo/glider/proxy/ws"
) )
var version = "0.10.2" var version = "0.10.3"
func main() { func main() {
// read configs // read configs

View File

@ -21,7 +21,7 @@ type PktConn struct {
ctrlConn net.Conn // tcp control conn ctrlConn net.Conn // tcp control conn
} }
// NewPktConn returns a PktConn // NewPktConn returns a PktConn.
func NewPktConn(c net.PacketConn, writeAddr net.Addr, tgtAddr socks.Addr, tgtHeader bool, ctrlConn net.Conn) *PktConn { func NewPktConn(c net.PacketConn, writeAddr net.Addr, tgtAddr socks.Addr, tgtHeader bool, ctrlConn net.Conn) *PktConn {
pc := &PktConn{ pc := &PktConn{
PacketConn: c, PacketConn: c,
@ -48,7 +48,7 @@ func NewPktConn(c net.PacketConn, writeAddr net.Addr, tgtAddr socks.Addr, tgtHea
return pc return pc
} }
// ReadFrom overrides the original function from net.PacketConn // ReadFrom overrides the original function from net.PacketConn.
func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) { func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
if !pc.tgtHeader { if !pc.tgtHeader {
return pc.PacketConn.ReadFrom(b) return pc.PacketConn.ReadFrom(b)
@ -90,7 +90,7 @@ func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
return n - len(tgtAddr) - 3, raddr, err return n - len(tgtAddr) - 3, raddr, err
} }
// WriteTo overrides the original function from net.PacketConn // WriteTo overrides the original function from net.PacketConn.
func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) { func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) {
if !pc.tgtHeader { if !pc.tgtHeader {
return pc.PacketConn.WriteTo(b, addr) return pc.PacketConn.WriteTo(b, addr)

View File

@ -42,7 +42,7 @@ func init() {
proxy.RegisterServer("socks5", NewSocks5Server) proxy.RegisterServer("socks5", NewSocks5Server)
} }
// NewSocks5 returns a Proxy that makes SOCKS v5 connections to the given address // NewSocks5 returns a Proxy that makes SOCKS v5 connections to the given address.
// with an optional username and password. (RFC 1928) // with an optional username and password. (RFC 1928)
func NewSocks5(s string, d proxy.Dialer, p proxy.Proxy) (*Socks5, error) { func NewSocks5(s string, d proxy.Dialer, p proxy.Proxy) (*Socks5, error) {
u, err := url.Parse(s) u, err := url.Parse(s)

View File

@ -5,7 +5,7 @@ import (
"strconv" "strconv"
) )
// Atyp is vmess addr type // Atyp is vmess addr type.
type Atyp byte type Atyp byte
// Atyp // Atyp
@ -16,13 +16,13 @@ const (
AtypIP6 Atyp = 3 AtypIP6 Atyp = 3
) )
// Addr is vmess addr // Addr is vmess addr.
type Addr []byte type Addr []byte
// Port is vmess addr port // Port is vmess addr port.
type Port uint16 type Port uint16
// ParseAddr parses the address in string s // ParseAddr parses the address in string s.
func ParseAddr(s string) (Atyp, Addr, Port, error) { func ParseAddr(s string) (Atyp, Addr, Port, error) {
var atyp Atyp var atyp Atyp
var addr Addr var addr Addr

View File

@ -16,7 +16,7 @@ type aeadWriter struct {
iv []byte iv []byte
} }
// AEADWriter returns a aead writer // AEADWriter returns a aead writer.
func AEADWriter(w io.Writer, aead cipher.AEAD, iv []byte) io.Writer { func AEADWriter(w io.Writer, aead cipher.AEAD, iv []byte) io.Writer {
return &aeadWriter{ return &aeadWriter{
Writer: w, Writer: w,
@ -79,7 +79,7 @@ type aeadReader struct {
iv []byte iv []byte
} }
// AEADReader returns a aead reader // AEADReader returns a aead reader.
func AEADReader(r io.Reader, aead cipher.AEAD, iv []byte) io.Reader { func AEADReader(r io.Reader, aead cipher.AEAD, iv []byte) io.Reader {
return &aeadReader{ return &aeadReader{
Reader: r, Reader: r,

View File

@ -16,7 +16,7 @@ type chunkedWriter struct {
io.Writer io.Writer
} }
// ChunkedWriter returns a chunked writer // ChunkedWriter returns a chunked writer.
func ChunkedWriter(w io.Writer) io.Writer { func ChunkedWriter(w io.Writer) io.Writer {
return &chunkedWriter{Writer: w} return &chunkedWriter{Writer: w}
} }
@ -52,7 +52,7 @@ type chunkedReader struct {
left int left int
} }
// ChunkedReader returns a chunked reader // ChunkedReader returns a chunked reader.
func ChunkedReader(r io.Reader) io.Reader { func ChunkedReader(r io.Reader) io.Reader {
return &chunkedReader{Reader: r} return &chunkedReader{Reader: r}
} }

View File

@ -39,7 +39,7 @@ const (
CmdUDP byte = 2 CmdUDP byte = 2
) )
// Client is a vmess client // Client is a vmess client.
type Client struct { type Client struct {
users []*User users []*User
count int count int
@ -47,7 +47,7 @@ type Client struct {
security byte security byte
} }
// Conn is a connection to vmess server // Conn is a connection to vmess server.
type Conn struct { type Conn struct {
user *User user *User
opt byte opt byte
@ -142,7 +142,7 @@ func (c *Client) NewConn(rc net.Conn, target string) (*Conn, error) {
return conn, nil return conn, nil
} }
// Auth send auth info: HMAC("md5", UUID, UTC) // Auth send auth info: HMAC("md5", UUID, UTC).
func (c *Conn) Auth() error { func (c *Conn) Auth() error {
ts := pool.GetBuffer(8) ts := pool.GetBuffer(8)
defer pool.PutBuffer(ts) defer pool.PutBuffer(ts)

View File

@ -12,13 +12,13 @@ import (
"github.com/nadoo/glider/common/pool" "github.com/nadoo/glider/common/pool"
) )
// User of vmess client // User of vmess client.
type User struct { type User struct {
UUID [16]byte UUID [16]byte
CmdKey [16]byte CmdKey [16]byte
} }
// NewUser . // NewUser returns a new user.
func NewUser(uuid [16]byte) *User { func NewUser(uuid [16]byte) *User {
u := &User{UUID: uuid} u := &User{UUID: uuid}
copy(u.CmdKey[:], GetKey(uuid)) copy(u.CmdKey[:], GetKey(uuid))
@ -38,7 +38,7 @@ func nextID(oldID [16]byte) (newID [16]byte) {
} }
} }
// GenAlterIDUsers generates users according to primary user's id and alterID // GenAlterIDUsers generates users according to primary user's id and alterID.
func (u *User) GenAlterIDUsers(alterID int) []*User { func (u *User) GenAlterIDUsers(alterID int) []*User {
users := make([]*User, alterID) users := make([]*User, alterID)
preID := u.UUID preID := u.UUID
@ -63,7 +63,7 @@ func StrToUUID(s string) (uuid [16]byte, err error) {
return return
} }
// GetKey returns the key of AES-128-CFB encrypter // GetKey returns the key of AES-128-CFB encrypter.
// KeyMD5(UUID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21')) // KeyMD5(UUID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21'))
func GetKey(uuid [16]byte) []byte { func GetKey(uuid [16]byte) []byte {
md5hash := md5.New() md5hash := md5.New()
@ -72,7 +72,7 @@ func GetKey(uuid [16]byte) []byte {
return md5hash.Sum(nil) return md5hash.Sum(nil)
} }
// TimestampHash returns the iv of AES-128-CFB encrypter // TimestampHash returns the iv of AES-128-CFB encrypter.
// IVMD5(X + X + X + X)X = []byte(timestamp.now) (8 bytes, Big Endian) // IVMD5(X + X + X + X)X = []byte(timestamp.now) (8 bytes, Big Endian)
func TimestampHash(t time.Time) []byte { func TimestampHash(t time.Time) []byte {
ts := pool.GetBuffer(8) ts := pool.GetBuffer(8)

View File

@ -11,7 +11,7 @@ import (
"github.com/nadoo/glider/strategy" "github.com/nadoo/glider/strategy"
) )
// Config , every rule dialer points to a rule file // Config of rule dialer.
type Config struct { type Config struct {
Name string Name string
@ -26,7 +26,7 @@ type Config struct {
CIDR []string CIDR []string
} }
// NewConfFromFile . // NewConfFromFile returns a new config from file.
func NewConfFromFile(ruleFile string) (*Config, error) { func NewConfFromFile(ruleFile string) (*Config, error) {
p := &Config{Name: ruleFile} p := &Config{Name: ruleFile}
@ -58,7 +58,7 @@ func NewConfFromFile(ruleFile string) (*Config, error) {
return p, err return p, err
} }
// ListDir returns file list named with suffix in dirPth // ListDir returns file list named with suffix in dirPth.
func ListDir(dirPth string, suffix string) (files []string, err error) { func ListDir(dirPth string, suffix string) (files []string, err error) {
files = make([]string, 0, 10) files = make([]string, 0, 10)
dir, err := ioutil.ReadDir(dirPth) dir, err := ioutil.ReadDir(dirPth)
@ -66,12 +66,12 @@ func ListDir(dirPth string, suffix string) (files []string, err error) {
return nil, err return nil, err
} }
PthSep := string(os.PathSeparator) PthSep := string(os.PathSeparator)
suffix = strings.ToUpper(suffix) suffix = strings.ToLower(suffix)
for _, fi := range dir { for _, fi := range dir {
if fi.IsDir() { if fi.IsDir() {
continue continue
} }
if strings.HasSuffix(strings.ToUpper(fi.Name()), suffix) { if strings.HasSuffix(strings.ToLower(fi.Name()), suffix) {
files = append(files, dirPth+PthSep+fi.Name()) files = append(files, dirPth+PthSep+fi.Name())
} }
} }

View File

@ -10,7 +10,7 @@ import (
"github.com/nadoo/glider/strategy" "github.com/nadoo/glider/strategy"
) )
// Proxy struct // Proxy struct.
type Proxy struct { type Proxy struct {
proxy *strategy.Proxy proxy *strategy.Proxy
proxies []*strategy.Proxy proxies []*strategy.Proxy
@ -90,13 +90,10 @@ func (p *Proxy) nextProxy(dstAddr string) *strategy.Proxy {
} }
domainParts := strings.Split(host, ".") host = strings.ToLower(host)
length := len(domainParts) for i := len(host); i != -1; {
for i := length - 1; i >= 0; i-- { i = strings.LastIndexByte(host[:i], '.')
domain := strings.Join(domainParts[i:length], ".") if proxy, ok := p.domainMap.Load(host[i+1:]); ok {
// find in domainMap
if proxy, ok := p.domainMap.Load(domain); ok {
return proxy.(*strategy.Proxy) return proxy.(*strategy.Proxy)
} }
} }
@ -117,15 +114,12 @@ func (p *Proxy) Record(dialer proxy.Dialer, success bool) {
// AddDomainIP used to update ipMap rules according to domainMap rule. // AddDomainIP used to update ipMap rules according to domainMap rule.
func (p *Proxy) AddDomainIP(domain, ip string) error { func (p *Proxy) AddDomainIP(domain, ip string) error {
if ip != "" { if ip != "" {
domainParts := strings.Split(domain, ".") domain = strings.ToLower(domain)
length := len(domainParts) for i := len(domain); i != -1; {
for i := length - 1; i >= 0; i-- { i = strings.LastIndexByte(domain[:i], '.')
pDomain := strings.ToLower(strings.Join(domainParts[i:length], ".")) if dialer, ok := p.domainMap.Load(domain[i+1:]); ok {
// find in domainMap
if dialer, ok := p.domainMap.Load(pDomain); ok {
p.ipMap.Store(ip, dialer) p.ipMap.Store(ip, dialer)
log.F("[rule] add ip=%s, based on rule: domain=%s & domain/ip: %s/%s\n", ip, pDomain, domain, ip) log.F("[rule] add ip=%s, based on rule: domain=%s & domain/ip: %s/%s\n", ip, domain[i+1:], domain, ip)
} }
} }
} }