Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/pkg/protocols/dns/dnsclientpool/clientpool.go
2072 views
1
package dnsclientpool
2
3
import (
4
"strconv"
5
"strings"
6
"sync"
7
8
"github.com/pkg/errors"
9
"github.com/projectdiscovery/nuclei/v3/pkg/types"
10
"github.com/projectdiscovery/retryabledns"
11
mapsutil "github.com/projectdiscovery/utils/maps"
12
)
13
14
var (
15
clientPool *mapsutil.SyncLockMap[string, *retryabledns.Client]
16
17
normalClient *retryabledns.Client
18
m sync.Mutex
19
)
20
21
// defaultResolvers contains the list of resolvers known to be trusted.
22
var defaultResolvers = []string{
23
"1.1.1.1:53", // Cloudflare
24
"1.0.0.1:53", // Cloudflare
25
"8.8.8.8:53", // Google
26
"8.8.4.4:53", // Google
27
}
28
29
// Init initializes the client pool implementation
30
func Init(options *types.Options) error {
31
m.Lock()
32
defer m.Unlock()
33
34
// Don't create clients if already created in the past.
35
if normalClient != nil {
36
return nil
37
}
38
clientPool = mapsutil.NewSyncLockMap[string, *retryabledns.Client]()
39
40
resolvers := defaultResolvers
41
if len(options.InternalResolversList) > 0 {
42
resolvers = options.InternalResolversList
43
}
44
var err error
45
normalClient, err = retryabledns.New(resolvers, 1)
46
if err != nil {
47
return errors.Wrap(err, "could not create dns client")
48
}
49
return nil
50
}
51
52
func getNormalClient() *retryabledns.Client {
53
m.Lock()
54
defer m.Unlock()
55
return normalClient
56
}
57
58
// Configuration contains the custom configuration options for a client
59
type Configuration struct {
60
// Retries contains the retries for the dns client
61
Retries int
62
// Resolvers contains the specific per request resolvers
63
Resolvers []string
64
// Proxy contains the proxy to use for the dns client
65
Proxy string
66
}
67
68
// Hash returns the hash of the configuration to allow client pooling
69
func (c *Configuration) Hash() string {
70
builder := &strings.Builder{}
71
builder.WriteString("r")
72
builder.WriteString(strconv.Itoa(c.Retries))
73
builder.WriteString("l")
74
builder.WriteString(strings.Join(c.Resolvers, ""))
75
builder.WriteString("p")
76
builder.WriteString(c.Proxy)
77
hash := builder.String()
78
return hash
79
}
80
81
// Get creates or gets a client for the protocol based on custom configuration
82
func Get(options *types.Options, configuration *Configuration) (*retryabledns.Client, error) {
83
if (configuration.Retries <= 1) && len(configuration.Resolvers) == 0 {
84
return getNormalClient(), nil
85
}
86
hash := configuration.Hash()
87
if client, ok := clientPool.Get(hash); ok {
88
return client, nil
89
}
90
91
resolvers := defaultResolvers
92
if len(options.InternalResolversList) > 0 {
93
resolvers = options.InternalResolversList
94
} else if len(configuration.Resolvers) > 0 {
95
resolvers = configuration.Resolvers
96
}
97
client, err := retryabledns.NewWithOptions(retryabledns.Options{
98
BaseResolvers: resolvers,
99
MaxRetries: configuration.Retries,
100
Proxy: options.AliveSocksProxy,
101
})
102
if err != nil {
103
return nil, errors.Wrap(err, "could not create dns client")
104
}
105
_ = clientPool.Set(hash, client)
106
107
return client, nil
108
}
109
110