Skip to content

Commit 3dd42bc

Browse files
authored
add ability to filter 'ban list' output (--ip --range --as --country --reason) (#115)
* add ability to filter 'ban list' output
1 parent 7691e5b commit 3dd42bc

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

cmd/crowdsec-cli/ban.go

+113
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ var remediationType string
2222
var atTime string
2323
var all bool
2424

25+
//user supplied filters
26+
var ipFilter, rangeFilter, reasonFilter, countryFilter, asFilter string
27+
2528
func simpleBanToSignal(targetIP string, reason string, expirationStr string, action string, asName string, asNum string, country string, banSource string) (types.SignalOccurence, error) {
2629
var signalOcc types.SignalOccurence
2730

@@ -84,6 +87,102 @@ func simpleBanToSignal(targetIP string, reason string, expirationStr string, act
8487
return signalOcc, nil
8588
}
8689

90+
func filterBans(bans []map[string]string) ([]map[string]string, error) {
91+
92+
var retBans []map[string]string
93+
94+
for _, ban := range bans {
95+
var banIP net.IP
96+
var banRange *net.IPNet
97+
var keep bool = true
98+
var err error
99+
100+
if ban["iptext"] != "" {
101+
if strings.Contains(ban["iptext"], "/") {
102+
log.Debugf("%s is a range", ban["iptext"])
103+
banIP, banRange, err = net.ParseCIDR(ban["iptext"])
104+
if err != nil {
105+
log.Warningf("failed to parse range '%s' from database : %s", ban["iptext"], err)
106+
}
107+
} else {
108+
log.Debugf("%s is IP", ban["iptext"])
109+
banIP = net.ParseIP(ban["iptext"])
110+
}
111+
}
112+
113+
if ipFilter != "" {
114+
var filterBinIP net.IP = net.ParseIP(ipFilter)
115+
116+
if banRange != nil {
117+
if banRange.Contains(filterBinIP) {
118+
log.Debugf("[keep] ip filter is set, and range contains ip")
119+
keep = true
120+
} else {
121+
log.Debugf("[discard] ip filter is set, and range doesn't contain ip")
122+
keep = false
123+
}
124+
} else {
125+
if ipFilter == ban["iptext"] {
126+
log.Debugf("[keep] (ip) %s == %s", ipFilter, ban["iptext"])
127+
keep = true
128+
} else {
129+
log.Debugf("[discard] (ip) %s == %s", ipFilter, ban["iptext"])
130+
keep = false
131+
}
132+
}
133+
}
134+
if rangeFilter != "" {
135+
_, filterBinRange, err := net.ParseCIDR(rangeFilter)
136+
if err != nil {
137+
return nil, fmt.Errorf("failed to parse range '%s' : %s", rangeFilter, err)
138+
}
139+
if filterBinRange.Contains(banIP) {
140+
log.Debugf("[keep] range filter %s contains %s", rangeFilter, banIP.String())
141+
keep = true
142+
} else {
143+
log.Debugf("[discard] range filter %s doesn't contain %s", rangeFilter, banIP.String())
144+
keep = false
145+
}
146+
}
147+
if reasonFilter != "" {
148+
if strings.Contains(ban["reason"], reasonFilter) {
149+
log.Debugf("[keep] reason filter %s matches %s", reasonFilter, ban["reason"])
150+
keep = true
151+
} else {
152+
log.Debugf("[discard] reason filter %s doesn't match %s", reasonFilter, ban["reason"])
153+
keep = false
154+
}
155+
}
156+
157+
if countryFilter != "" {
158+
if ban["cn"] == countryFilter {
159+
log.Debugf("[keep] country filter %s matches %s", countryFilter, ban["cn"])
160+
keep = true
161+
} else {
162+
log.Debugf("[discard] country filter %s matches %s", countryFilter, ban["cn"])
163+
keep = false
164+
}
165+
}
166+
167+
if asFilter != "" {
168+
if strings.Contains(ban["as"], asFilter) {
169+
log.Debugf("[keep] AS filter %s matches %s", asFilter, ban["as"])
170+
keep = true
171+
} else {
172+
log.Debugf("[discard] AS filter %s doesn't match %s", asFilter, ban["as"])
173+
keep = false
174+
}
175+
}
176+
177+
if keep {
178+
retBans = append(retBans, ban)
179+
} else {
180+
log.Debugf("[discard] discard %v", ban)
181+
}
182+
}
183+
return retBans, nil
184+
}
185+
87186
func BanList() error {
88187
at := time.Now()
89188
if atTime != "" {
@@ -96,6 +195,10 @@ func BanList() error {
96195
if err != nil {
97196
return fmt.Errorf("unable to get records from sqlite : %v", err)
98197
}
198+
ret, err = filterBans(ret)
199+
if err != nil {
200+
log.Errorf("Error while filtering : %s", err)
201+
}
99202
if config.output == "raw" {
100203
fmt.Printf("source,ip,reason,bans,action,country,as,events_count,expiration\n")
101204
for _, rm := range ret {
@@ -312,6 +415,10 @@ Time can be specified with --at and support a variety of date formats:
312415
- 2006-01-02
313416
- 2006-01-02 15:04
314417
`,
418+
Example: `ban list --range 0.0.0.0/0 : will list all
419+
ban list --country CN
420+
ban list --reason crowdsecurity/http-probing
421+
ban list --as OVH`,
315422
Args: cobra.ExactArgs(0),
316423
Run: func(cmd *cobra.Command, args []string) {
317424
if err := BanList(); err != nil {
@@ -321,6 +428,12 @@ Time can be specified with --at and support a variety of date formats:
321428
}
322429
cmdBanList.PersistentFlags().StringVar(&atTime, "at", "", "List bans at given time")
323430
cmdBanList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List as well bans received from API")
431+
cmdBanList.PersistentFlags().StringVar(&ipFilter, "ip", "", "List bans for given IP")
432+
cmdBanList.PersistentFlags().StringVar(&rangeFilter, "range", "", "List bans belonging to given range")
433+
cmdBanList.PersistentFlags().StringVar(&reasonFilter, "reason", "", "List bans containing given reason")
434+
cmdBanList.PersistentFlags().StringVar(&countryFilter, "country", "", "List bans belonging to given country code")
435+
cmdBanList.PersistentFlags().StringVar(&asFilter, "as", "", "List bans belonging to given AS name")
436+
324437
cmdBan.AddCommand(cmdBanList)
325438
return cmdBan
326439
}

0 commit comments

Comments
 (0)