Skip to content

Commit 795952e

Browse files
authored
Merge pull request #6 from lordixir/main
bug fix
2 parents 215ee8d + debd4db commit 795952e

File tree

5 files changed

+172
-41
lines changed

5 files changed

+172
-41
lines changed

modules/dns_resolver.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"ipmap/config"
66
"net"
7+
"strings"
78
"time"
89
)
910

@@ -18,6 +19,19 @@ func ReverseDNS(ip string) string {
1819
d := net.Dialer{
1920
Timeout: time.Second * 2,
2021
}
22+
// Use custom DNS servers if configured
23+
if len(config.DNSServers) > 0 {
24+
for _, dns := range config.DNSServers {
25+
dnsAddr := strings.TrimSpace(dns)
26+
if !strings.Contains(dnsAddr, ":") {
27+
dnsAddr = dnsAddr + ":53"
28+
}
29+
conn, err := d.DialContext(ctx, network, dnsAddr)
30+
if err == nil {
31+
return conn, nil
32+
}
33+
}
34+
}
2135
return d.DialContext(ctx, network, address)
2236
},
2337
}

modules/request.go

Lines changed: 125 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,128 @@ import (
77
"ipmap/config"
88
"net"
99
"net/http"
10+
"net/url"
1011
"strconv"
1112
"strings"
13+
"sync"
1214
"time"
1315

1416
"github.com/corpix/uarand"
1517
)
1618

17-
// Reusable HTTP client with connection pooling
18-
var httpClient *http.Client
19+
// HTTP client with lazy initialization
20+
var (
21+
httpClient *http.Client
22+
httpClientOnce sync.Once
23+
lastProxyURL string
24+
lastDNSServers string
25+
clientMu sync.RWMutex
26+
)
27+
28+
// GetHTTPClient returns the HTTP client, creating or recreating if config changed
29+
func GetHTTPClient() *http.Client {
30+
clientMu.RLock()
31+
currentProxy := config.ProxyURL
32+
currentDNS := strings.Join(config.DNSServers, ",")
33+
needsRecreate := httpClient != nil && (lastProxyURL != currentProxy || lastDNSServers != currentDNS)
34+
clientMu.RUnlock()
35+
36+
if needsRecreate {
37+
clientMu.Lock()
38+
// Double-check after acquiring write lock
39+
if lastProxyURL != currentProxy || lastDNSServers != currentDNS {
40+
httpClient = createHTTPClientWithConfig()
41+
lastProxyURL = currentProxy
42+
lastDNSServers = currentDNS
43+
config.VerboseLog("HTTP client recreated with new config (Proxy: %s, DNS: %s)", currentProxy, currentDNS)
44+
}
45+
clientMu.Unlock()
46+
return httpClient
47+
}
48+
49+
httpClientOnce.Do(func() {
50+
clientMu.Lock()
51+
defer clientMu.Unlock()
52+
httpClient = createHTTPClientWithConfig()
53+
lastProxyURL = config.ProxyURL
54+
lastDNSServers = strings.Join(config.DNSServers, ",")
55+
})
56+
57+
return httpClient
58+
}
59+
60+
// createCustomDialer creates a dialer with optional custom DNS servers
61+
func createCustomDialer() *net.Dialer {
62+
dialer := &net.Dialer{
63+
Timeout: 10 * time.Second,
64+
KeepAlive: 30 * time.Second,
65+
}
66+
return dialer
67+
}
68+
69+
// createDialContext creates a DialContext function with optional custom DNS
70+
func createDialContext() func(ctx context.Context, network, addr string) (net.Conn, error) {
71+
dialer := createCustomDialer()
72+
73+
if len(config.DNSServers) == 0 {
74+
return dialer.DialContext
75+
}
76+
77+
// Custom DNS resolver
78+
resolver := &net.Resolver{
79+
PreferGo: true,
80+
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
81+
d := net.Dialer{Timeout: 5 * time.Second}
82+
// Use first available custom DNS server
83+
for _, dns := range config.DNSServers {
84+
dnsAddr := strings.TrimSpace(dns)
85+
if !strings.Contains(dnsAddr, ":") {
86+
dnsAddr = dnsAddr + ":53"
87+
}
88+
conn, err := d.DialContext(ctx, "udp", dnsAddr)
89+
if err == nil {
90+
return conn, nil
91+
}
92+
}
93+
// Fallback to default
94+
return d.DialContext(ctx, network, address)
95+
},
96+
}
97+
98+
config.VerboseLog("Using custom DNS servers: %v", config.DNSServers)
99+
100+
return func(ctx context.Context, network, addr string) (net.Conn, error) {
101+
// Split host and port
102+
host, port, err := net.SplitHostPort(addr)
103+
if err != nil {
104+
return dialer.DialContext(ctx, network, addr)
105+
}
106+
107+
// Resolve using custom DNS
108+
ips, err := resolver.LookupIPAddr(ctx, host)
109+
if err != nil || len(ips) == 0 {
110+
// Fallback to normal resolution
111+
return dialer.DialContext(ctx, network, addr)
112+
}
19113

20-
func init() {
21-
httpClient = createHTTPClient()
114+
// Try each resolved IP
115+
for _, ip := range ips {
116+
conn, err := dialer.DialContext(ctx, network, net.JoinHostPort(ip.String(), port))
117+
if err == nil {
118+
return conn, nil
119+
}
120+
}
121+
122+
// Fallback
123+
return dialer.DialContext(ctx, network, addr)
124+
}
22125
}
23126

