defender: don't return expired hosts/banned ip

This commit is contained in:
Nicola Murino 2021-06-19 11:02:46 +02:00
parent 62744e081b
commit 6321d51a24
No known key found for this signature in database
GPG key ID: 2F1FB59433D5A8CB
2 changed files with 98 additions and 10 deletions

View file

@ -236,17 +236,27 @@ func (d *memoryDefender) GetHosts() []*DefenderEntry {
var result []*DefenderEntry var result []*DefenderEntry
for k, v := range d.banned { for k, v := range d.banned {
if v.After(time.Now()) {
result = append(result, &DefenderEntry{ result = append(result, &DefenderEntry{
IP: k, IP: k,
BanTime: v, BanTime: v,
}) })
} }
}
for k, v := range d.hosts { for k, v := range d.hosts {
score := 0
for _, event := range v.Events {
if event.dateTime.Add(time.Duration(d.config.ObservationTime) * time.Minute).After(time.Now()) {
score += event.score
}
}
if score > 0 {
result = append(result, &DefenderEntry{ result = append(result, &DefenderEntry{
IP: k, IP: k,
Score: v.TotalScore, Score: score,
}) })
} }
}
return result return result
} }
@ -339,9 +349,12 @@ func (d *memoryDefender) AddEvent(ip string, event HostEvent) {
} }
// ignore events for already banned hosts // ignore events for already banned hosts
if _, ok := d.banned[ip]; ok { if v, ok := d.banned[ip]; ok {
if v.After(time.Now()) {
return return
} }
delete(d.banned, ip)
}
var score int var score int

View file

@ -179,6 +179,81 @@ func TestBasicDefender(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
} }
func TestExpiredHostBans(t *testing.T) {
config := &DefenderConfig{
Enabled: true,
BanTime: 10,
BanTimeIncrement: 2,
Threshold: 5,
ScoreInvalid: 2,
ScoreValid: 1,
ScoreLimitExceeded: 3,
ObservationTime: 15,
EntriesSoftLimit: 1,
EntriesHardLimit: 2,
}
d, err := newInMemoryDefender(config)
assert.NoError(t, err)
defender := d.(*memoryDefender)
testIP := "1.2.3.4"
defender.banned[testIP] = time.Now().Add(-24 * time.Hour)
// the ban is expired testIP should not be listed
res := defender.GetHosts()
assert.Len(t, res, 0)
assert.False(t, defender.IsBanned(testIP))
entry, err := defender.GetHost(testIP)
assert.NoError(t, err)
assert.Equal(t, testIP, entry.IP)
assert.NotEmpty(t, entry.GetBanTime())
// now add an event for an expired banned ip, it should be removed
defender.AddEvent(testIP, HostEventLoginFailed)
assert.False(t, defender.IsBanned(testIP))
entry, err = defender.GetHost(testIP)
assert.NoError(t, err)
assert.Equal(t, testIP, entry.IP)
assert.Empty(t, entry.GetBanTime())
assert.Equal(t, 1, entry.Score)
res = defender.GetHosts()
if assert.Len(t, res, 1) {
assert.Equal(t, testIP, res[0].IP)
assert.Empty(t, res[0].GetBanTime())
assert.Equal(t, 1, res[0].Score)
}
events := []hostEvent{
{
dateTime: time.Now().Add(-24 * time.Hour),
score: 2,
},
{
dateTime: time.Now().Add(-24 * time.Hour),
score: 3,
},
}
hs := hostScore{
Events: events,
TotalScore: 5,
}
defender.hosts[testIP] = hs
// the recorded scored are too old
res = defender.GetHosts()
assert.Len(t, res, 0)
// the old API still returns the host
entry, err = defender.GetHost(testIP)
assert.NoError(t, err)
assert.Equal(t, testIP, entry.IP)
assert.Empty(t, entry.GetBanTime())
assert.Equal(t, 5, entry.Score)
}
func TestLoadHostListFromFile(t *testing.T) { func TestLoadHostListFromFile(t *testing.T) {
_, err := loadHostListFromFile(".") _, err := loadHostListFromFile(".")
assert.Error(t, err) assert.Error(t, err)