feat: IP-Status-Diagnose hinzufügen
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
package appinfo
|
||||
|
||||
var Version = "v1.1.1"
|
||||
var Version = "v1.1.2"
|
||||
|
||||
const ProjectURL = "https://git.techniverse.net/scriptos/adguard-shield.git"
|
||||
|
||||
@@ -25,6 +25,27 @@ type Ban struct {
|
||||
GeoIPMode string
|
||||
}
|
||||
|
||||
type Offense struct {
|
||||
IP string
|
||||
Level int
|
||||
LastEpoch int64
|
||||
Last string
|
||||
First string
|
||||
}
|
||||
|
||||
type WhitelistEntry struct {
|
||||
IP string
|
||||
Source string
|
||||
ResolvedAt string
|
||||
}
|
||||
|
||||
type GeoIPCacheEntry struct {
|
||||
IP string
|
||||
CountryCode string
|
||||
LookedUpAtEpoch int64
|
||||
DBMtime int64
|
||||
}
|
||||
|
||||
type ReportStats struct {
|
||||
Since int64
|
||||
Until int64
|
||||
@@ -120,6 +141,22 @@ func (s *Store) BanExists(ip string) (bool, error) {
|
||||
return err == nil, err
|
||||
}
|
||||
|
||||
func (s *Store) BanByIP(ip string) (Ban, bool, error) {
|
||||
row := s.DB.QueryRow(`SELECT client_ip, COALESCE(domain,''), COALESCE(count,0), COALESCE(ban_until_epoch,0),
|
||||
COALESCE(ban_duration,0), COALESCE(offense_level,0), COALESCE(is_permanent,0), COALESCE(reason,''), COALESCE(protocol,''),
|
||||
COALESCE(source,''), COALESCE(geoip_country,''), COALESCE(geoip_mode,'') FROM active_bans WHERE client_ip=? LIMIT 1`, ip)
|
||||
var b Ban
|
||||
var perm int
|
||||
if err := row.Scan(&b.IP, &b.Domain, &b.Count, &b.BanUntil, &b.Duration, &b.OffenseLevel, &perm, &b.Reason, &b.Protocol, &b.Source, &b.GeoIPCountry, &b.GeoIPMode); err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return Ban{}, false, nil
|
||||
}
|
||||
return Ban{}, false, err
|
||||
}
|
||||
b.Permanent = perm == 1
|
||||
return b, true, nil
|
||||
}
|
||||
|
||||
func (s *Store) InsertBan(b Ban) error {
|
||||
now := time.Now()
|
||||
perm := 0
|
||||
@@ -259,6 +296,18 @@ func (s *Store) WhitelistContains(ip string) (bool, error) {
|
||||
return err == nil, err
|
||||
}
|
||||
|
||||
func (s *Store) WhitelistByIP(ip string) (WhitelistEntry, bool, error) {
|
||||
var e WhitelistEntry
|
||||
err := s.DB.QueryRow(`SELECT ip_address, COALESCE(source,''), COALESCE(resolved_at,'') FROM whitelist_cache WHERE ip_address=? LIMIT 1`, ip).Scan(&e.IP, &e.Source, &e.ResolvedAt)
|
||||
if err == sql.ErrNoRows {
|
||||
return WhitelistEntry{}, false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return WhitelistEntry{}, false, err
|
||||
}
|
||||
return e, true, nil
|
||||
}
|
||||
|
||||
func (s *Store) ReplaceWhitelist(ips []string, source string) error {
|
||||
tx, err := s.DB.Begin()
|
||||
if err != nil {
|
||||
@@ -348,6 +397,19 @@ func (s *Store) CountExpiredOffenses(resetAfter int64) (int, error) {
|
||||
return count, err
|
||||
}
|
||||
|
||||
func (s *Store) OffenseByIP(ip string) (Offense, bool, error) {
|
||||
var o Offense
|
||||
err := s.DB.QueryRow(`SELECT client_ip, COALESCE(offense_level,0), COALESCE(last_offense_epoch,0), COALESCE(last_offense,''), COALESCE(first_offense,'')
|
||||
FROM offense_tracking WHERE client_ip=? LIMIT 1`, ip).Scan(&o.IP, &o.Level, &o.LastEpoch, &o.Last, &o.First)
|
||||
if err == sql.ErrNoRows {
|
||||
return Offense{}, false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return Offense{}, false, err
|
||||
}
|
||||
return o, true, nil
|
||||
}
|
||||
|
||||
func (s *Store) LoadGeoIPCache(ttl, dbMtime int64) (map[string]string, error) {
|
||||
rows, err := s.DB.Query(`SELECT ip, country_code FROM geoip_cache WHERE looked_up_at_epoch >= ? AND (db_mtime=? OR db_mtime=0)`, time.Now().Unix()-ttl, dbMtime)
|
||||
if err != nil {
|
||||
@@ -365,6 +427,18 @@ func (s *Store) LoadGeoIPCache(ttl, dbMtime int64) (map[string]string, error) {
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
func (s *Store) GeoIPCacheByIP(ip string) (GeoIPCacheEntry, bool, error) {
|
||||
var e GeoIPCacheEntry
|
||||
err := s.DB.QueryRow(`SELECT ip, country_code, COALESCE(looked_up_at_epoch,0), COALESCE(db_mtime,0) FROM geoip_cache WHERE ip=? LIMIT 1`, ip).Scan(&e.IP, &e.CountryCode, &e.LookedUpAtEpoch, &e.DBMtime)
|
||||
if err == sql.ErrNoRows {
|
||||
return GeoIPCacheEntry{}, false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return GeoIPCacheEntry{}, false, err
|
||||
}
|
||||
return e, true, nil
|
||||
}
|
||||
|
||||
func (s *Store) UpsertGeoIP(ip, country string, dbMtime int64) error {
|
||||
_, err := s.DB.Exec(`INSERT OR REPLACE INTO geoip_cache (ip, country_code, looked_up_at_epoch, db_mtime) VALUES (?, ?, ?, ?)`, ip, country, time.Now().Unix(), dbMtime)
|
||||
return err
|
||||
@@ -479,3 +553,21 @@ FROM ban_history WHERE action='BAN' AND timestamp_epoch BETWEEN ? AND ? ORDER BY
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
func (s *Store) RecentHistoryByIP(ip string, limit int) ([]string, error) {
|
||||
rows, err := s.DB.Query(`SELECT timestamp_text, action, client_ip, COALESCE(domain,''), COALESCE(count,''), COALESCE(duration,''), COALESCE(protocol,''), COALESCE(reason,'')
|
||||
FROM ban_history WHERE client_ip=? ORDER BY id DESC LIMIT ?`, ip, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []string
|
||||
for rows.Next() {
|
||||
var ts, action, clientIP, domain, count, duration, proto, reason string
|
||||
if err := rows.Scan(&ts, &action, &clientIP, &domain, &count, &duration, &proto, &reason); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, fmt.Sprintf("%s | %s | %s | %s | %s | %s | %s | %s", ts, action, clientIP, domain, count, duration, proto, reason))
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
@@ -29,3 +29,80 @@ func TestStoreBanAndGeoIPCache(t *testing.T) {
|
||||
t.Fatalf("unexpected cache: %#v", cache)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreIPStatusQueries(t *testing.T) {
|
||||
s, err := Open(filepath.Join(t.TempDir(), "test.db"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
ban := Ban{
|
||||
IP: "192.0.2.10",
|
||||
Domain: "example.com",
|
||||
Count: 42,
|
||||
BanUntil: 1234567890,
|
||||
Duration: 600,
|
||||
OffenseLevel: 2,
|
||||
Reason: "rate-limit",
|
||||
Protocol: "dns",
|
||||
Source: "monitor",
|
||||
}
|
||||
if err := s.InsertBan(ban); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
gotBan, ok, err := s.BanByIP("192.0.2.10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !ok || gotBan.IP != ban.IP || gotBan.Count != ban.Count || gotBan.Reason != ban.Reason {
|
||||
t.Fatalf("unexpected ban lookup: %#v found=%v", gotBan, ok)
|
||||
}
|
||||
if _, ok, err := s.BanByIP("192.0.2.11"); err != nil || ok {
|
||||
t.Fatalf("unexpected missing ban lookup: found=%v err=%v", ok, err)
|
||||
}
|
||||
|
||||
if _, err := s.DB.Exec(`INSERT INTO whitelist_cache (ip_address, source) VALUES (?, ?)`, "192.0.2.10", "external"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wl, ok, err := s.WhitelistByIP("192.0.2.10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !ok || wl.Source != "external" {
|
||||
t.Fatalf("unexpected whitelist lookup: %#v found=%v", wl, ok)
|
||||
}
|
||||
|
||||
if _, err := s.IncrementOffense("192.0.2.10", 86400); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
offense, ok, err := s.OffenseByIP("192.0.2.10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !ok || offense.Level != 1 || offense.LastEpoch == 0 {
|
||||
t.Fatalf("unexpected offense lookup: %#v found=%v", offense, ok)
|
||||
}
|
||||
|
||||
if err := s.UpsertGeoIP("192.0.2.10", "DE", 456); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
geo, ok, err := s.GeoIPCacheByIP("192.0.2.10")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !ok || geo.CountryCode != "DE" || geo.DBMtime != 456 {
|
||||
t.Fatalf("unexpected geo lookup: %#v found=%v", geo, ok)
|
||||
}
|
||||
|
||||
if err := s.History("BAN", "192.0.2.10", "example.com", "42", "600s", "dns", "rate-limit"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
history, err := s.RecentHistoryByIP("192.0.2.10", 5)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(history) != 1 {
|
||||
t.Fatalf("unexpected history: %#v", history)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user