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
+14
-4
@@ -43,7 +43,7 @@ named answers "doesn't exist" for the domains on them (docs/blocking.md).
|
||||
Hosts, plain domain and Adblock (||domain^) lists work. Your own block and
|
||||
allow rules ('jarl block') take precedence over every list.`}
|
||||
var views []string
|
||||
var comment string
|
||||
var comment, step string
|
||||
|
||||
list := &cobra.Command{
|
||||
Use: "list",
|
||||
@@ -59,7 +59,7 @@ allow rules ('jarl block') take precedence over every list.`}
|
||||
return err
|
||||
}
|
||||
return output(lists, func(w io.Writer) {
|
||||
fmt.Fprintln(w, "NAME\tSTATE\tDOMAINS\tVIEWS\tUPDATED\tMEMORY\tURL")
|
||||
fmt.Fprintln(w, "NAME\tSTATE\tSTEP\tDOMAINS\tVIEWS\tUPDATED\tMEMORY\tURL")
|
||||
for _, b := range lists {
|
||||
domains, updated, mem := "-", "-", "-"
|
||||
if s := b.Status; s != nil && s.UpdatedAt != nil {
|
||||
@@ -68,7 +68,7 @@ allow rules ('jarl block') take precedence over every list.`}
|
||||
if b.MemoryMB > 0 {
|
||||
mem = fmt.Sprintf("~%d MB", b.MemoryMB)
|
||||
}
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", b.Name, b.State, domains, viewsText(b.Views, b.AutoViews), updated, mem, b.URL)
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", b.Name, b.State, b.Step, domains, viewsText(b.Views, b.AutoViews), updated, mem, b.URL)
|
||||
}
|
||||
for _, b := range lists {
|
||||
if b.Status != nil && b.Status.Error != "" {
|
||||
@@ -95,6 +95,9 @@ allow rules ('jarl block') take precedence over every list.`}
|
||||
}
|
||||
body := map[string]any{"name": args[0], "url": args[1]}
|
||||
viewsBody(body, views)
|
||||
if step != "" {
|
||||
body["step"] = step
|
||||
}
|
||||
if comment != "" {
|
||||
body["comment"] = comment
|
||||
}
|
||||
@@ -111,6 +114,7 @@ allow rules ('jarl block') take precedence over every list.`}
|
||||
}
|
||||
add.Flags().StringArrayVar(&views, "view", nil, "a view it applies to (repeat for several; default: every view that offers recursion)")
|
||||
add.Flags().StringVar(&comment, "comment", "", "comment")
|
||||
add.Flags().StringVar(&step, "step", "", "the blocking step it starts at (default: normal; see 'jarl block step')")
|
||||
|
||||
var rename, newURL string
|
||||
update := &cobra.Command{
|
||||
@@ -136,6 +140,9 @@ allow rules ('jarl block') take precedence over every list.`}
|
||||
if f.Changed("comment") {
|
||||
body["comment"] = comment
|
||||
}
|
||||
if f.Changed("step") {
|
||||
body["step"] = step
|
||||
}
|
||||
viewsBody(body, views)
|
||||
if len(body) == 0 {
|
||||
return fmt.Errorf("nothing to change (see --help)")
|
||||
@@ -151,6 +158,7 @@ allow rules ('jarl block') take precedence over every list.`}
|
||||
update.Flags().StringVar(&newURL, "url", "", "new URL")
|
||||
update.Flags().StringArrayVar(&views, "view", nil, `a view it applies to (repeat for several; "auto": every view that offers recursion)`)
|
||||
update.Flags().StringVar(&comment, "comment", "", "new comment")
|
||||
update.Flags().StringVar(&step, "step", "", "the blocking step it starts at (normal, or a step above it)")
|
||||
|
||||
toggle := func(disable bool) *cobra.Command {
|
||||
verb := map[bool]string{true: "disable", false: "enable"}[disable]
|
||||
@@ -394,6 +402,8 @@ names below it (docs/blocking.md).`}
|
||||
switch {
|
||||
case m.Result == "none":
|
||||
fmt.Fprintf(w, "%snot blocked\n", where)
|
||||
case m.List != "" && m.Step != "":
|
||||
fmt.Fprintf(w, "%sblocked for clients at step %s and above, by blocklist %s (entry %s); not for others\n", where, m.Step, m.List, m.Entry)
|
||||
case m.List != "":
|
||||
fmt.Fprintf(w, "%sblocked by blocklist %s (entry %s)\n", where, m.List, m.Entry)
|
||||
default:
|
||||
@@ -473,7 +483,7 @@ at once. "indefinitely" pauses until 'jarl block resume'.
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(addRule("block"), addRule("allow"), list, del, check, pause, resume)
|
||||
cmd.AddCommand(addRule("block"), addRule("allow"), list, del, check, pause, resume, blockStepCmd(), blockGroupCmd())
|
||||
return cmd
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user