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
@@ -108,6 +108,7 @@ func (s *Server) rulesetDiff(before, after *model.State) string {
|
||||
var kindOf = map[string]string{
|
||||
"zones": model.KindZone, "sets": model.KindSet, "services": model.KindService, "rules": model.KindRule,
|
||||
"forwards": model.KindForward, "snats": model.KindSNAT, "redirects": model.KindRedirect,
|
||||
"banlists": model.KindBanList,
|
||||
}
|
||||
|
||||
func pathKind(r *http.Request) (string, error) {
|
||||
@@ -128,13 +129,16 @@ func findObject(st *model.State, kind, ref string) (model.Object, error) {
|
||||
// ---- objects
|
||||
|
||||
func (s *Server) listObjects(w http.ResponseWriter, r *http.Request, p *auth.Principal) error {
|
||||
if err := require(p, auth.ResConfig, false); err != nil {
|
||||
return err
|
||||
}
|
||||
kind, err := pathKind(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if kind == model.KindBanList && !p.Can(auth.ResConfig, false) {
|
||||
return s.listOwnBanLists(w, p)
|
||||
}
|
||||
if err := require(p, auth.ResConfig, false); err != nil {
|
||||
return err
|
||||
}
|
||||
cur, st, draft, err := s.viewState(w, r)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -180,13 +184,22 @@ func (s *Server) listObjects(w http.ResponseWriter, r *http.Request, p *auth.Pri
|
||||
}
|
||||
|
||||
func (s *Server) getObject(w http.ResponseWriter, r *http.Request, p *auth.Principal) error {
|
||||
if err := require(p, auth.ResConfig, false); err != nil {
|
||||
return err
|
||||
}
|
||||
kind, err := pathKind(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// A program that bans into a list may read it (its grouping, times).
|
||||
if kind == model.KindBanList && !p.Can(auth.ResConfig, false) {
|
||||
b, err := s.banList(r, p, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
writeJSON(w, http.StatusOK, b)
|
||||
return nil
|
||||
}
|
||||
if err := require(p, auth.ResConfig, false); err != nil {
|
||||
return err
|
||||
}
|
||||
_, st, _, err := s.viewState(w, r)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -223,6 +236,8 @@ func decodeObject(kind string, data []byte) (model.Object, error) {
|
||||
o = &model.SourceNAT{}
|
||||
case model.KindRedirect:
|
||||
o = &model.Redirect{}
|
||||
case model.KindBanList:
|
||||
o = &model.BanList{}
|
||||
}
|
||||
dec := json.NewDecoder(strings.NewReader(string(data)))
|
||||
dec.DisallowUnknownFields()
|
||||
@@ -274,6 +289,8 @@ func setID(o model.Object, id int64) {
|
||||
x.ID = id
|
||||
case *model.Redirect:
|
||||
x.ID = id
|
||||
case *model.BanList:
|
||||
x.ID = id
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,6 +408,11 @@ func usedBy(st *model.State, kind string, o model.Object) string {
|
||||
return f.Label()
|
||||
}
|
||||
}
|
||||
for _, b := range st.BanLists {
|
||||
if has(b.Hosts) || has(b.Never) {
|
||||
return "ban list " + b.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -433,6 +455,10 @@ func renameRefs(st *model.State, kind, old, now string) {
|
||||
fix(f.PublicAddresses)
|
||||
fix(f.HairpinSources)
|
||||
}
|
||||
for _, b := range st.BanLists {
|
||||
fix(b.Hosts)
|
||||
fix(b.Never)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -669,3 +695,19 @@ func (s *Server) rollbackChanges(w http.ResponseWriter, r *http.Request, p *auth
|
||||
writeJSON(w, http.StatusOK, map[string]int{"rolled_back": n})
|
||||
return nil
|
||||
}
|
||||
|
||||
// listOwnBanLists lists the ban lists a principal without config:read
|
||||
// may use.
|
||||
func (s *Server) listOwnBanLists(w http.ResponseWriter, p *auth.Principal) error {
|
||||
out := []*model.BanList{}
|
||||
for _, b := range s.eng.State().BanLists {
|
||||
if p.CanBan(b.Name, false) {
|
||||
out = append(out, b)
|
||||
}
|
||||
}
|
||||
if len(out) == 0 && !p.Can(auth.ResBans, false) {
|
||||
return require(p, auth.ResConfig, false)
|
||||
}
|
||||
writeJSON(w, http.StatusOK, out)
|
||||
return nil
|
||||
}
|
||||
Reference in new issue
Block a user