Procházet zdrojové kódy

add ability to filter 'ban list' output (`--ip` `--range` `--as` `--country` `--reason`) (#115)

* add ability to filter 'ban list' output
Thibault "bui" Koechlin před 5 roky
rodič
revize
3dd42bc9fd
1 změnil soubory, kde provedl 113 přidání a 0 odebrání
  1. 113 0
      cmd/crowdsec-cli/ban.go

+ 113 - 0
cmd/crowdsec-cli/ban.go

@@ -22,6 +22,9 @@ var remediationType string
 var atTime string
 var all bool
 
+//user supplied filters
+var ipFilter, rangeFilter, reasonFilter, countryFilter, asFilter string
+
 func simpleBanToSignal(targetIP string, reason string, expirationStr string, action string, asName string, asNum string, country string, banSource string) (types.SignalOccurence, error) {
 	var signalOcc types.SignalOccurence
 
@@ -84,6 +87,102 @@ func simpleBanToSignal(targetIP string, reason string, expirationStr string, act
 	return signalOcc, nil
 }
 
+func filterBans(bans []map[string]string) ([]map[string]string, error) {
+
+	var retBans []map[string]string
+
+	for _, ban := range bans {
+		var banIP net.IP
+		var banRange *net.IPNet
+		var keep bool = true
+		var err error
+
+		if ban["iptext"] != "" {
+			if strings.Contains(ban["iptext"], "/") {
+				log.Debugf("%s is a range", ban["iptext"])
+				banIP, banRange, err = net.ParseCIDR(ban["iptext"])
+				if err != nil {
+					log.Warningf("failed to parse range '%s' from database : %s", ban["iptext"], err)
+				}
+			} else {
+				log.Debugf("%s is IP", ban["iptext"])
+				banIP = net.ParseIP(ban["iptext"])
+			}
+		}
+
+		if ipFilter != "" {
+			var filterBinIP net.IP = net.ParseIP(ipFilter)
+
+			if banRange != nil {
+				if banRange.Contains(filterBinIP) {
+					log.Debugf("[keep] ip filter is set, and range contains ip")
+					keep = true
+				} else {
+					log.Debugf("[discard] ip filter is set, and range doesn't contain ip")
+					keep = false
+				}
+			} else {
+				if ipFilter == ban["iptext"] {
+					log.Debugf("[keep] (ip) %s == %s", ipFilter, ban["iptext"])
+					keep = true
+				} else {
+					log.Debugf("[discard] (ip) %s == %s", ipFilter, ban["iptext"])
+					keep = false
+				}
+			}
+		}
+		if rangeFilter != "" {
+			_, filterBinRange, err := net.ParseCIDR(rangeFilter)
+			if err != nil {
+				return nil, fmt.Errorf("failed to parse range '%s' : %s", rangeFilter, err)
+			}
+			if filterBinRange.Contains(banIP) {
+				log.Debugf("[keep] range filter %s contains %s", rangeFilter, banIP.String())
+				keep = true
+			} else {
+				log.Debugf("[discard] range filter %s doesn't contain %s", rangeFilter, banIP.String())
+				keep = false
+			}
+		}
+		if reasonFilter != "" {
+			if strings.Contains(ban["reason"], reasonFilter) {
+				log.Debugf("[keep] reason filter %s matches %s", reasonFilter, ban["reason"])
+				keep = true
+			} else {
+				log.Debugf("[discard] reason filter %s doesn't match %s", reasonFilter, ban["reason"])
+				keep = false
+			}
+		}
+
+		if countryFilter != "" {
+			if ban["cn"] == countryFilter {
+				log.Debugf("[keep] country filter %s matches %s", countryFilter, ban["cn"])
+				keep = true
+			} else {
+				log.Debugf("[discard] country filter %s matches %s", countryFilter, ban["cn"])
+				keep = false
+			}
+		}
+
+		if asFilter != "" {
+			if strings.Contains(ban["as"], asFilter) {
+				log.Debugf("[keep] AS filter %s matches %s", asFilter, ban["as"])
+				keep = true
+			} else {
+				log.Debugf("[discard] AS filter %s doesn't match %s", asFilter, ban["as"])
+				keep = false
+			}
+		}
+
+		if keep {
+			retBans = append(retBans, ban)
+		} else {
+			log.Debugf("[discard] discard %v", ban)
+		}
+	}
+	return retBans, nil
+}
+
 func BanList() error {
 	at := time.Now()
 	if atTime != "" {
@@ -96,6 +195,10 @@ func BanList() error {
 	if err != nil {
 		return fmt.Errorf("unable to get records from sqlite : %v", err)
 	}
+	ret, err = filterBans(ret)
+	if err != nil {
+		log.Errorf("Error while filtering : %s", err)
+	}
 	if config.output == "raw" {
 		fmt.Printf("source,ip,reason,bans,action,country,as,events_count,expiration\n")
 		for _, rm := range ret {
@@ -312,6 +415,10 @@ Time can be specified with --at and support a variety of date formats:
  - 2006-01-02  
  - 2006-01-02 15:04
 `,
+		Example: `ban list --range 0.0.0.0/0 : will list all
+		ban list --country CN
+		ban list --reason crowdsecurity/http-probing
+		ban list --as OVH`,
 		Args: cobra.ExactArgs(0),
 		Run: func(cmd *cobra.Command, args []string) {
 			if err := BanList(); err != nil {
@@ -321,6 +428,12 @@ Time can be specified with --at and support a variety of date formats:
 	}
 	cmdBanList.PersistentFlags().StringVar(&atTime, "at", "", "List bans at given time")
 	cmdBanList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List as well bans received from API")
+	cmdBanList.PersistentFlags().StringVar(&ipFilter, "ip", "", "List bans for given IP")
+	cmdBanList.PersistentFlags().StringVar(&rangeFilter, "range", "", "List bans belonging to given range")
+	cmdBanList.PersistentFlags().StringVar(&reasonFilter, "reason", "", "List bans containing given reason")
+	cmdBanList.PersistentFlags().StringVar(&countryFilter, "country", "", "List bans belonging to given country code")
+	cmdBanList.PersistentFlags().StringVar(&asFilter, "as", "", "List bans belonging to given AS name")
+
 	cmdBan.AddCommand(cmdBanList)
 	return cmdBan
 }