|
|
<!-- vim:set spell spelllang=en colorcolumn=100: -->
|
|
|
# Design Document: Views
|
|
|
|
|
|
[[_TOC_]]
|
|
|
|
|
|
## Purpose of Views
|
|
|
|
|
|
Views allow the server to expose the same zone with different content to different clients. This
|
|
|
functionality has been available in BIND for years and although it brings some operational
|
|
|
problems, quite a lot of users are brave enough to request this functionality to be added into
|
|
|
Knot DNS.
|
|
|
|
|
|
## Proposed implementation
|
|
|
|
|
|
The proposed implementation utilizes existing ACLs with to build matching rules for views. The
|
|
|
views are defined in a new configuration section *view* and are process in order according to
|
|
|
their binary (alphabetically) ordered unique identifiers. The only attribute of the view is the
|
|
|
*acl* attribute which carries a list of ACLs to match. The **first matching ACL** determines the
|
|
|
view, **any ACL** in a view can match.
|
|
|
|
|
|
The new syntax is as follows:
|
|
|
|
|
|
```
|
|
|
view:
|
|
|
- id: STR
|
|
|
acl: acl_id ...
|
|
|
```
|
|
|
|
|
|
A view can be then assigned to a template or a zone using the *view* attribute. This attribute
|
|
|
is multi-valued and the zone can be thus assigned into multiple views. Also, in order to be able
|
|
|
to identify multiple zones with the same name but a different template, a **domain** attribute of
|
|
|
a zone is optionally suffixed with the at sign (`@`) and an arbitrary alias. The while attribute
|
|
|
must be unique.
|
|
|
|
|
|
The *template* and *zone* syntax is modified as follows:
|
|
|
|
|
|
```
|
|
|
template:
|
|
|
- id: STR
|
|
|
view: view_id ...
|
|
|
# existing options
|
|
|
```
|
|
|
|
|
|
zone:
|
|
|
- domain: DNAME[@STR]
|
|
|
view: view_id ...
|
|
|
# existing options
|
|
|
```
|
|
|
|
|
|
For backward compatibility, the defaults are defined as follows:
|
|
|
|
|
|
```
|
|
|
view:
|
|
|
- id: default
|
|
|
acl: []
|
|
|
|
|
|
template:
|
|
|
- id: default
|
|
|
view: default
|
|
|
# existing defaults
|
|
|
```
|
|
|
|
|
|
## Use Cases
|
|
|
|
|
|
This section describes a few basic uses of the proposed functionality with configuration file
|
|
|
examples.
|
|
|
|
|
|
### Public domain split-view
|
|
|
|
|
|
A company has a public domain *acme.test*. The zone visible to the world is different from the zone
|
|
|
visible to clients inside a internal network. In addition, there is an internal subdomain
|
|
|
*int.acme.test* visible only for the internal clients.
|
|
|
|
|
|
```yaml
|
|
|
acl:
|
|
|
- id: internal_clients
|
|
|
address: [192.168.0.0/16]
|
|
|
action: query
|
|
|
|
|
|
view:
|
|
|
- id: 00_internal
|
|
|
acl: interal_clients
|
|
|
- id: 99_external
|
|
|
|
|
|
zone:
|
|
|
- domain: acme.test
|
|
|
view: 99_external
|
|
|
file: acme.test.zone
|
|
|
- domain: acme.test@internal
|
|
|
view: 00_internal
|
|
|
file: int/acme.test.zone
|
|
|
- domain: int.acme.test
|
|
|
view: 00_internal
|
|
|
file: int/int.acme.test.zone
|
|
|
```
|
|
|
|
|
|
### Zone in multiple views
|
|
|
|
|
|
A zone can be exposed via multiple views. Let's have an external network, an office network, and
|
|
|
a lab network. Again, the parent zone *acme.test* exists in two variants (one for the world, one
|
|
|
internal for the company) and again the *int.acme.test* child zone is available to all internal
|
|
|
clients. In addition, there is a *builds.acme.test* zone visible only within the lab network.
|
|
|
In addition, a system administrator can use their TSIG key and access that zone from anywhere.
|
|
|
|
|
|
```yaml
|
|
|
key:
|
|
|
- id: alice.admin
|
|
|
algorithm: hmac-sha256
|
|
|
secret: ffObJdpfV2AiY7qHQgLFbk0mOzaGfyKQFmx/kpg2lE8=
|
|
|
|
|
|
acl:
|
|
|
- id: office
|
|
|
address: 192.168.1.0/24
|
|
|
action: query
|
|
|
- id: lab
|
|
|
address: [192.168.2.0/24, 10.0.0.0/8]
|
|
|
action: query
|
|
|
- id: admins
|
|
|
key: alice.admin
|
|
|
action: query
|
|
|
|
|
|
view:
|
|
|
- id: 00_admin
|
|
|
acl: admins
|
|
|
- id: 01_office
|
|
|
acl: office
|
|
|
- id: 02_lab
|
|
|
acl: lab
|
|
|
- id: 99_external
|
|
|
|
|
|
zone:
|
|
|
- domain: acme.test
|
|
|
view: 99_external
|
|
|
file: acme.test.zone
|
|
|
- domain: acme.test@internal
|
|
|
view: [00_admin, 01_office, 02_lab]
|
|
|
file: int/acme.test.zone
|
|
|
- domain: int.acme.test
|
|
|
view: [00_admin, 01_office, 02_lab]
|
|
|
file: int/acme.test.zone
|
|
|
- domain: builds.acme.test
|
|
|
view: [00_admin, 02_lab]
|
|
|
file: builds.acme.test.zone
|
|
|
```
|
|
|
|
|
|
### Zone transfers with views
|
|
|
|
|
|
To differentiate a view for the purpose of zone transfer, a different TSIG key can be used. Let's
|
|
|
limit the configuration to two views only, and share the common configuration between zones using
|
|
|
templates.
|
|
|
|
|
|
Master server configuration:
|
|
|
|
|
|
```yaml
|
|
|
key:
|
|
|
- id: int.slaves
|
|
|
algorithm: hmac-sha256
|
|
|
secret: vZNKk2r/iuybafZ1mjpEHnzaThr/xcTSBLtOmOHVtbo=
|
|
|
- id: ext.slaves
|
|
|
algorithm: hmac-sha256
|
|
|
secret: HVo02ON60KDJneMIpKksSqCWa4w5CwE44U45aIpGfv8=
|
|
|
|
|
|
acl:
|
|
|
- id: transfer_to_slave
|
|
|
key: [int.slaves, ext.slaves]
|
|
|
address: 172.16.100.0/8
|
|
|
action: transfer
|
|
|
- id: query_from_slave_internal
|
|
|
address: 172.16.100.0/8
|
|
|
key: int.slaves
|
|
|
action: query
|
|
|
- id: query_from_slave_external
|
|
|
address: 172.16.100.0/8
|
|
|
key: ext.slaves
|
|
|
action: query
|
|
|
- id: query_from_internal_client
|
|
|
address: [ 192.168.0.0/16, 10.0.0.0/8 ]
|
|
|
action: query
|
|
|
|
|
|
view:
|
|
|
- id: 00_internal
|
|
|
acl: [query_from_internal_client, query_from_slave_internal]
|
|
|
- id: 99_external
|
|
|
|
|
|
template:
|
|
|
- id: default
|
|
|
view: internal
|
|
|
file: "/var/lib/knot/int_%s.zone"
|
|
|
acl: [transfer_to_slave]
|
|
|
- id: external
|
|
|
view: external
|
|
|
file: "/var/lib/knot/ext_%s.zone"
|
|
|
acl: [transfer_to_slave]
|
|
|
|
|
|
zone:
|
|
|
- domain: acme.test@ext
|
|
|
template: external
|
|
|
- domain: acme.test
|
|
|
- domain: int.acme.test
|
|
|
```
|
|
|
|
|
|
Matching slave server configuration:
|
|
|
|
|
|
```yaml
|
|
|
# key: ...
|
|
|
|
|
|
# view: ...
|
|
|
|
|
|
remote:
|
|
|
- id: master_as_internal
|
|
|
address: 172.16.100.1
|
|
|
key: int.slaves
|
|
|
- id: master_as_external
|
|
|
address: 172.16.100.1
|
|
|
key: ext.slaves
|
|
|
|
|
|
template:
|
|
|
- id: default
|
|
|
view: internal
|
|
|
file: "/var/lib/knot/int_%s.zone"
|
|
|
master: master_as_internal
|
|
|
- id: external
|
|
|
view: external
|
|
|
file: "/var/lib/knot/ext_%s.zone"
|
|
|
master: master_as_external
|
|
|
|
|
|
# zone: ...
|
|
|
``` |