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
@@ -392,3 +392,103 @@ func (r *Redirect) Label() string {
|
||||
}
|
||||
return fmt.Sprintf("redirect #%d", r.ID)
|
||||
}
|
||||
|
||||
// Ban list scopes: what a list's bans keep the banned addresses from.
|
||||
const (
|
||||
// BanScopeFirewall: the firewall itself (the input chain).
|
||||
BanScopeFirewall = "firewall"
|
||||
// BanScopeHosts: the list's hosts, behind the firewall (the forward
|
||||
// chain, where port forwards' addresses are already translated).
|
||||
BanScopeHosts = "hosts"
|
||||
// BanScopeEverything: the firewall and everything behind it.
|
||||
BanScopeEverything = "everything"
|
||||
)
|
||||
|
||||
// BanScopes lists the scopes.
|
||||
var BanScopes = []string{BanScopeFirewall, BanScopeHosts, BanScopeEverything}
|
||||
|
||||
// Ban lists' defaults.
|
||||
const (
|
||||
DefaultBanTime = 3600
|
||||
DefaultBanMaxTime = 7 * 24 * 3600
|
||||
DefaultBanEntries = 10000
|
||||
DefaultBanGroupV6 = 64
|
||||
)
|
||||
|
||||
// BanList is where a program such as Guard, or fail2ban, bans addresses
|
||||
// (docs/bans.md). The program names only the address, and perhaps a
|
||||
// protocol and ports; the list says what the address is kept from. The
|
||||
// bans themselves are kept apart from the configuration, like a dynamic
|
||||
// set's entries.
|
||||
type BanList struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Scope string `json:"scope"`
|
||||
// Hosts are set names or addresses: what scope hosts protects.
|
||||
Hosts []string `json:"hosts,omitempty"`
|
||||
// Never are set names or addresses the list never bans.
|
||||
Never []string `json:"never,omitempty"`
|
||||
// DefaultTime is a ban's length in seconds when none is asked for
|
||||
// (0: an hour); MaxTime the longest (0: a week; -1: no limit, so
|
||||
// bans may be permanent).
|
||||
DefaultTime int `json:"default_time,omitempty"`
|
||||
MaxTime int `json:"max_time,omitempty"`
|
||||
// MaxEntries limits the bans the list holds (0: 10000).
|
||||
MaxEntries int `json:"max_entries,omitempty"`
|
||||
// GroupV6 is the IPv6 prefix length banned for an address (0: /64,
|
||||
// what one customer usually gets); IPv4 addresses are banned alone.
|
||||
GroupV6 int `json:"group_v6,omitempty"`
|
||||
Comment string `json:"comment,omitempty"`
|
||||
Disabled bool `json:"disabled,omitempty"`
|
||||
}
|
||||
|
||||
func (b *BanList) GetID() int64 { return b.ID }
|
||||
func (b *BanList) Label() string { return b.Name }
|
||||
|
||||
// BanTime is the default ban length in seconds.
|
||||
func (b *BanList) BanTime() int {
|
||||
if b.DefaultTime > 0 {
|
||||
return b.DefaultTime
|
||||
}
|
||||
return DefaultBanTime
|
||||
}
|
||||
|
||||
// BanMaxTime is the longest ban in seconds, 0 for no limit.
|
||||
func (b *BanList) BanMaxTime() int {
|
||||
switch {
|
||||
case b.MaxTime < 0:
|
||||
return 0
|
||||
case b.MaxTime > 0:
|
||||
return b.MaxTime
|
||||
}
|
||||
return DefaultBanMaxTime
|
||||
}
|
||||
|
||||
// Entries is the most bans the list holds.
|
||||
func (b *BanList) Entries() int {
|
||||
if b.MaxEntries > 0 {
|
||||
return b.MaxEntries
|
||||
}
|
||||
return DefaultBanEntries
|
||||
}
|
||||
|
||||
// V6Group is the IPv6 prefix length an address is banned with.
|
||||
func (b *BanList) V6Group() int {
|
||||
if b.GroupV6 > 0 {
|
||||
return b.GroupV6
|
||||
}
|
||||
return DefaultBanGroupV6
|
||||
}
|
||||
|
||||
// Covers reports whether the list's bans apply to a chain.
|
||||
func (b *BanList) Covers(chain string) bool {
|
||||
switch b.Scope {
|
||||
case BanScopeFirewall:
|
||||
return chain == ChainInput
|
||||
case BanScopeHosts:
|
||||
return chain == ChainForward
|
||||
case BanScopeEverything:
|
||||
return chain == ChainInput || chain == ChainForward
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in new issue
Block a user