470 lines
12 KiB
Groff
470 lines
12 KiB
Groff
.\" Generated by Mmark Markdown Processer - mmark.miek.nl
|
|
.TH "COREDNS-REWRITE" 7 "March 2021" "CoreDNS" "CoreDNS Plugins"
|
|
|
|
.SH "NAME"
|
|
.PP
|
|
\fIrewrite\fP - performs internal message rewriting.
|
|
|
|
.SH "DESCRIPTION"
|
|
.PP
|
|
Rewrites are invisible to the client. There are simple rewrites (fast) and complex rewrites
|
|
(slower), but they're powerful enough to accommodate most dynamic back-end applications.
|
|
|
|
.SH "SYNTAX"
|
|
.PP
|
|
A simplified/easy-to-digest syntax for \fIrewrite\fP is...
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
rewrite [continue|stop] FIELD [FROM TO|FROM TTL]
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.IP \(bu 4
|
|
\fBFIELD\fP indicates what part of the request/response is being re-written.
|
|
|
|
.RS
|
|
.IP \(en 4
|
|
\fB\fCtype\fR - the type field of the request will be rewritten. FROM/TO must be a DNS record type (\fB\fCA\fR, \fB\fCMX\fR, etc.);
|
|
e.g., to rewrite ANY queries to HINFO, use \fB\fCrewrite type ANY HINFO\fR.
|
|
.IP \(en 4
|
|
\fB\fCclass\fR - the class of the message will be rewritten. FROM/TO must be a DNS class type (\fB\fCIN\fR, \fB\fCCH\fR, or \fB\fCHS\fR); e.g., to rewrite CH queries to IN use \fB\fCrewrite class CH IN\fR.
|
|
.IP \(en 4
|
|
\fB\fCname\fR - the query name in the \fIrequest\fP is rewritten; by default this is a full match of the
|
|
name, e.g., \fB\fCrewrite name example.net example.org\fR. Other match types are supported, see the \fBName Field Rewrites\fP section below.
|
|
.IP \(en 4
|
|
\fB\fCanswer name\fR - the query name in the \fIresponse\fP is rewritten. This option has special restrictions and requirements, in particular it must always combined with a \fB\fCname\fR rewrite. See below in the \fBResponse Rewrites\fP section.
|
|
.IP \(en 4
|
|
\fB\fCedns0\fR - an EDNS0 option can be appended to the request as described below in the \fBEDNS0 Options\fP section.
|
|
.IP \(en 4
|
|
\fB\fCttl\fR - the TTL value in the \fIresponse\fP is rewritten.
|
|
|
|
.RE
|
|
.IP \(bu 4
|
|
\fBFROM\fP is the name (exact, suffix, prefix, substring, or regex) or type to match
|
|
.IP \(bu 4
|
|
\fBTO\fP is the destination name or type to rewrite to
|
|
.IP \(bu 4
|
|
\fBTTL\fP is the number of seconds to set the TTL value to
|
|
|
|
|
|
.PP
|
|
If you specify multiple rules and an incoming query matches multiple rules, the rewrite
|
|
will behave as follows:
|
|
|
|
.IP \(bu 4
|
|
\fB\fCcontinue\fR will continue applying the next rule in the rule list.
|
|
.IP \(bu 4
|
|
\fB\fCstop\fR will consider the current rule the last rule and will not continue. The default behaviour is \fB\fCstop\fR
|
|
|
|
|
|
.SH "EXAMPLES"
|
|
.SS "NAME FIELD REWRITES"
|
|
.PP
|
|
The \fB\fCrewrite\fR plugin offers the ability to match the name in the question section of
|
|
a DNS request. The match could be exact, a substring match, or based on a prefix, suffix, or regular
|
|
expression. If the newly used name is not a legal domain name, the plugin returns an error to the
|
|
client.
|
|
|
|
.PP
|
|
The syntax for name rewriting is as follows:
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
rewrite [continue|stop] name [exact|prefix|suffix|substring|regex] STRING STRING
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.PP
|
|
The match type, e.g., \fB\fCexact\fR, \fB\fCsubstring\fR, etc., triggers rewrite:
|
|
|
|
.IP \(bu 4
|
|
\fBexact\fP (default): on an exact match of the name in the question section of a request
|
|
.IP \(bu 4
|
|
\fBsubstring\fP: on a partial match of the name in the question section of a request
|
|
.IP \(bu 4
|
|
\fBprefix\fP: when the name begins with the matching string
|
|
.IP \(bu 4
|
|
\fBsuffix\fP: when the name ends with the matching string
|
|
.IP \(bu 4
|
|
\fBregex\fP: when the name in the question section of a request matches a regular expression
|
|
|
|
|
|
.PP
|
|
If the match type is omitted, the \fB\fCexact\fR match type is assumed.
|
|
|
|
.PP
|
|
The following instruction allows rewriting names in the query that
|
|
contain the substring \fB\fCservice.us-west-1.example.org\fR:
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
rewrite name substring service.us\-west\-1.example.org service.us\-west\-1.consul
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.PP
|
|
Thus:
|
|
|
|
.IP \(bu 4
|
|
Incoming Request Name: \fB\fCftp.service.us-west-1.example.org\fR
|
|
.IP \(bu 4
|
|
Rewritten Request Name: \fB\fCftp.service.us-west-1.consul\fR
|
|
|
|
|
|
.PP
|
|
The following instruction uses regular expressions. Names in requests
|
|
matching the regular expression \fB\fC(.*)-(us-west-1)\.example\.org\fR are replaced with
|
|
\fB\fC{1}.service.{2}.consul\fR, where \fB\fC{1}\fR and \fB\fC{2}\fR are regular expression match groups.
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
rewrite name regex (.*)\-(us\-west\-1)\\.example\\.org {1}.service.{2}.consul
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.PP
|
|
Thus:
|
|
|
|
.IP \(bu 4
|
|
Incoming Request Name: \fB\fCftp-us-west-1.example.org\fR
|
|
.IP \(bu 4
|
|
Rewritten Request Name: \fB\fCftp.service.us-west-1.consul\fR
|
|
|
|
|
|
.PP
|
|
The following example rewrites the \fB\fCschmoogle.com\fR suffix to \fB\fCgoogle.com\fR.
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
rewrite name suffix .schmoogle.com. .google.com.
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.SS "RESPONSE REWRITES"
|
|
.PP
|
|
When rewriting incoming DNS requests' names, CoreDNS re-writes the \fB\fCQUESTION SECTION\fR
|
|
section of the requests. It may be necessary to rewrite the \fB\fCANSWER SECTION\fR of the
|
|
requests, because some DNS resolvers treat mismatches between the \fB\fCQUESTION SECTION\fR
|
|
and \fB\fCANSWER SECTION\fR as a man-in-the-middle attack (MITM).
|
|
|
|
.PP
|
|
For example, a user tries to resolve \fB\fCftp-us-west-1.coredns.rocks\fR. The
|
|
CoreDNS configuration file has the following rule:
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
rewrite name regex (.*)\-(us\-west\-1)\\.coredns\\.rocks {1}.service.{2}.consul
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.PP
|
|
CoreDNS rewrote the request from \fB\fCftp-us-west-1.coredns.rocks\fR to
|
|
\fB\fCftp.service.us-west-1.consul\fR and ultimately resolved it to 3 records.
|
|
The resolved records, in the \fB\fCANSWER SECTION\fR below, were not from \fB\fCcoredns.rocks\fR, but
|
|
rather from \fB\fCservice.us-west-1.consul\fR.
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
$ dig @10.1.1.1 ftp\-us\-west\-1.coredns.rocks
|
|
|
|
;; QUESTION SECTION:
|
|
;ftp\-us\-west\-1.coredns.rocks. IN A
|
|
|
|
;; ANSWER SECTION:
|
|
ftp.service.us\-west\-1.consul. 0 IN A 10.10.10.10
|
|
ftp.service.us\-west\-1.consul. 0 IN A 10.20.20.20
|
|
ftp.service.us\-west\-1.consul. 0 IN A 10.30.30.30
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.PP
|
|
The above is a mismatch between the question asked and the answer provided.
|
|
|
|
.PP
|
|
The following configuration snippet allows for rewriting of the
|
|
\fB\fCANSWER SECTION\fR, provided that the \fB\fCQUESTION SECTION\fR was rewritten:
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
rewrite stop {
|
|
name regex (.*)\-(us\-west\-1)\\.coredns\\.rocks {1}.service.{2}.consul
|
|
answer name (.*)\\.service\\.(us\-west\-1)\\.consul {1}\-{2}.coredns.rocks
|
|
}
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.PP
|
|
Now, the \fB\fCANSWER SECTION\fR matches the \fB\fCQUESTION SECTION\fR:
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
$ dig @10.1.1.1 ftp\-us\-west\-1.coredns.rocks
|
|
|
|
;; QUESTION SECTION:
|
|
;ftp\-us\-west\-1.coredns.rocks. IN A
|
|
|
|
;; ANSWER SECTION:
|
|
ftp\-us\-west\-1.coredns.rocks. 0 IN A 10.10.10.10
|
|
ftp\-us\-west\-1.coredns.rocks. 0 IN A 10.20.20.20
|
|
ftp\-us\-west\-1.coredns.rocks. 0 IN A 10.30.30.30
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.PP
|
|
It is also possible to rewrite other values returned in the DNS response records
|
|
(e.g. the server names returned in \fB\fCSRV\fR and \fB\fCMX\fR records). This can be enabled by adding
|
|
the \fB\fCanswer value\fR to a name regex rule as specified below. \fB\fCanswer value\fR takes a
|
|
regular expression and a rewrite name as parameters and works in the same way as the
|
|
\fB\fCanswer name\fR rule.
|
|
|
|
.PP
|
|
Note that names in the \fB\fCAUTHORITY SECTION\fR and \fB\fCADDITIONAL SECTION\fR will also be
|
|
rewritten following the specified rules. The names returned by the following
|
|
record types: \fB\fCCNAME\fR, \fB\fCDNAME\fR, \fB\fCSOA\fR, \fB\fCSRV\fR, \fB\fCMX\fR, \fB\fCNAPTR\fR, \fB\fCNS\fR will be rewritten
|
|
if the \fB\fCanswer value\fR rule is specified.
|
|
|
|
.PP
|
|
The syntax for the rewrite of DNS request and response is as follows:
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
rewrite [continue|stop] {
|
|
name regex STRING STRING
|
|
answer name STRING STRING
|
|
[answer value STRING STRING]
|
|
}
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.PP
|
|
Note that the above syntax is strict. For response rewrites, only \fB\fCname\fR
|
|
rules are allowed to match the question section, and only by match type
|
|
\fB\fCregex\fR. The answer rewrite must be after the name, as in the
|
|
syntax example.
|
|
|
|
.PP
|
|
An alternate syntax for rewriting a DNS request and response is as
|
|
follows:
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
rewrite [continue|stop] name regex STRING STRING answer name STRING STRING [answer value STRING STRING]
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.PP
|
|
When using \fB\fCexact\fR name rewrite rules, the answer gets rewritten automatically,
|
|
and there is no need to define \fB\fCanswer name\fR. The rule below
|
|
rewrites the name in a request from \fB\fCRED\fR to \fB\fCBLUE\fR, and subsequently
|
|
rewrites the name in a corresponding response from \fB\fCBLUE\fR to \fB\fCRED\fR. The
|
|
client in the request would see only \fB\fCRED\fR and no \fB\fCBLUE\fR.
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
rewrite [continue|stop] name exact RED BLUE
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.SS "TTL FIELD REWRITES"
|
|
.PP
|
|
At times, the need to rewrite a TTL value could arise. For example, a DNS server
|
|
may not cache records with a TTL of zero (\fB\fC0\fR). An administrator
|
|
may want to increase the TTL to ensure it is cached, e.g., by increasing it to 15 seconds.
|
|
|
|
.PP
|
|
In the below example, the TTL in the answers for \fB\fCcoredns.rocks\fR domain are
|
|
being set to \fB\fC15\fR:
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
rewrite continue {
|
|
ttl regex (.*)\\.coredns\\.rocks 15
|
|
}
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.PP
|
|
By the same token, an administrator may use this feature to prevent or limit caching by
|
|
setting the TTL value really low.
|
|
|
|
.PP
|
|
The syntax for the TTL rewrite rule is as follows. The meaning of
|
|
\fB\fCexact|prefix|suffix|substring|regex\fR is the same as with the name rewrite rules.
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
rewrite [continue|stop] ttl [exact|prefix|suffix|substring|regex] STRING SECONDS
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.SH "EDNS0 OPTIONS"
|
|
.PP
|
|
Using the FIELD edns0, you can set, append, or replace specific EDNS0 options in the request.
|
|
|
|
.IP \(bu 4
|
|
\fB\fCreplace\fR will modify any "matching" option with the specified option. The criteria for "matching" varies based on EDNS0 type.
|
|
.IP \(bu 4
|
|
\fB\fCappend\fR will add the option only if no matching option exists
|
|
.IP \(bu 4
|
|
\fB\fCset\fR will modify a matching option or add one if none is found
|
|
|
|
|
|
.PP
|
|
Currently supported are \fB\fCEDNS0_LOCAL\fR, \fB\fCEDNS0_NSID\fR and \fB\fCEDNS0_SUBNET\fR.
|
|
|
|
.SS "EDNS0_LOCAL"
|
|
.PP
|
|
This has two fields, code and data. A match is defined as having the same code. Data may be a string or a variable.
|
|
|
|
.IP \(bu 4
|
|
A string data is treated as hex if it starts with \fB\fC0x\fR. Example:
|
|
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
\&. {
|
|
rewrite edns0 local set 0xffee 0x61626364
|
|
whoami
|
|
}
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.PP
|
|
rewrites the first local option with code 0xffee, setting the data to "abcd". This is equivalent to:
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
\&. {
|
|
rewrite edns0 local set 0xffee abcd
|
|
}
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.IP \(bu 4
|
|
A variable data is specified with a pair of curly brackets \fB\fC{}\fR. Following are the supported variables:
|
|
{qname}, {qtype}, {client\fIip}, {client\fPport}, {protocol}, {server\fIip}, {server\fPport}.
|
|
.IP \(bu 4
|
|
If the metadata plugin is enabled, then labels are supported as variables if they are presented within curly brackets.
|
|
The variable data will be replaced with the value associated with that label. If that label is not provided,
|
|
the variable will be silently substituted with an empty string.
|
|
|
|
|
|
.PP
|
|
Examples:
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
rewrite edns0 local set 0xffee {client\_ip}
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.PP
|
|
The following example uses metadata and an imaginary "some-plugin" that would provide "some-label" as metadata information.
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
metadata
|
|
some\-plugin
|
|
rewrite edns0 local set 0xffee {some\-plugin/some\-label}
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.SS "EDNS0_NSID"
|
|
.PP
|
|
This has no fields; it will add an NSID option with an empty string for the NSID. If the option already exists
|
|
and the action is \fB\fCreplace\fR or \fB\fCset\fR, then the NSID in the option will be set to the empty string.
|
|
|
|
.SS "EDNS0_SUBNET"
|
|
.PP
|
|
This has two fields, IPv4 bitmask length and IPv6 bitmask length. The bitmask
|
|
length is used to extract the client subnet from the source IP address in the query.
|
|
|
|
.PP
|
|
Example:
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
rewrite edns0 subnet set 24 56
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.IP \(bu 4
|
|
If the query's source IP address is an IPv4 address, the first 24 bits in the IP will be the network subnet.
|
|
.IP \(bu 4
|
|
If the query's source IP address is an IPv6 address, the first 56 bits in the IP will be the network subnet.
|
|
|
|
|
|
.SH "FULL SYNTAX"
|
|
.PP
|
|
The full plugin usage syntax is harder to digest...
|
|
|
|
.PP
|
|
.RS
|
|
|
|
.nf
|
|
rewrite [continue|stop] {type|class|edns0|name [exact|prefix|suffix|substring|regex [FROM TO answer name]]} FROM TO
|
|
|
|
.fi
|
|
.RE
|
|
|
|
.PP
|
|
The syntax above doesn't cover the multi-line block option for specifying a name request+response rewrite rule described in the \fBResponse Rewrite\fP section.
|
|
|