Give every view a TSIG key that selects it
Each view's match-clients starts with "key jarl-view-NAME" (after
"!key" for the views listed after it), so a query signed with a view's
key lands in that view from any address. The secrets are derived from a
random seed in Jarl's database. The delegation check signs its queries
to this server's own addresses with the key of the zone's view: before,
they got whichever view matched the server's address, usually internal.
jarl view key / GET /views/{id}/key show a key for dig -k (tsig:write,
audited). jarl-view- key names are reserved; the importer drops view
keys from a configuration Jarl wrote.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c696d02513
commit
384f6b3060
26 files changed
+463
-16
No files matched your search
@@ -386,6 +386,7 @@ Disabling a record that is already disabled is a 409; with `missing_ok=1`
|
||||
| GET / PATCH / DELETE | `/views/{id}` | DELETE `?cascade=1` also deletes the view's zones |
|
||||
| POST | `/views/order` | `{"ids": [3, 1, 2]}` |
|
||||
| PUT | `/views/{id}/color` | `{"color": "green"}`; `""` for the default |
|
||||
| GET | `/views/{id}/key` | `{name, algorithm, secret}`: the TSIG key that selects the view (docs/views.md); needs `tsig:write`, audited |
|
||||
|
||||
`adopt_zones` moves zones that are not in a view into the new view. named
|
||||
requires every zone to be in a view as soon as one view exists.
|
||||
|
||||
@@ -368,6 +368,7 @@ jarl view order internal external
|
||||
jarl view update external --match-clients "!homelab,any"
|
||||
jarl view delete old [--cascade]
|
||||
jarl view color internal green # web UI colour; "default" resets it
|
||||
jarl view key external [--named-conf] # the key that selects the view (dig -k), docs/views.md
|
||||
|
||||
jarl acl create homelab 192.168.1.0/24 10.10.0.0/16 localhost
|
||||
jarl acl update homelab --add 10.20.0.0/16 --remove 10.10.0.0/16
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ showing them.
|
||||
| `acl_ref_missing`, `key_ref_missing` | error | Every ACL or TSIG key that is referenced must exist |
|
||||
| `acl_cycle` | error | ACLs that include each other |
|
||||
| `acl_duplicate`, `acl_name_invalid`, `acl_empty`, `acl_shadowed` | error / warning | Unique names, built-in names reserved, elements that can never match |
|
||||
| `key_*` | error / warning | Valid key names, a supported algorithm, a base64 secret of a sensible length. hmac-md5/sha1 are flagged as weak |
|
||||
| `key_*` | error / warning | Valid key names, a supported algorithm, a base64 secret of a sensible length. hmac-md5/sha1 are flagged as weak. Names starting with `jarl-view-` are reserved for the view keys (`key_name_reserved`) |
|
||||
| `view_duplicate`, `view_name_invalid`, `view_acl_invalid` | error | Valid, unique views and match lists |
|
||||
| `view_unreachable` | warning | A view that comes after one matching every client is never used |
|
||||
| `option_unknown`, `option_scope_invalid` | error | The option must exist in BIND 9.20 and be allowed where it is set (server, view, zone of this type, top level) |
|
||||
|
||||
+41
-2
@@ -116,7 +116,44 @@ dig @<public-ip> example.com # from outside: status R
|
||||
jarl check
|
||||
```
|
||||
|
||||
On the server, `dig -b <source address>` picks which view you test.
|
||||
On the server, `dig -b <source address>` picks which view you test, or,
|
||||
from anywhere, sign the query with the view's key (below):
|
||||
|
||||
```sh
|
||||
jarl view key external --named-conf > external.key
|
||||
dig -k external.key @ns1.adbraun.lol nas.adbraun.lol +short # 203.0.113.20, even from the LAN
|
||||
```
|
||||
|
||||
## View keys
|
||||
|
||||
named picks a view by where a query comes from, so a query this server
|
||||
sends to its own public address usually lands in the internal view: its
|
||||
source is one of your own networks. That makes checks of the external view
|
||||
from the server itself (such as Jarl's delegation check) see the wrong
|
||||
view.
|
||||
|
||||
So Jarl gives every view a TSIG key, `jarl-view-NAME`, and puts it at the
|
||||
front of the view's `match-clients`:
|
||||
|
||||
```
|
||||
view "internal" {
|
||||
match-clients { !key jarl-view-external; key jarl-view-internal; homelab; };
|
||||
...
|
||||
view "external" {
|
||||
match-clients { key jarl-view-external; any; };
|
||||
```
|
||||
|
||||
A query signed with a view's key lands in that view, whatever its source;
|
||||
the `!key` stops an earlier view from taking a later view's queries.
|
||||
Clients don't send these keys, so for them nothing changes. Jarl signs its
|
||||
own queries to this server's addresses with the key of the zone's view.
|
||||
The keys live in `keys.conf` with your other keys, never in diffs or in
|
||||
`jarl tsig list`; their secrets are derived from a random value in Jarl's
|
||||
database (and in its backups), so they stay the same from one apply to
|
||||
the next. `jarl view key VIEW`
|
||||
shows one (it needs `tsig:write` and is audited). Key names starting with
|
||||
`jarl-view-` are reserved, and the view keys can be used in your own
|
||||
options (`allow-transfer { key jarl-view-external; }`).
|
||||
|
||||
## Living with views
|
||||
|
||||
@@ -130,7 +167,9 @@ On the server, `dig -b <source address>` picks which view you test.
|
||||
`jarl view list` shows it.
|
||||
* Deleting a view is refused while it still has zones, unless you pass
|
||||
`--cascade`.
|
||||
* Give each view a colour (Views → Edit → Colour, or
|
||||
* Each view has its own page (Views → the view's name): its settings,
|
||||
options and zones.
|
||||
* Give each view a colour (the view's page → Settings → Colour, or
|
||||
`jarl view color internal green`) to tell the zones of each view apart
|
||||
in the zone list. The colour only affects the web UI, so it applies at
|
||||
once, with no changeset or deploy. `jarl view color internal default`
|
||||
|
||||
Reference in new issue
Block a user