diff --git a/README.md b/README.md index 0949cdd..7c6a1d9 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,10 @@ # ipbl + [![Build Status](https://drone.paulbsd.com/api/badges/paulbsd/ipbl/status.svg)](https://drone.paulbsd.com/paulbsd/ipbl) ## Summary -ipbl is ... +ipbl is a webservice storing IP address blacklist ## Howto @@ -59,4 +60,4 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of this project. -``` \ No newline at end of file +``` diff --git a/cmd/ipbl/ipbl.go b/cmd/ipbl/ipbl.go index 5d30956..d54d5a5 100644 --- a/cmd/ipbl/ipbl.go +++ b/cmd/ipbl/ipbl.go @@ -2,7 +2,9 @@ package main import ( "context" + "fmt" "log" + "os" "git.paulbsd.com/paulbsd/ipbl/src/config" "git.paulbsd.com/paulbsd/ipbl/src/database" @@ -18,6 +20,10 @@ func main() { var cfg config.Config cfg.GetConfig() cfg.Options.Version = version + if cfg.Switchs.Version { + fmt.Printf("ipbl version %s\n", cfg.Options.Version) + os.Exit(0) + } // Initialize database app context err := database.Initialize(&ctx, &cfg) diff --git a/src/config/main.go b/src/config/main.go index 314e93b..0d16d46 100644 --- a/src/config/main.go +++ b/src/config/main.go @@ -15,6 +15,7 @@ func (cfg *Config) GetConfig() error { var drop bool var init bool var port int + var version bool flag.Usage = utils.Usage @@ -23,6 +24,7 @@ func (cfg *Config) GetConfig() error { flag.BoolVar(&debug, "debug", false, "If debug logging must be enabled") flag.BoolVar(&drop, "drop", false, "If dropping tables must occur") flag.BoolVar(&init, "init", false, "If init of database must be done") + flag.BoolVar(&version, "version", false, "Show version") flag.Parse() @@ -30,6 +32,7 @@ func (cfg *Config) GetConfig() error { cfg.Switchs.Drop = drop cfg.Switchs.Init = init cfg.Switchs.Port = port + cfg.Switchs.Version = version var inicfg, err = ini.Load(configfile) if err != nil { @@ -61,10 +64,11 @@ type Config struct { HideBanner bool `json:"hidebanner"` } `json:"-"` Switchs struct { - Port int `json:"port"` - NoFeed bool `json:"nofeed"` - Debug bool `json:"debug"` - Drop bool `json:"drop"` - Init bool `json:"init"` + Port int `json:"port"` + NoFeed bool `json:"nofeed"` + Debug bool `json:"debug"` + Drop bool `json:"drop"` + Init bool `json:"init"` + Version bool `json:"version"` } `json:"-"` } diff --git a/src/models/cfg.go b/src/models/cfg.go index cd5c83f..ab31568 100644 --- a/src/models/cfg.go +++ b/src/models/cfg.go @@ -1,19 +1,63 @@ package models import ( + "fmt" + "regexp" "strings" "git.paulbsd.com/paulbsd/ipbl/src/config" ) +//var ipv4_regex = `^(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4})/` +var ipv4_cidr_regex = `^(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|)){4}\/([1-3])?([0-9])?$)` + // GetWhitelists ... -func GetWhitelists(cfg config.Config) (res []string) { +func GetWhitelists(cfg config.Config) (res []string, err error) { var w = Cfg{Key: "whitelist"} - cfg.Db.Get(&w) - res = strings.Split(w.Value, ",") + if exists, _ := cfg.Db.Get(&w); exists { + res = strings.Split(w.Value, ",") + } return } +func (wl Whitelist) Insert(cfg config.Config) (err error) { + var w = Cfg{Key: "whitelist"} + exists, _ := cfg.Db.Get(&w) + if exists { + existing, _ := GetWhitelists(cfg) + existing = append(existing, wl.IP) + w.Value = strings.Join(existing, ",") + cfg.Db.ID(w.ID).Update(&w) + } + return fmt.Errorf("no whitelist updated") +} + +func (wl Whitelist) Delete(cfg config.Config, ip string) (err error) { + var w = Cfg{Key: "whitelist"} + exists, _ := cfg.Db.Get(&w) + var updated []string + if exists { + existing, _ := GetWhitelists(cfg) + for _, sip := range existing { + if sip != ip { + updated = append(updated, sip) + } + } + w.Value = strings.Join(updated, ",") + cfg.Db.ID(w.ID).Update(&w) + } + return fmt.Errorf("no whitelist updated") +} + +func (wl Whitelist) Verify() bool { + reg := regexp.MustCompile(ipv4_cidr_regex) + return reg.MatchString(wl.IP) +} + +type Whitelist struct { + IP string `json:"ip"` +} + // Cfg is ipbl config type Cfg struct { ID int `xorm:"pk autoincr" json:"-"` diff --git a/src/models/ip.go b/src/models/ip.go index f0b37e3..00eb21e 100644 --- a/src/models/ip.go +++ b/src/models/ip.go @@ -6,7 +6,6 @@ import ( "fmt" "log" "net" - "reflect" "time" "git.paulbsd.com/paulbsd/ipbl/src/api" @@ -40,7 +39,7 @@ func GetIP(ctx *context.Context, config *config.Config, ipquery interface{}) (ap var ip IP has, err := config.Db.Where("ip = ?", ipquery).Get(&ip) if !has { - err = fmt.Errorf("Not Found") + err = fmt.Errorf("not found") return nil, err } if err != nil { @@ -93,9 +92,8 @@ func InsertIPBulk(cfg *config.Config, ips *[]IP) (numinserts int64, numupdates i // ScanIP ... func ScanIP(cfg *config.Config) (err error) { for { - var orphans = []IP{} - cfg.Db.Where("rdns IS NULL").Asc("ip").Find(&orphans) - if len(orphans) > 0 { + orphans := []IP{} + if cfg.Db.Where("rdns IS NULL").Asc("ip").Find(&orphans); len(orphans) > 0 { for _, i := range orphans { reverse, _ := i.UpdateRDNS() if reverse == "" { @@ -130,29 +128,6 @@ func (ip *IP) APIFormat() *api.IP { } } -func differ(sl1 []IP, sl2 []IP) (toinsert []IP, err error) { - var m = make(map[string]IPDiffer) - longslice := append(sl1, sl2...) - - for _, v2 := range longslice { - if _, v := m[v2.IP]; !v { - m[v2.IP] = IPDiffer{IP: v2, Num: 1} - } else { - if this, ok := m[v2.IP]; ok { - this.Num += 1 - m[v2.IP] = this - } - } - } - - for _, j := range reflect.ValueOf(m).MapKeys() { - if m[j.String()].Num == 1 { - toinsert = append(toinsert, m[j.String()].IP) - } - } - return -} - // IP describe IP objects type IP struct { ID int `xorm:"pk autoincr" json:"-"` @@ -162,8 +137,3 @@ type IP struct { Created time.Time `xorm:"created notnull" json:"-"` Updated time.Time `xorm:"updated notnull" json:"-"` } - -type IPDiffer struct { - IP IP - Num int -} diff --git a/src/models/utils.go b/src/models/utils.go index d37c53d..6fe59af 100644 --- a/src/models/utils.go +++ b/src/models/utils.go @@ -1,3 +1,33 @@ package models +import "reflect" + const keyname string = "id" + +func differ(sl1 []IP, sl2 []IP) (toinsert []IP, err error) { + var m = make(map[string]IPDiffer) + longslice := append(sl1, sl2...) + + for _, v2 := range longslice { + if _, v := m[v2.IP]; !v { + m[v2.IP] = IPDiffer{IP: v2, Num: 1} + } else { + if this, ok := m[v2.IP]; ok { + this.Num += 1 + m[v2.IP] = this + } + } + } + + for _, j := range reflect.ValueOf(m).MapKeys() { + if m[j.String()].Num == 1 { + toinsert = append(toinsert, m[j.String()].IP) + } + } + return +} + +type IPDiffer struct { + IP IP + Num int +} diff --git a/src/routers/funcs.go b/src/routers/funcs.go index 8816c89..aae4869 100644 --- a/src/routers/funcs.go +++ b/src/routers/funcs.go @@ -18,7 +18,7 @@ func RegisterRoutes(e *echo.Echo, ctx *context.Context, cfg *config.Config) { e.GET("/", func(c echo.Context) error { return c.HTML(http.StatusOK, ` -

