Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/pkg/protocols/headless/engine/http_client.go
2840 views
1
package engine
2
3
import (
4
"context"
5
"crypto/tls"
6
"fmt"
7
"net"
8
"net/http"
9
"net/http/cookiejar"
10
"net/url"
11
"time"
12
13
"golang.org/x/net/proxy"
14
15
"github.com/projectdiscovery/fastdialer/fastdialer/ja3/impersonate"
16
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
17
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/utils"
18
"github.com/projectdiscovery/nuclei/v3/pkg/types"
19
)
20
21
// newHttpClient creates a new http client for headless communication with a timeout
22
func newHttpClient(options *types.Options) (*http.Client, error) {
23
dialers := protocolstate.GetDialersWithId(options.ExecutionId)
24
if dialers == nil {
25
return nil, fmt.Errorf("dialers not initialized for %s", options.ExecutionId)
26
}
27
// Set the base TLS configuration definition
28
tlsConfig := &tls.Config{
29
Renegotiation: tls.RenegotiateOnceAsClient,
30
InsecureSkipVerify: true,
31
MinVersion: tls.VersionTLS10,
32
ClientSessionCache: tls.NewLRUClientSessionCache(1024),
33
}
34
35
if options.SNI != "" {
36
tlsConfig.ServerName = options.SNI
37
}
38
39
// Add the client certificate authentication to the request if it's configured
40
var err error
41
tlsConfig, err = utils.AddConfiguredClientCertToRequest(tlsConfig, options)
42
if err != nil {
43
return nil, err
44
}
45
46
transport := &http.Transport{
47
ForceAttemptHTTP2: options.ForceAttemptHTTP2,
48
DialContext: dialers.Fastdialer.Dial,
49
DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
50
if options.TlsImpersonate {
51
return dialers.Fastdialer.DialTLSWithConfigImpersonate(ctx, network, addr, tlsConfig, impersonate.Random, nil)
52
}
53
if options.HasClientCertificates() || options.ForceAttemptHTTP2 {
54
return dialers.Fastdialer.DialTLSWithConfig(ctx, network, addr, tlsConfig)
55
}
56
return dialers.Fastdialer.DialTLS(ctx, network, addr)
57
},
58
MaxIdleConns: 500,
59
MaxIdleConnsPerHost: 500,
60
MaxConnsPerHost: 500,
61
TLSClientConfig: tlsConfig,
62
}
63
if options.AliveHttpProxy != "" {
64
if proxyURL, err := url.Parse(options.AliveHttpProxy); err == nil {
65
transport.Proxy = http.ProxyURL(proxyURL)
66
}
67
} else if options.AliveSocksProxy != "" {
68
socksURL, proxyErr := url.Parse(options.AliveSocksProxy)
69
if proxyErr != nil {
70
return nil, err
71
}
72
dialer, err := proxy.FromURL(socksURL, proxy.Direct)
73
if err != nil {
74
return nil, err
75
}
76
77
dc := dialer.(interface {
78
DialContext(ctx context.Context, network, addr string) (net.Conn, error)
79
})
80
transport.DialContext = dc.DialContext
81
}
82
83
jar, _ := cookiejar.New(nil)
84
85
httpclient := &http.Client{
86
Transport: transport,
87
Timeout: time.Duration(options.Timeout*3) * time.Second,
88
Jar: jar,
89
CheckRedirect: func(req *http.Request, via []*http.Request) error {
90
// the browser should follow redirects not us
91
return http.ErrUseLastResponse
92
},
93
}
94
95
return httpclient, nil
96
}
97
98