24-
func createHTTPClient() *http.Client {
127+
func createHTTPClientWithConfig() *http.Client {
25128
transport := &http.Transport{
26129
TLSClientConfig: &tls.Config{
27130
InsecureSkipVerify: true,
28131
MinVersion: tls.VersionTLS12,
29-
// Allow more cipher suites for compatibility
30132
CipherSuites: []uint16{
31133
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
32134
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
@@ -36,21 +138,25 @@ func createHTTPClient() *http.Client {
36138
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
37139
},
38140
},
39-
// Connection pooling
40-
MaxIdleConns: 100,
41-
MaxIdleConnsPerHost: 10,
42-
IdleConnTimeout: 90 * time.Second,
43-
// Timeouts
141+
MaxIdleConns: 100,
142+
MaxIdleConnsPerHost: 10,
143+
IdleConnTimeout: 90 * time.Second,
44144
TLSHandshakeTimeout: 10 * time.Second,
45145
ResponseHeaderTimeout: 10 * time.Second,
46146
ExpectContinueTimeout: 1 * time.Second,
47-
// Custom dialer with timeout
48-
DialContext: (&net.Dialer{
49-
Timeout: 10 * time.Second,
50-
KeepAlive: 30 * time.Second,
51-
}).DialContext,
52-
// Enable HTTP/2
53-
ForceAttemptHTTP2: true,
147+
DialContext: createDialContext(),
148+
ForceAttemptHTTP2: true,
149+
}
150+
151+
// Configure proxy if specified
152+
if config.ProxyURL != "" {
153+
proxyURL, err := url.Parse(config.ProxyURL)
154+
if err != nil {
155+
config.ErrorLog("Invalid proxy URL '%s': %v", config.ProxyURL, err)
156+
} else {
157+
transport.Proxy = http.ProxyURL(proxyURL)
158+
config.VerboseLog("Using proxy: %s", config.ProxyURL)
159+
}
54160
}
55161

56162
return &http.Client{
@@ -59,7 +165,6 @@ func createHTTPClient() *http.Client {
59165
if len(via) >= 10 {
60166
return http.ErrUseLastResponse
61167
}
62-
// Preserve headers on redirect
63168
for key, val := range via[0].Header {
64169
if _, ok := req.Header[key]; !ok {
65170
req.Header[key] = val
@@ -118,7 +223,7 @@ func RequestFuncWithRetry(ip string, url string, timeout int, maxRetries int) []
118223
req.Header.Set("Sec-Ch-Ua-Mobile", "?0")
119224
req.Header.Set("Sec-Ch-Ua-Platform", `"Windows"`)
120225

121-
resp, err := httpClient.Do(req)
226+
resp, err := GetHTTPClient().Do(req)
122227

123228
if err != nil {
124229
cancel() // Cancel on error

modules/resolve_site.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ func ResolveSite(IPAddress []string, Websites [][]string, DomainTitle string, IP
1717
config.VerboseLog("Starting scan with %d concurrent workers", workerCount)
1818
sem := make(chan struct{}, workerCount)
1919

20+
// Create rate limiter
21+
rateLimiter := NewRateLimiter(config.RateLimit, config.RateLimit*2)
22+
if rateLimiter.IsEnabled() {
23+
config.VerboseLog("Rate limiting enabled: %d requests/second", config.RateLimit)
24+
}
25+
2026
// Create progress bar
2127
bar := progressbar.NewOptions(len(IPAddress),
2228
progressbar.OptionEnableColorCodes(true),
@@ -41,6 +47,9 @@ func ResolveSite(IPAddress []string, Websites [][]string, DomainTitle string, IP
4147
defer wg.Done()
4248
defer func() { <-sem }()
4349

50+
// Wait for rate limiter before making request
51+
rateLimiter.Wait()
52+
4453
site := GetSite(ip, domain, timeout)
4554
if len(site) > 0 {
4655

tools/find_asn.go

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,37 +8,36 @@ import (
88
"time"
99
)
1010

11-
var (
12-
IPBlocks []string
13-
IPAddress []string
14-
Websites [][]string
15-
)
16-
1711
func FindASN(asn string, domain string, domainTitle string, con bool, export bool, timeout int, interruptData *modules.InterruptData) {
12+
// Use local variables instead of global to avoid race conditions
13+
var ipBlocks []string
14+
var ipAddress []string
15+
var websites [][]string
16+
1817
re := regexp.MustCompile(`(?m)route:\s+([0-9\.\/]+)$`)
1918
for _, match := range re.FindAllStringSubmatch(modules.FindIPBlocks(asn), -1) {
20-
IPBlocks = append(IPBlocks, match[1])
19+
ipBlocks = append(ipBlocks, match[1])
2120
}
2221

23-
for _, block := range IPBlocks {
22+
for _, block := range ipBlocks {
2423
ips, err := modules.CalcIPAddress(block)
2524
if err != nil {
2625
return
2726
}
2827

29-
IPAddress = append(IPAddress, ips...)
28+
ipAddress = append(ipAddress, ips...)
3029
}
3130

3231
// Update interrupt data with IP blocks
3332
if interruptData != nil {
34-
interruptData.IPBlocks = IPBlocks
33+
interruptData.IPBlocks = ipBlocks
3534
}
3635

3736
fmt.Println("ASN: " + asn +
38-
"\nIP Block: " + strconv.Itoa(len(IPBlocks)) +
39-
"\nIP Address: " + strconv.Itoa(len(IPAddress)) +
37+
"\nIP Block: " + strconv.Itoa(len(ipBlocks)) +
38+
"\nIP Address: " + strconv.Itoa(len(ipAddress)) +
4039
"\nStart Time: " + time.Now().Local().String() +
41-
"\nEnd Time: " + time.Now().Add((time.Millisecond*time.Duration(timeout))*time.Duration(len(IPAddress))).Local().String())
40+
"\nEnd Time: " + time.Now().Add((time.Millisecond*time.Duration(timeout))*time.Duration(len(ipAddress))).Local().String())
4241

43-
modules.ResolveSite(IPAddress, Websites, domainTitle, IPBlocks, domain, con, export, timeout, interruptData)
42+
modules.ResolveSite(ipAddress, websites, domainTitle, ipBlocks, domain, con, export, timeout, interruptData)
4443
}

tools/find_ip.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,24 @@ import (
77
"time"
88
)
99

10-
func FindIP(IPBlocks []string, domain string, domainTitle string, con bool, export bool, timeout int, interruptData *modules.InterruptData) {
11-
for _, block := range IPBlocks {
10+
func FindIP(ipBlocks []string, domain string, domainTitle string, con bool, export bool, timeout int, interruptData *modules.InterruptData) {
11+
// Use local variables instead of global to avoid race conditions
12+
var ipAddress []string
13+
var websites [][]string
14+
15+
for _, block := range ipBlocks {
1216
ips, err := modules.CalcIPAddress(block)
1317
if err != nil {
1418
return
1519
}
1620

17-
IPAddress = append(IPAddress, ips...)
21+
ipAddress = append(ipAddress, ips...)
1822
}
1923

20-
fmt.Println("IP Block: " + strconv.Itoa(len(IPBlocks)) +
21-
"\nIP Address: " + strconv.Itoa(len(IPAddress)) +
24+
fmt.Println("IP Block: " + strconv.Itoa(len(ipBlocks)) +
25+
"\nIP Address: " + strconv.Itoa(len(ipAddress)) +
2226
"\nStart Time: " + time.Now().Local().String() +
23-
"\nEnd Time: " + time.Now().Add((time.Millisecond*time.Duration(timeout))*time.Duration(len(IPAddress))).Local().String())
27+
"\nEnd Time: " + time.Now().Add((time.Millisecond*time.Duration(timeout))*time.Duration(len(ipAddress))).Local().String())
2428

25-
modules.ResolveSite(IPAddress, Websites, domainTitle, IPBlocks, domain, con, export, timeout, interruptData)
29+
modules.ResolveSite(ipAddress, websites, domainTitle, ipBlocks, domain, con, export, timeout, interruptData)
2630
}

0 commit comments

Comments
 (0)