Welcome to ipbl software (https://git.paulbsd.com/paulbsd/ipbl)

+

Welcome to ipbl software (https://git.paulbsd.com/paulbsd/ipbl)

`) }) @@ -76,12 +76,30 @@ func RegisterRoutes(e *echo.Echo, ctx *context.Context, cfg *config.Config) { return c.JSON(http.StatusOK, msg) }) e.GET("/ips/whitelist", func(c echo.Context) (err error) { - var whitelists = models.GetWhitelists(*cfg) + whitelists, _ := models.GetWhitelists(*cfg) if len(whitelists) > 0 { return c.JSON(http.StatusOK, whitelists) } return c.JSON(http.StatusInternalServerError, "") }) + e.PUT("/ips/whitelist", func(c echo.Context) (err error) { + var cidr models.Whitelist + err = c.Bind(&cidr) + if err == nil && cidr.Verify() { + cidr.Insert(*cfg) + return c.JSON(http.StatusOK, "Inserted new CIDR") + } + return c.JSON(http.StatusInternalServerError, "Invalid CIDR") + }) + e.DELETE("/ips/whitelist/:ip", func(c echo.Context) (err error) { + var ip = c.Param("ip") + var cidr models.Whitelist + err = cidr.Delete(*cfg, ip) + if err != nil { + return c.JSON(http.StatusOK, "Deleted old CIDR") + } + return + }) e.Logger.Fatal( e.Start( diff --git a/utils/main.go b/utils/main.go index a3922d6..bfc06e9 100644 --- a/utils/main.go +++ b/utils/main.go @@ -3,12 +3,13 @@ package utils import ( "flag" "log" + "os" ) // Usage displays possible arguments func Usage() { flag.PrintDefaults() - log.Fatal() + os.Exit(0) } // Advice displays possible arguments with warning advices @@ -17,5 +18,5 @@ func Advice(advice string) { if advice != "" { log.Fatalln(advice) } - log.Fatal() + os.Exit(0) }