Use proxy for dns and ssl templates (#6255)

* Use proxy for dns and ssl templates

- while using template execute level function we need to override custom dialer

* rename overridedialer to customdialer

* Add proxy into hash

- proxy client is shared between non proxy requests

* add dialer into request object

- use request.dialer instead of global variable

* resolve comments

* rename dialer
This commit is contained in:
Shubham Rasal
2025-06-16 22:24:52 +05:30
committed by GitHub
parent fc6d5a7773
commit f89a6d33e9
10 changed files with 51 additions and 14 deletions

View File

@@ -185,6 +185,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
func (request *Request) getDnsClient(options *protocols.ExecutorOptions, metadata map[string]interface{}) (*retryabledns.Client, error) {
dnsClientOptions := &dnsclientpool.Configuration{
Retries: request.Retries,
Proxy: options.Options.AliveSocksProxy,
}
if len(request.Resolvers) > 0 {
if len(request.Resolvers) > 0 {

View File

@@ -51,6 +51,8 @@ type Configuration struct {
Retries int
// Resolvers contains the specific per request resolvers
Resolvers []string
// Proxy contains the proxy to use for the dns client
Proxy string
}
// Hash returns the hash of the configuration to allow client pooling
@@ -60,6 +62,8 @@ func (c *Configuration) Hash() string {
builder.WriteString(strconv.Itoa(c.Retries))
builder.WriteString("l")
builder.WriteString(strings.Join(c.Resolvers, ""))
builder.WriteString("p")
builder.WriteString(c.Proxy)
hash := builder.String()
return hash
}
@@ -83,7 +87,11 @@ func Get(options *types.Options, configuration *Configuration) (*retryabledns.Cl
} else if len(configuration.Resolvers) > 0 {
resolvers = configuration.Resolvers
}
client, err := retryabledns.New(resolvers, configuration.Retries)
client, err := retryabledns.NewWithOptions(retryabledns.Options{
BaseResolvers: resolvers,
MaxRetries: configuration.Retries,
Proxy: options.AliveSocksProxy,
})
if err != nil {
return nil, errors.Wrap(err, "could not create dns client")
}

View File

@@ -11,6 +11,7 @@ import (
json "github.com/json-iterator/go"
"github.com/pkg/errors"
"github.com/projectdiscovery/fastdialer/fastdialer"
_ "github.com/projectdiscovery/nuclei/v3/pkg/fuzz/analyzers/time"
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz"
@@ -22,6 +23,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/http/httpclientpool"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/network/networkclientpool"
httputil "github.com/projectdiscovery/nuclei/v3/pkg/protocols/utils/http"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/stats"
"github.com/projectdiscovery/rawhttp"
@@ -144,6 +146,7 @@ type Request struct {
generator *generators.PayloadGenerator // optional, only enabled when using payloads
httpClient *retryablehttp.Client
rawhttpClient *rawhttp.Client
dialer *fastdialer.Dialer
// description: |
// SelfContained specifies if the request is self-contained.
@@ -348,6 +351,15 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
}
request.customHeaders = make(map[string]string)
request.httpClient = client
dialer, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{
CustomDialer: options.CustomFastdialer,
})
if err != nil {
return errors.Wrap(err, "could not get dialer")
}
request.dialer = dialer
request.options = options
for _, option := range request.options.Options.CustomHeaders {
parts := strings.SplitN(option, ":", 2)

View File

@@ -841,7 +841,7 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ
if input.MetaInput.CustomIP != "" {
outputEvent["ip"] = input.MetaInput.CustomIP
} else {
outputEvent["ip"] = protocolstate.Dialer.GetDialedIP(hostname)
outputEvent["ip"] = request.dialer.GetDialedIP(hostname)
// try getting cname
request.addCNameIfAvailable(hostname, outputEvent)
}
@@ -1085,11 +1085,11 @@ func (request *Request) validateNFixEvent(input *contextargs.Context, gr *genera
// addCNameIfAvailable adds the cname to the event if available
func (request *Request) addCNameIfAvailable(hostname string, outputEvent map[string]interface{}) {
if protocolstate.Dialer == nil {
if request.dialer == nil {
return
}
data, err := protocolstate.Dialer.GetDNSData(hostname)
data, err := request.dialer.GetDNSData(hostname)
if err == nil {
switch len(data.CNAME) {
case 0:

View File

@@ -237,7 +237,9 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
}
// Create a client for the class
client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{})
client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{
CustomDialer: options.CustomFastdialer,
})
if err != nil {
return errors.Wrap(err, "could not get network client")
}
@@ -259,7 +261,3 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
func (request *Request) Requests() int {
return len(request.Address)
}
func (request *Request) SetDialer(dialer *fastdialer.Dialer) {
request.dialer = dialer
}

View File

@@ -21,7 +21,9 @@ func Init(options *types.Options) error {
}
// Configuration contains the custom configuration options for a client
type Configuration struct{}
type Configuration struct {
CustomDialer *fastdialer.Dialer
}
// Hash returns the hash of the configuration to allow client pooling
func (c *Configuration) Hash() string {
@@ -30,5 +32,10 @@ func (c *Configuration) Hash() string {
// Get creates or gets a client for the protocol based on custom configuration
func Get(options *types.Options, configuration *Configuration /*TODO review unused parameters*/) (*fastdialer.Dialer, error) {
if configuration != nil && configuration.CustomDialer != nil {
return configuration.CustomDialer, nil
}
return normalClient, nil
}

View File

@@ -25,9 +25,9 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/helpers/eventcreator"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/helpers/responsehighlighter"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/replacer"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/utils/vardump"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/network/networkclientpool"
protocolutils "github.com/projectdiscovery/nuclei/v3/pkg/protocols/utils"
templateTypes "github.com/projectdiscovery/nuclei/v3/pkg/templates/types"
errorutil "github.com/projectdiscovery/utils/errors"
@@ -64,7 +64,11 @@ func (request *Request) getOpenPorts(target *contextargs.Context) ([]string, err
errs = append(errs, err)
continue
}
conn, err := protocolstate.Dialer.Dial(target.Context(), "tcp", addr)
if request.dialer == nil {
request.dialer, _ = networkclientpool.Get(request.options.Options, &networkclientpool.Configuration{})
}
conn, err := request.dialer.Dial(target.Context(), "tcp", addr)
if err != nil {
errs = append(errs, err)
continue

View File

@@ -5,6 +5,7 @@ import (
"encoding/base64"
"sync/atomic"
"github.com/projectdiscovery/fastdialer/fastdialer"
"github.com/projectdiscovery/ratelimit"
mapsutil "github.com/projectdiscovery/utils/maps"
stringsutil "github.com/projectdiscovery/utils/strings"
@@ -132,6 +133,8 @@ type ExecutorOptions struct {
ExportReqURLPattern bool
// GlobalMatchers is the storage for global matchers with http passive templates
GlobalMatchers *globalmatchers.Storage
// CustomFastdialer is a fastdialer dialer instance
CustomFastdialer *fastdialer.Dialer
}
// todo: centralizing components is not feasible with current clogged architecture

View File

@@ -115,7 +115,9 @@ func (request *Request) IsClusterable() bool {
func (request *Request) Compile(options *protocols.ExecutorOptions) error {
request.options = options
client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{})
client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{
CustomDialer: options.CustomFastdialer,
})
if err != nil {
return errorutil.NewWithTag("ssl", "could not get network client").Wrap(err)
}

View File

@@ -100,7 +100,9 @@ const (
func (request *Request) Compile(options *protocols.ExecutorOptions) error {
request.options = options
client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{})
client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{
CustomDialer: options.CustomFastdialer,
})
if err != nil {
return errors.Wrap(err, "could not get network client")
}