-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.go
136 lines (127 loc) · 3.15 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
package main
import (
"bufio"
"fmt"
"net"
"net/url"
"os"
"sync"
valid "github.com/asaskevich/govalidator"
"github.com/jessevdk/go-flags"
)
var scopeSubnets []*net.IPNet
var opts struct {
CIDRS string `short:"c" long:"cidrs" required:"true" description:"CIDRS to match with, line separated"`
Threads int `short:"t" long:"threads" default:"20" description:"Number of concurrent threads"`
Verbose bool `short:"v" long:"verbose" description:"Turns on verbose logging (shows the scope and resolved IP(s))"`
}
func main() {
_, err := flags.Parse(&opts)
if err != nil {
os.Exit(1)
}
// Get Scope File's once STDIN
if opts.CIDRS != "" {
file, err := os.Open(opts.CIDRS)
scanner := bufio.NewScanner(file)
if err != nil {
fmt.Fprintln(os.Stderr, "ERR: could not load CIDR file please try again", err)
os.Exit(1)
}
for scanner.Scan() {
r := scanner.Text()
_, subnet, err := net.ParseCIDR(r)
if err != nil {
scopeSubnets = append(scopeSubnets, subnet)
} else {
fmt.Fprintln(os.Stderr, "ERR: Error parsing", r, "with fault", err)
}
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "ERR: reading cidrs failed:", err)
}
file.Close()
}
//get STDIN
numWorkers := opts.Threads
work := make(chan string)
go func() {
scanner := bufio.NewScanner(os.Stdin)
// for each line on STDIN
for scanner.Scan() {
work <- scanner.Text()
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "ERR: reading input failed:", err)
}
close(work)
}()
// Create a waiting group
wg := &sync.WaitGroup{}
for i := 0; i < numWorkers; i++ {
wg.Add(1)
go doWork(work, wg) //Schedule the work
}
wg.Wait() //Wait for it all to complete
}
func doWork(work chan string, wg *sync.WaitGroup) {
defer wg.Done() // done after we exit this func
//for each item to check scope
for toScope := range work {
procesInput(toScope, nil)
}
}
func procesInput(input string, override []*net.IPNet) bool {
if override != nil {
scopeSubnets = override
}
if ip := net.ParseIP(input); ip != nil {
for _, scope := range scopeSubnets {
if scope.Contains(ip) {
if opts.Verbose == true {
fmt.Printf("%s, is within scope of %s\n", input, scope)
} else {
fmt.Println(input)
}
return true
}
}
} else {
var ips []net.IP
var err error
if valid.IsDNSName(input) {
ips, err = net.LookupIP(input)
if err != nil {
if opts.Verbose {
fmt.Fprintln(os.Stderr, "ERR: identified DNSName but couldn't parse IP's without error", err)
}
return false
}
} else if valid.IsURL(input) {
if u, _ := url.Parse(input); u != nil {
ips, err = net.LookupIP(u.Hostname())
if err != nil {
if opts.Verbose {
fmt.Fprintln(os.Stderr, "ERR: identified URL but couldn't parse IP's without error", err)
}
return false
}
}
}
if ips != nil {
for _, ip := range ips {
for _, scope := range scopeSubnets {
if scope.Contains(ip) {
if opts.Verbose {
fmt.Printf("%s, resolved to %s (%v) which is within scope of %s\n", input, ip, ips, scope)
} else {
fmt.Println(input)
}
return true
}
}
}
}
}
return false
}