When using the view plugin, filtered and unfiltered server blocks can share the same zone and port. The zone overlap validation rejected this configuration when the unfiltered block was not declared last, because filtered configs treated an already-registered zone as an error. Skip the 'already defined' check for configs that have filter functions, since they are expected to coexist with an unfiltered catch-all block on the same zone/port. Fixes #7733 Signed-off-by: umut-polat <52835619+umut-polat@users.noreply.github.com>
4.4 KiB
view
Name
view - defines conditions that must be met for a DNS request to be routed to the server block.
Description
view defines an expression that must evaluate to true for a DNS request to be routed to the server block. This enables advanced server block routing functions such as split dns.
Syntax
view NAME {
expr EXPRESSION
}
viewNAME - The name of the view used by metrics and exported as metadata for requests that match the view's expressionexprEXPRESSION - CoreDNS will only route incoming queries to the enclosing server block if the EXPRESSION evaluates to true. See the Expressions section for available variables and functions. If multiple instances of view are defined, all EXPRESSION must evaluate to true for CoreDNS will only route incoming queries to the enclosing server block.
For expression syntax and examples, see the Expressions and Examples sections.
Server Block Ordering
Server blocks sharing the same zone and port are evaluated top to bottom. The first block whose view expression matches (or that has no view) handles the query. An unfiltered catch-all block declared before a filtered block will shadow it, because the catch-all matches every query.
To get the expected split-DNS behavior, declare all filtered (view) blocks first and the unfiltered catch-all block last.
Examples
Implement CIDR based split DNS routing. This will return a different
answer for test. depending on client's IP address. It returns ...
test. 3600 IN A 1.1.1.1, for queries with a source address in 127.0.0.0/24test. 3600 IN A 2.2.2.2, for queries with a source address in 192.168.0.0/16test. 3600 IN AAAA 2001:0DB8::1, for queries with a source address in 2001:0DB8::/32test. 3600 IN A 3.3.3.3, for all others
. {
view example1 {
expr incidr(client_ip(), '127.0.0.0/24')
}
hosts {
1.1.1.1 test
}
}
. {
view example2 {
expr incidr(client_ip(), '192.168.0.0/16')
}
hosts {
2.2.2.2 test
}
}
. {
view v6_example1 {
expr incidr(client_ip(), '2001:0DB8::/32')
}
hosts {
2001:0DB8::1 test
}
}
}
. {
hosts {
3.3.3.3 test
}
}
Send all A and AAAA requests to 10.0.0.6, and all other requests to 10.0.0.1.
. {
view example {
expr type() in ['A', 'AAAA']
}
forward . 10.0.0.6
}
. {
forward . 10.0.0.1
}
Send all requests for abc.*.example.com (where * can be any number of labels), to 10.0.0.2, and all other
requests to 10.0.0.1.
Note that the regex pattern is enclosed in single quotes, and backslashes are escaped with backslashes.
. {
view example {
expr name() matches '^abc\\..*\\.example\\.com\\.$'
}
forward . 10.0.0.2
}
. {
forward . 10.0.0.1
}
Expressions
To evaluate expressions, view uses the expr-lang/expr package ( https://github.com/expr-lang/expr ).
For example, an expression could look like:
(type() == 'A' && name() == 'example.com.') || client_ip() == '1.2.3.4'.
All expressions should be written to evaluate to a boolean value.
See https://github.com/expr-lang/expr/blob/master/docs/language-definition.md as a detailed reference for valid syntax.
Available Expression Functions
In the context of the view plugin, expressions can reference DNS query information by using utility functions defined below.
DNS Query Functions
bufsize() int: the EDNS0 buffer size advertised in the queryclass() string: class of the request (IN, CH, ...)client_ip() string: client's IP address, for IPv6 addresses these are enclosed in brackets:[::1]do() bool: the EDNS0 DO (DNSSEC OK) bit set in the queryid() int: query IDname() string: name of the request (the domain name requested ending with a dot):example.com.opcode() int: query OPCODEport() string: client's portproto() string: protocol used (tcp or udp)server_ip() string: server's IP address; for IPv6 addresses these are enclosed in brackets:[::1]server_port() string: server's portsize() int: request size in bytestype() string: type of the request (A, AAAA, TXT, ...)
Utility Functions
incidr(ip string, cidr string) bool: returns true if ip is within cidrmetadata(label string)- returns the value for the metadata matching label
Metadata
The view plugin will publish the following metadata, if the metadata plugin is also enabled:
view/name: the name of the view handling the current request