Skip to content

Commit 3281b92

Browse files
committed
v0.2.17 add parallel mode
1 parent 0285b63 commit 3281b92

File tree

7 files changed

+126
-26
lines changed

7 files changed

+126
-26
lines changed

HISTORY.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## v0.2.17 add parallel mode
2+
3+
- such as ```fofa -f ip "is_ipv6=false && port=22" | fofa -f ip -uniqByIP -template "port=8443 && ip={}"```
4+
- host mode raise error if data.error is true
5+
- fixed bug of: ```fofa -f ip -uniqByIP 'port=22 && ip=154.19.247.29'``` return multiple lines of ip even if set uniqByIP
6+
17
## v0.1.16 add domains mode
28

39
- add domains mode to extend domains from domain, through certs ```./fofa domains -s 1000 -withCount baidu.com```

README.md

+7
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,13 @@ redis://152.136.145.87:6379
105105
./fofa --fixUrl --size 1000 --fields host --uniqByIP 'host="edu.cn"'
106106
```
107107

108+
- pipeline with parallel mode
109+
110+
```shell
111+
fofa -f ip "is_ipv6=false && port=22" | fofa -f ip -uniqByIP -template "port=8443 && ip={}"
112+
```
113+
can use `-rate 3` to increase rate limit, default is 2
114+
108115
### Stats
109116

110117
- stats subcommand

cmd/fofa/cmd/search.go

+99-25
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,39 @@
11
package cmd
22

33
import (
4+
"bufio"
5+
"context"
46
"errors"
57
"fmt"
68
"github.com/LubyRuffy/gofofa"
79
"github.com/LubyRuffy/gofofa/pkg/outformats"
810
"github.com/sirupsen/logrus"
911
"github.com/urfave/cli/v2"
12+
"golang.org/x/time/rate"
1013
"io"
14+
"log"
1115
"os"
16+
"strconv"
1217
"strings"
18+
"sync"
1319
)
1420

1521
var (
16-
fieldString string // fieldString
17-
size int // fetch size
18-
format string // out format
19-
outFile string // out file
20-
inFile string // in file
21-
deductMode string // deduct Mode
22-
fixUrl bool // each host fix as url, like 1.1.1.1,80 will change to http://1.1.1.1
23-
urlPrefix string // each host fix as url, like 1.1.1.1,80 will change to http://1.1.1.1
24-
full bool // search result for over a year
25-
batchSize int // amount of data contained in each batch, only for dump
26-
json bool // out format as json for short
27-
uniqByIP bool // group by ip
22+
fieldString string // fieldString
23+
size int // fetch size
24+
format string // out format
25+
outFile string // out file
26+
inFile string // in file
27+
deductMode string // deduct Mode
28+
fixUrl bool // each host fix as url, like 1.1.1.1,80 will change to http://1.1.1.1
29+
urlPrefix string // each host fix as url, like 1.1.1.1,80 will change to http://1.1.1.1
30+
full bool // search result for over a year
31+
batchSize int // amount of data contained in each batch, only for dump
32+
json bool // out format as json for short
33+
uniqByIP bool // group by ip
34+
workers int // number of workers
35+
ratePerSecond int // fofa request per second
36+
template string // template in pipeline mode
2837
)
2938

3039
// search subcommand
@@ -89,6 +98,24 @@ var searchCmd = &cli.Command{
8998
Usage: "uniq by ip",
9099
Destination: &uniqByIP,
91100
},
101+
&cli.IntFlag{
102+
Name: "workers",
103+
Value: 10,
104+
Usage: "number of workers",
105+
Destination: &workers,
106+
},
107+
&cli.IntFlag{
108+
Name: "rate",
109+
Value: 2,
110+
Usage: "fofa query per second",
111+
Destination: &ratePerSecond,
112+
},
113+
&cli.StringFlag{
114+
Name: "template",
115+
Value: "ip={}",
116+
Usage: "template in pipeline mode",
117+
Destination: &template,
118+
},
92119
},
93120
Action: SearchAction,
94121
}
@@ -126,8 +153,10 @@ func SearchAction(ctx *cli.Context) error {
126153

127154
query := ctx.Args().First()
128155
if len(query) == 0 {
129-
return errors.New("fofa query cannot be empty")
156+
//return errors.New("fofa query cannot be empty")
157+
log.Println("not set fofa query, now in pipeline mode....")
130158
}
159+
131160
fields := strings.Split(fieldString, ",")
132161
if len(fields) == 0 {
133162
return errors.New("fofa fields cannot be empty")
@@ -165,20 +194,65 @@ func SearchAction(ctx *cli.Context) error {
165194
}
166195
}
167196

168-
// do search
169-
res, err := fofaCli.HostSearch(query, size, fields, gofofa.SearchOptions{
170-
FixUrl: fixUrl,
171-
UrlPrefix: urlPrefix,
172-
Full: full,
173-
UniqByIP: uniqByIP,
174-
})
175-
if err != nil {
176-
return err
197+
writeQuery := func(query string) error {
198+
log.Println("query fofa of:", query)
199+
// do search
200+
res, err := fofaCli.HostSearch(query, size, fields, gofofa.SearchOptions{
201+
FixUrl: fixUrl,
202+
UrlPrefix: urlPrefix,
203+
Full: full,
204+
UniqByIP: uniqByIP,
205+
})
206+
if err != nil {
207+
return err
208+
}
209+
210+
// output
211+
if err = writer.WriteAll(res); err != nil {
212+
return err
213+
}
214+
215+
return nil
177216
}
178217

179-
// output
180-
if err = writer.WriteAll(res); err != nil {
181-
return err
218+
if query != "" {
219+
return writeQuery(query)
220+
} else {
221+
// 并发模式
222+
wg := sync.WaitGroup{}
223+
queries := make(chan string, workers)
224+
limiter := rate.NewLimiter(rate.Limit(ratePerSecond), 5)
225+
226+
worker := func(queries <-chan string, wg *sync.WaitGroup) {
227+
for q := range queries {
228+
tmpQuery := strings.ReplaceAll(template, "{}",
229+
strconv.Quote(q))
230+
if err := limiter.Wait(context.Background()); err != nil {
231+
fmt.Println("Error: ", err)
232+
}
233+
if err := writeQuery(tmpQuery); err != nil {
234+
log.Println(err)
235+
}
236+
wg.Done()
237+
}
238+
}
239+
for w := 0; w < workers; w++ {
240+
go worker(queries, &wg)
241+
}
242+
243+
scanner := bufio.NewScanner(os.Stdin)
244+
for scanner.Scan() { // internally, it advances token based on sperator
245+
line := scanner.Text()
246+
wg.Add(1)
247+
queries <- line
248+
}
249+
250+
if err := scanner.Err(); err != nil {
251+
log.Println(err)
252+
}
253+
254+
wg.Wait()
182255
}
256+
183257
return nil
184258
}

cmd/fofa/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
)
1010

1111
var (
12-
version = "v0.1.16"
12+
version = "v0.2.17"
1313
commit = "none"
1414
date = "unknown"
1515
builtBy = "unknown" // goreleaser fill

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ require (
2525
github.com/russross/blackfriday/v2 v2.1.0 // indirect
2626
golang.org/x/sys v0.10.0 // indirect
2727
golang.org/x/text v0.11.0 // indirect
28+
golang.org/x/time v0.5.0 // indirect
2829
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
2930
gopkg.in/yaml.v3 v3.0.0-20210106172901-c476de37821d // indirect
3031
)

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
101101
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
102102
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
103103
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
104+
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
105+
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
104106
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
105107
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
106108
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=

host.go

+10
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,13 @@ func (c *Client) HostSearch(query string, size int, fields []string, options ...
264264
}
265265
results = append(results, newSlice)
266266
} else if vStr, ok := result.(string); ok {
267+
// 确定第一个就是ip
268+
if uniqByIP && ipIndex == 0 {
269+
if _, ok := uniqIPMap[vStr]; ok {
270+
continue
271+
}
272+
uniqIPMap[vStr] = true
273+
}
267274
results = append(results, []string{vStr})
268275
}
269276
}
@@ -320,6 +327,9 @@ func (c *Client) HostStats(host string) (data HostStatsData, err error) {
320327
if err != nil {
321328
return
322329
}
330+
if data.Error {
331+
err = errors.New(data.Errmsg)
332+
}
323333
return
324334
}
325335

0 commit comments

Comments
 (0)