Different blocking for different devices: steps and client groups
Client groups put devices (addresses, networks, or ACLs of them) at a blocking step: off (only your rules), normal (the default), or steps added above it, each including the lists of the steps below. Lists start at a step. In each view, a gate policy zone in front of a step's lists lets the devices below that step through (rpz-client-ip triggers with rpz-passthru), so every list is still loaded once. The IPv6 part of a gate leaves the IPv4-mapped range out: named matches IPv4 clients as ::ffff:a.b.c.d. Web UI: a Devices panel on the Blocking page and a step on each list. CLI: jarl block step, jarl block group, jarl blocklist --step. API: /blocking/steps, /blocking/groups. Database schema 8. Also: copying the state kept empty lists as empty (not nil), so reverting a changeset no longer adds restore operations for unchanged blocklists, rules and views. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5b8f681e2a
commit
76aaaf3ef5
33 files changed
+2096
-55
No files matched your search
+29
-12
@@ -9,6 +9,7 @@ package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -247,8 +248,10 @@ type State struct {
|
||||
Records map[int64]*Record
|
||||
Options map[int64]*Option
|
||||
// Blocking (docs/blocking.md).
|
||||
Blocklists map[int64]*Blocklist
|
||||
BlockRules map[int64]*BlockRule
|
||||
Blocklists map[int64]*Blocklist
|
||||
BlockRules map[int64]*BlockRule
|
||||
BlockSteps map[int64]*BlockStep
|
||||
ClientGroups map[int64]*ClientGroup
|
||||
}
|
||||
|
||||
// NewState returns an empty state with default settings.
|
||||
@@ -262,8 +265,10 @@ func NewState() *State {
|
||||
Records: map[int64]*Record{},
|
||||
Options: map[int64]*Option{},
|
||||
|
||||
Blocklists: map[int64]*Blocklist{},
|
||||
BlockRules: map[int64]*BlockRule{},
|
||||
Blocklists: map[int64]*Blocklist{},
|
||||
BlockRules: map[int64]*BlockRule{},
|
||||
BlockSteps: map[int64]*BlockStep{},
|
||||
ClientGroups: map[int64]*ClientGroup{},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,14 +283,16 @@ func (s *State) Clone() *State {
|
||||
Records: make(map[int64]*Record, len(s.Records)),
|
||||
Options: make(map[int64]*Option, len(s.Options)),
|
||||
|
||||
Blocklists: make(map[int64]*Blocklist, len(s.Blocklists)),
|
||||
BlockRules: make(map[int64]*BlockRule, len(s.BlockRules)),
|
||||
Blocklists: make(map[int64]*Blocklist, len(s.Blocklists)),
|
||||
BlockRules: make(map[int64]*BlockRule, len(s.BlockRules)),
|
||||
BlockSteps: make(map[int64]*BlockStep, len(s.BlockSteps)),
|
||||
ClientGroups: make(map[int64]*ClientGroup, len(s.ClientGroups)),
|
||||
}
|
||||
c.Settings.Nameservers = append([]string(nil), s.Settings.Nameservers...)
|
||||
c.Settings.Nameservers = slices.Clone(s.Settings.Nameservers)
|
||||
for id, v := range s.Views {
|
||||
n := *v
|
||||
n.MatchClients = append([]string(nil), v.MatchClients...)
|
||||
n.MatchDestinations = append([]string(nil), v.MatchDestinations...)
|
||||
n.MatchClients = slices.Clone(v.MatchClients)
|
||||
n.MatchDestinations = slices.Clone(v.MatchDestinations)
|
||||
if v.MatchRecursiveOnly != nil {
|
||||
b := *v.MatchRecursiveOnly
|
||||
n.MatchRecursiveOnly = &b
|
||||
@@ -294,7 +301,7 @@ func (s *State) Clone() *State {
|
||||
}
|
||||
for id, a := range s.ACLs {
|
||||
n := *a
|
||||
n.Elements = append([]string(nil), a.Elements...)
|
||||
n.Elements = slices.Clone(a.Elements)
|
||||
c.ACLs[id] = &n
|
||||
}
|
||||
for id, k := range s.Keys {
|
||||
@@ -319,14 +326,24 @@ func (s *State) Clone() *State {
|
||||
}
|
||||
for id, b := range s.Blocklists {
|
||||
n := *b
|
||||
n.ViewIDs = append([]int64(nil), b.ViewIDs...)
|
||||
n.ViewIDs = slices.Clone(b.ViewIDs)
|
||||
c.Blocklists[id] = &n
|
||||
}
|
||||
for id, r := range s.BlockRules {
|
||||
n := *r
|
||||
n.ViewIDs = append([]int64(nil), r.ViewIDs...)
|
||||
n.ViewIDs = slices.Clone(r.ViewIDs)
|
||||
c.BlockRules[id] = &n
|
||||
}
|
||||
for id, st := range s.BlockSteps {
|
||||
n := *st
|
||||
c.BlockSteps[id] = &n
|
||||
}
|
||||
for id, g := range s.ClientGroups {
|
||||
n := *g
|
||||
n.Members = slices.Clone(g.Members)
|
||||
n.ViewIDs = slices.Clone(g.ViewIDs)
|
||||
c.ClientGroups[id] = &n
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user