* removed unused columns in tables * added multithreaded support for ip scans * added health endpoint
This commit is contained in:
parent
698510b19a
commit
5b95e817de
@ -1,6 +1,10 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "xorm.io/xorm"
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"xorm.io/xorm"
|
||||||
|
)
|
||||||
|
|
||||||
func (as *AutonomousSystem) GetOrCreate(session *xorm.Session) (apias *APIAutonomousSystem, err error) {
|
func (as *AutonomousSystem) GetOrCreate(session *xorm.Session) (apias *APIAutonomousSystem, err error) {
|
||||||
has, err := session.Get(as)
|
has, err := session.Get(as)
|
||||||
@ -44,9 +48,11 @@ func (as *AutonomousSystem) APIParse(apias APIAutonomousSystem) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AutonomousSystem struct {
|
type AutonomousSystem struct {
|
||||||
ID int `xorm:"pk autoincr"`
|
ID int `xorm:"pk autoincr"`
|
||||||
ASID int `xorm:"integer unique(asindex) as_id"`
|
ASID int `xorm:"integer unique(asindex) as_id"`
|
||||||
ASName string `xorm:"text unique(asindex) as_name"`
|
ASName string `xorm:"text unique(asindex) as_name"`
|
||||||
|
Created time.Time `xorm:"created notnull"`
|
||||||
|
Updated time.Time `xorm:"updated notnull"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type APIAutonomousSystem struct {
|
type APIAutonomousSystem struct {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -44,8 +46,10 @@ func (city *City) APIParse(apicity APICity) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type City struct {
|
type City struct {
|
||||||
ID int `xorm:"pk autoincr"`
|
ID int `xorm:"pk autoincr"`
|
||||||
CityName string `xorm:"text unique(cityindex) city_name" json:"city_name"`
|
CityName string `xorm:"text unique(cityindex) city_name" json:"city_name"`
|
||||||
|
Created time.Time `xorm:"created notnull"`
|
||||||
|
Updated time.Time `xorm:"updated notnull"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type APICity struct {
|
type APICity struct {
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "xorm.io/xorm"
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"xorm.io/xorm"
|
||||||
|
)
|
||||||
|
|
||||||
func (country *Country) GetOrCreate(session *xorm.Session) (apicountry *APICountry, err error) {
|
func (country *Country) GetOrCreate(session *xorm.Session) (apicountry *APICountry, err error) {
|
||||||
has, err := session.Get(country)
|
has, err := session.Get(country)
|
||||||
@ -42,8 +46,10 @@ func (country *Country) APIParse(apicountry APICountry) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Country struct {
|
type Country struct {
|
||||||
ID int `xorm:"pk autoincr"`
|
ID int `xorm:"pk autoincr"`
|
||||||
CountryName string `xorm:"text unique(countryindex) country_name" json:"country_name"`
|
CountryName string `xorm:"text unique(countryindex) country_name" json:"country_name"`
|
||||||
|
Created time.Time `xorm:"created notnull"`
|
||||||
|
Updated time.Time `xorm:"updated notnull"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type APICountry struct {
|
type APICountry struct {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.paulbsd.com/paulbsd/ipbl/src/config"
|
"git.paulbsd.com/paulbsd/ipbl/src/config"
|
||||||
@ -33,22 +32,22 @@ func (event *Event) APIFormat() *APIEvent {
|
|||||||
|
|
||||||
func (event *Event) APIParse(session *xorm.Session, apievent APIEvent) (err error) {
|
func (event *Event) APIParse(session *xorm.Session, apievent APIEvent) (err error) {
|
||||||
*event = Event{
|
*event = Event{
|
||||||
IP: &IP{IP: apievent.IPData.IP},
|
IP: &IP{IP: apievent.IPData.IP},
|
||||||
Src: apievent.IPData.Src,
|
Host: &Host{Host: apievent.IPData.Hostname},
|
||||||
Hostname: sql.NullString{
|
Src: &Src{Src: apievent.IPData.Src},
|
||||||
String: apievent.IPData.Hostname,
|
|
||||||
Valid: true},
|
|
||||||
}
|
}
|
||||||
event.IP.GetOrCreate(session)
|
event.IP.GetOrCreate(session)
|
||||||
|
event.Host.GetOrCreate(session)
|
||||||
|
event.Src.GetOrCreate(session)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type Event struct {
|
type Event struct {
|
||||||
ID int `xorm:"pk autoincr"`
|
ID int `xorm:"pk autoincr"`
|
||||||
Src string `xorm:"text notnull"`
|
Src *Src `xorm:"int src_id"`
|
||||||
Hostname sql.NullString `xorm:"text default NULL"`
|
Host *Host `xorm:"int host_id"`
|
||||||
IP *IP `xorm:"int ip_id"`
|
IP *IP `xorm:"int ip_id"`
|
||||||
Created time.Time `xorm:"created notnull"`
|
Created time.Time `xorm:"created notnull"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type APIEvent struct {
|
type APIEvent struct {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -44,8 +46,10 @@ func (host *Host) APIParse(apihost APIHost) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Host struct {
|
type Host struct {
|
||||||
ID int `xorm:"pk autoincr"`
|
ID int `xorm:"pk autoincr"`
|
||||||
Host string `xorm:"text unique host" json:"host"`
|
Host string `xorm:"text unique host" json:"host"`
|
||||||
|
Created time.Time `xorm:"created notnull"`
|
||||||
|
Updated time.Time `xorm:"updated notnull"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type APIHost struct {
|
type APIHost struct {
|
||||||
|
@ -35,8 +35,7 @@ func ProcessHostInfo(cfg *config.Config, hostinfos []HostInfo) (err error) {
|
|||||||
|
|
||||||
func HostInfoToIP(session *xorm.Session, hi *HostInfo) (ip IP) {
|
func HostInfoToIP(session *xorm.Session, hi *HostInfo) (ip IP) {
|
||||||
ip = IP{
|
ip = IP{
|
||||||
IP: hi.IP,
|
IP: hi.IP,
|
||||||
Whois: hi.Whois,
|
|
||||||
Rdns: sql.NullString{
|
Rdns: sql.NullString{
|
||||||
String: hi.Rdns,
|
String: hi.Rdns,
|
||||||
Valid: true},
|
Valid: true},
|
||||||
|
108
src/models/ip.go
108
src/models/ip.go
@ -8,13 +8,14 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.paulbsd.com/paulbsd/ipbl/src/config"
|
"git.paulbsd.com/paulbsd/ipbl/src/config"
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
const SCANLIMIT = 10
|
const SCANLIMIT = 100
|
||||||
|
|
||||||
const IPINFO_WS = "https://ip.paulbsd.com"
|
const IPINFO_WS = "https://ip.paulbsd.com"
|
||||||
|
|
||||||
@ -42,8 +43,6 @@ func (ip *IP) GetOrCreate(session *xorm.Session) (apiip *APIIP, err error) {
|
|||||||
ip.City.GetOrCreate(session)
|
ip.City.GetOrCreate(session)
|
||||||
ip.Country.GetOrCreate(session)
|
ip.Country.GetOrCreate(session)
|
||||||
ip.AutonomousSystem.GetOrCreate(session)
|
ip.AutonomousSystem.GetOrCreate(session)
|
||||||
ip.Host.GetOrCreate(session)
|
|
||||||
ip.Src.GetOrCreate(session)
|
|
||||||
session.Commit()
|
session.Commit()
|
||||||
|
|
||||||
var tmpip *IP
|
var tmpip *IP
|
||||||
@ -132,43 +131,81 @@ func InsertIPBulk(session *xorm.Session, ips *[]IP) (numinsert int64, numupdate
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ScanIP(cfg *config.Config) (err error) {
|
func ScanIP(cfg *config.Config) (err error) {
|
||||||
queryclient := http.Client{}
|
var numthreads = 8
|
||||||
for {
|
for {
|
||||||
session := cfg.Db.NewSession()
|
session := cfg.Db.NewSession()
|
||||||
orphans := []IP{}
|
orphans := []IP{}
|
||||||
err = session.Where("(as_id is null or country_id is null or city_id is null or rdns = '') and updated < now()-'1d'::interval").Asc("updated").Limit(SCANLIMIT).Find(&orphans)
|
err = session.Where(`((as_id IS NULL
|
||||||
|
OR country_id IS NULL
|
||||||
|
OR city_id IS NULL
|
||||||
|
OR rdns = ''
|
||||||
|
OR rdns IS NULL) AND updated < now()-'1d'::interval) OR
|
||||||
|
(as_id IS NULL
|
||||||
|
AND country_id IS NULL
|
||||||
|
AND city_id IS NULL
|
||||||
|
AND rdns IS NULL)
|
||||||
|
`).Desc("updated").Limit(SCANLIMIT).Find(&orphans)
|
||||||
session.Close()
|
session.Close()
|
||||||
|
|
||||||
if err == nil && len(orphans) > 0 {
|
if err == nil && len(orphans) > 0 {
|
||||||
|
orphanchan := make(chan IP)
|
||||||
|
done := make(chan bool)
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
for thr := range make([]int, numthreads) {
|
||||||
|
go ScanOrphan(&wg, orphanchan, done, thr, cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, orphan := range orphans {
|
||||||
|
orphanchan <- orphan
|
||||||
|
}
|
||||||
|
|
||||||
|
close(orphanchan)
|
||||||
|
<-done
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
} else {
|
||||||
|
time.Sleep(30 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScanOrphan(wg *sync.WaitGroup, orphans chan IP, done chan bool, thr int, cfg *config.Config) (err error) {
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
for {
|
||||||
|
orphan, more := <-orphans
|
||||||
|
if more {
|
||||||
session := cfg.Db.NewSession()
|
session := cfg.Db.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
for _, orphan := range orphans {
|
queryclient := http.Client{}
|
||||||
query, err := QueryInfo(&queryclient, orphan.IP)
|
var query QueryIP
|
||||||
if err != nil {
|
query, err := QueryInfo(&queryclient, orphan.IP)
|
||||||
log.Println(err)
|
if err != nil {
|
||||||
continue
|
log.Println(err)
|
||||||
}
|
continue
|
||||||
as := &AutonomousSystem{ASID: query.APIAS.ASID, ASName: query.APIAS.ASName}
|
|
||||||
orphan.AutonomousSystem = as
|
|
||||||
|
|
||||||
if query.APICity != "" {
|
|
||||||
var city = City{CityName: query.APICity}
|
|
||||||
orphan.City = &city
|
|
||||||
}
|
|
||||||
|
|
||||||
if query.APICountry != "" {
|
|
||||||
var country = Country{CountryName: query.APICountry}
|
|
||||||
orphan.Country = &country
|
|
||||||
}
|
|
||||||
|
|
||||||
orphan.Rdns = sql.NullString{String: query.Rdns, Valid: true}
|
|
||||||
log.Printf("%s -> \"%s\"\n", orphan.IP, query.Rdns)
|
|
||||||
|
|
||||||
orphan.GetOrCreate(session)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var as = AutonomousSystem{ASID: query.APIAS.Number, ASName: query.APIAS.Org}
|
||||||
|
orphan.AutonomousSystem = &as
|
||||||
|
|
||||||
|
if query.APICity != "" {
|
||||||
|
var city = City{CityName: query.APICity}
|
||||||
|
orphan.City = &city
|
||||||
|
}
|
||||||
|
|
||||||
|
if query.APICountry != "" {
|
||||||
|
var country = Country{CountryName: query.APICountry}
|
||||||
|
orphan.Country = &country
|
||||||
|
}
|
||||||
|
|
||||||
|
orphan.Rdns = sql.NullString{String: query.Rdns, Valid: true}
|
||||||
|
log.Printf("%s -> \"%s\"\n", orphan.IP, query.Rdns)
|
||||||
|
|
||||||
|
orphan.GetOrCreate(session)
|
||||||
|
|
||||||
err = session.Commit()
|
err = session.Commit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
@ -178,9 +215,11 @@ func ScanIP(cfg *config.Config) (err error) {
|
|||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
time.Sleep(2 * time.Minute)
|
//fmt.Printf("All orphan migrated on thread num %d\n", thr)
|
||||||
|
wg.Done()
|
||||||
|
done <- true
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,9 +300,6 @@ type IP struct {
|
|||||||
AutonomousSystem *AutonomousSystem `xorm:"as_id int index default null"`
|
AutonomousSystem *AutonomousSystem `xorm:"as_id int index default null"`
|
||||||
City *City `xorm:"city_id int index default null"`
|
City *City `xorm:"city_id int index default null"`
|
||||||
Country *Country `xorm:"country_id int index default null"`
|
Country *Country `xorm:"country_id int index default null"`
|
||||||
Src *Src `xorm:"src_id int index default null"`
|
|
||||||
Host *Host `xorm:"host_id int index default null"`
|
|
||||||
Whois string `xorm:"text index default null"`
|
|
||||||
Created time.Time `xorm:"created notnull"`
|
Created time.Time `xorm:"created notnull"`
|
||||||
Updated time.Time `xorm:"updated notnull"`
|
Updated time.Time `xorm:"updated notnull"`
|
||||||
}
|
}
|
||||||
@ -280,12 +316,12 @@ type APIIP struct {
|
|||||||
type QueryIP struct {
|
type QueryIP struct {
|
||||||
IP string `json:"ip"`
|
IP string `json:"ip"`
|
||||||
Rdns string `json:"hostname"`
|
Rdns string `json:"hostname"`
|
||||||
APIAS QueryAutonomousSystem `json:"asn"`
|
APIAS QueryAutonomousSystem `json:"as"`
|
||||||
APICity string `json:"city"`
|
APICity string `json:"city"`
|
||||||
APICountry string `json:"country"`
|
APICountry string `json:"country"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type QueryAutonomousSystem struct {
|
type QueryAutonomousSystem struct {
|
||||||
ASID int `json:"id"`
|
Number int `json:"number"`
|
||||||
ASName string `json:"name"`
|
Org string `json:"org"`
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -44,8 +46,10 @@ func (src *Src) APIParse(apisrc APISrc) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Src struct {
|
type Src struct {
|
||||||
ID int `xorm:"pk autoincr"`
|
ID int `xorm:"pk autoincr"`
|
||||||
Src string `xorm:"text unique(srcindex) src" json:"src"`
|
Src string `xorm:"text unique(srcindex) src" json:"src"`
|
||||||
|
Created time.Time `xorm:"created notnull"`
|
||||||
|
Updated time.Time `xorm:"updated notnull"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type APISrc struct {
|
type APISrc struct {
|
||||||
|
@ -22,6 +22,10 @@ func RegisterRoutes(e *echo.Echo, ctx *context.Context, cfg *config.Config) {
|
|||||||
</html>`)
|
</html>`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
e.GET("/health", func(c echo.Context) error {
|
||||||
|
return c.HTML(http.StatusOK, `OK`)
|
||||||
|
})
|
||||||
|
|
||||||
e.GET("/ip/:ip", func(c echo.Context) (err error) {
|
e.GET("/ip/:ip", func(c echo.Context) (err error) {
|
||||||
session := cfg.Db.NewSession()
|
session := cfg.Db.NewSession()
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
Loading…
Reference in New Issue
Block a user