This repository has been archived by the owner on May 10, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 38
/
main.go
216 lines (181 loc) · 4.3 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
package main
import (
"bufio"
"crypto/tls"
"flag"
"fmt"
"log"
"net"
"net/http"
"os"
"strings"
"sync"
"time"
jsoniter "github.com/json-iterator/go"
"github.com/yl2chen/cidranger"
)
// Client checks for CDN based IPs which should be excluded
// during scans since they belong to third party firewalls.
type Client struct {
Options *Options
ranges map[string][]string
rangers map[string]cidranger.Ranger
}
type Options struct {
Cache bool
}
// New creates a new firewall IP checking client.
func New() (*Client, error) {
return new(&Options{})
}
// NewWithCache creates a new firewall IP with cached data from project discovery (faster)
func NewWithCache() (*Client, error) {
return new(&Options{Cache: true})
}
func new(options *Options) (*Client, error) {
httpClient := &http.Client{
Transport: &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 100,
TLSClientConfig: &tls.Config{
Renegotiation: tls.RenegotiateOnceAsClient,
InsecureSkipVerify: true,
},
},
Timeout: time.Duration(30) * time.Second,
}
client := &Client{Options: options}
err := client.getCDNDataFromCache(httpClient)
if err != nil {
return nil, err
}
return client, nil
}
func scrapeProjectDiscovery(httpClient *http.Client) (map[string][]string, error) {
var (
err error
response *http.Response
retries int = 2
url string
url_fallback string
data map[string][]string
)
url = "https://cdn.nuclei.sh"
url_fallback = "https://raw.githubusercontent.com/six2dez/ipcdn/main/ranges.txt"
for retries > 0 {
response, err = http.Get(url)
if err != nil {
url = url_fallback
retries -= 1
} else {
break
}
}
if response != nil {
defer response.Body.Close()
if err := jsoniter.NewDecoder(response.Body).Decode(&data); err != nil {
return nil, err
}
} else {
return nil, err
}
return data, nil
}
func (c *Client) getCDNDataFromCache(httpClient *http.Client) error {
var err error
c.ranges, err = scrapeProjectDiscovery(httpClient)
if err != nil {
return err
}
c.rangers = make(map[string]cidranger.Ranger)
for provider, ranges := range c.ranges {
ranger := cidranger.NewPCTrieRanger()
for _, cidr := range ranges {
_, network, err := net.ParseCIDR(cidr)
if err != nil {
continue
}
_ = ranger.Insert(cidranger.NewBasicRangerEntry(*network))
}
c.rangers[provider] = ranger
}
return nil
}
// Check checks if an IP is contained in the blacklist
func (c *Client) Check(ip net.IP) (bool, string, error) {
for provider, ranger := range c.rangers {
if contains, err := ranger.Contains(ip); contains {
return true, provider, err
}
}
return false, "", nil
}
// Ranges returns the providers and ranges for the cdn client
func (c *Client) Ranges() map[string][]string {
return c.ranges
}
func main() {
var verbose bool
flag.BoolVar(&verbose, "v", false, "verbose mode")
var method string
flag.StringVar(&method, "m", "cdn", "Output method:\n cdn - Only prints IPs on CDN\n not - only prints NOT on CDN\n all - prints all with verbose\n")
flag.Parse()
var rangesWG sync.WaitGroup
ips := make(chan string)
output := make(chan string)
var outputWG sync.WaitGroup
rangesWG.Add(1)
go func() {
for ip := range ips {
if isListening(ip, verbose, method) {
output <- ip
continue
}
}
rangesWG.Done()
}()
go func() {
for o := range output {
if !verbose {
if method != "all" {
_ = o
}
}
}
outputWG.Done()
}()
// Close the output channel when the HTTP workers are done
go func() {
rangesWG.Wait()
close(output)
}()
sc := bufio.NewScanner(os.Stdin)
for sc.Scan() {
ip := strings.ToLower(sc.Text())
ips <- ip
}
}
func isListening(ip string, verbose bool, method string) bool {
client, err := NewWithCache()
if err != nil {
log.Fatal(err)
}
if found, provider, err := client.Check(net.ParseIP(ip)); found && provider != "" && err == nil {
if verbose && (method == "all" || method == "cdn") {
fmt.Println(ip + "-" + provider)
} else if method == "all" || method == "cdn" {
fmt.Println(ip)
}
} else {
provider := "not CDN"
if verbose && (method == "all" || method == "not") {
fmt.Println(ip + "-" + provider)
} else if method == "all" || method == "not" {
fmt.Println(ip)
}
}
if err != nil {
return false
}
return true
}