Ban lists: where Guard and fail2ban ban addresses
A program bans an address (every port, or a protocol's ports) for a time; the ban list says what it is kept from: the firewall, some hosts behind it, or everything. Bans drop ahead of every rule, close the address's connections, group IPv6 by /64, are kept in the database across restarts and audited. Never banned: the inside, the firewall's own addresses, the caller, the list's never. bans grant (bans:write:LIST), hc banlist/bans/ban/unban, Traffic -> Bans, a fail2ban action in contrib/, and failed logins and refused tokens logged for Guard and fail2ban. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6f56eefae2
commit
500bfc7bdd
44 files changed
+2541
-39
No files matched your search
@@ -103,3 +103,60 @@ func TestUsersAndAudit(t *testing.T) {
|
||||
t.Errorf("audit %+v", evs)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBans(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
s, err := Open(filepath.Join(t.TempDir(), "housecarl.db"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer s.Close()
|
||||
in := func(d time.Duration) *time.Time { t := time.Now().Add(d); return &t }
|
||||
b := &model.Ban{ListID: 7, Address: "203.0.113.9", Expires: in(time.Hour), Who: "guard", Source: "guard/ssh"}
|
||||
if existing, err := s.PutBan(ctx, b); err != nil || existing {
|
||||
t.Fatalf("new ban: %v %v", existing, err)
|
||||
}
|
||||
id := b.ID
|
||||
again := &model.Ban{ListID: 7, Address: "203.0.113.9", Expires: in(2 * time.Hour), Who: "guard", Reason: "again"}
|
||||
if existing, err := s.PutBan(ctx, again); err != nil || !existing || again.ID != id {
|
||||
t.Fatalf("renewed ban: %v %v id %d, want %d", existing, err, again.ID, id)
|
||||
}
|
||||
port := &model.Ban{ListID: 7, Address: "2001:db8:1:2::/64", Protocol: "tcp", Port: 22}
|
||||
if _, err := s.PutBan(ctx, port); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
gone := &model.Ban{ListID: 7, Address: "198.51.100.1", Expires: in(-time.Second)}
|
||||
if _, err := s.PutBan(ctx, gone); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
other := &model.Ban{ListID: 8, Address: "198.51.100.2"}
|
||||
if _, err := s.PutBan(ctx, other); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
list, err := s.ListBans(ctx, 7)
|
||||
if err != nil || len(list) != 2 {
|
||||
t.Fatalf("list 7: %v %+v", err, list)
|
||||
}
|
||||
if list[0].Reason != "again" || list[0].Timeout < 7100 || list[0].Timeout > 7200 || list[1].Expires != nil || list[1].Timeout != 0 {
|
||||
t.Errorf("bans: %+v %+v", list[0], list[1])
|
||||
}
|
||||
if n, _ := s.CountBans(ctx, 7); n != 2 {
|
||||
t.Errorf("count %d", n)
|
||||
}
|
||||
// An ended ban is renewed as new.
|
||||
if existing, _ := s.PutBan(ctx, &model.Ban{ListID: 7, Address: "198.51.100.1", Expires: in(time.Minute)}); existing {
|
||||
t.Error("an ended ban counted as existing")
|
||||
}
|
||||
if n, err := s.PruneBans(ctx, []int64{7}); err != nil || n != 1 {
|
||||
t.Errorf("prune: %d %v (list 8's ban)", n, err)
|
||||
}
|
||||
if all, _ := s.ListBans(ctx, 0); len(all) != 3 {
|
||||
t.Errorf("after pruning: %+v", all)
|
||||
}
|
||||
if err := s.DeleteBan(ctx, id); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := s.GetBan(ctx, id); !errors.Is(err, ErrNotFound) {
|
||||
t.Errorf("deleted ban: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user