2016-03-20 09:40:35 +00:00
# rewrite
2018-01-04 12:53:07 +00:00
## Name
*rewrite* - performs internal message rewriting.
## Description
2017-07-24 08:24:53 -07:00
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.
2016-03-20 09:40:35 +00:00
## Syntax
2018-05-11 13:50:59 -04:00
A simplified/easy to digest syntax for *rewrite* is...
2016-03-20 09:40:35 +00:00
~~~
2017-09-20 13:06:53 -07:00
rewrite [continue|stop] FIELD FROM TO
2016-03-20 09:40:35 +00:00
~~~
2018-05-11 13:50:59 -04:00
* **FIELD** indicates what part of the request/response is being re-written.
2018-05-24 07:51:59 +01:00
* `type` - the type field of the request will be rewritten. FROM/TO must be a DNS record type (`A` , `MX` , etc);
2017-02-07 16:53:16 -05:00
e.g., to rewrite ANY queries to HINFO, use `rewrite type ANY HINFO` .
2018-05-11 13:50:59 -04:00
* `class` - the class of the message will be rewritten. FROM/TO must be a DNS class type (`IN` , `CH` , or `HS` ) e.g., to rewrite CH queries to IN use `rewrite class CH IN` .
* `name` - the query name in the _request_ is rewritten; by default this is a full match of the name, e.g., `rewrite name miek.nl example.org` . Other match types are supported, see the **Name Field Rewrites** section below.
* `answer name` - the query name in the _response_ is rewritten. This option has special restrictions and requirements, in particular it must always combined with a `name` rewrite. See below in the **Response Rewrites** section.
* `edns0` - an EDNS0 option can be appended to the request as described below in the **EDNS0 Options** section.
2018-05-24 07:51:59 +01:00
2018-05-11 13:50:59 -04:00
* **FROM** is the name or type to match
* **TO** is the destination name or type to rewrite to
2017-03-06 16:32:17 -05:00
2017-09-20 13:06:53 -07:00
If you specify multiple rules and an incoming query matches on multiple rules, the rewrite
will behave as following
2018-01-04 12:53:07 +00:00
* `continue` will continue apply the next rule in the rule list.
2017-09-20 13:06:53 -07:00
* `stop` will consider the current rule is the last rule and will not continue. Default behaviour
for not specifying this rule processing mode is `stop`
2016-03-20 10:44:03 +00:00
2018-01-22 22:01:13 -05:00
### Name Field Rewrites
The `rewrite` plugin offers the ability to match on the name in the question section of
a DNS request. The match could be exact, substring, or based on a prefix, suffix, or regular
expression.
The syntax for the name re-writing is as follows:
```
rewrite [continue|stop] name [exact|prefix|suffix|substring|regex] STRING STRING
```
The match type, i.e. `exact` , `substring` , etc., triggers re-write:
* **exact** (default): on exact match of the name in the question section of a request
* **substring**: on a partial match of the name in the question section of a request
* **prefix**: when the name begins with the matching string
* **suffix**: when the name ends with the matching string
* **regex**: when the name in the question section of a request matches a regular expression
If the match type is omitted, the `exact` match type is being assumed.
The following instruction allows re-writing the name in the query that
contains `service.us-west-1.example.org` substring.
```
rewrite name substring service.us-west-1.example.org service.us-west-1.consul
```
Thus:
* Incoming Request Name: `ftp.service.us-west-1.example.org`
* Re-written Request Name: `ftp.service.us-west-1.consul`
The following instruction uses regular expressions. The name in a request
matching `(.*)-(us-west-1)\.example\.org` regular expression is being replaces with
`{1}.service.{2}.consul` , where `{1}` and `{2}` are regular expression match groups.
```
rewrite name regex (.*)-(us-west-1)\.example\.org {1}.service.{2}.consul
```
Thus:
* Incoming Request Name: `ftp-us-west-1.example.org`
* Re-written Request Name: `ftp.service.us-west-1.consul`
### Response Rewrites
When re-writing incoming DNS requests' names, CoreDNS re-writes the `QUESTION SECTION`
section of the requests. It may be necessary to re-write the `ANSWER SECTION` of the
requests, because some DNS resolvers would treat the mismatch between `QUESTION SECTION`
and `ANSWER SECTION` as a man-in-the-middle attack (MITM).
For example, a user tries to resolve `ftp-us-west-1.coredns.rocks` . The
CoreDNS configuration file has the following rule:
```
rewrite name regex (.*)-(us-west-1)\.coredns\.rocks {1}.service.{2}.consul
```
CoreDNS instance re-wrote the request to `ftp-us-west-1.coredns.rocks` with
`ftp.service.us-west-1.consul` and ultimately resolved it to 3 records.
The resolved records, see `ANSWER SECTION` , were not from `coredns.rocks` , but
rather from `service.us-west-1.consul` .
```
$ dig @10 .1.1.1 ftp-us-west-1.coredns.rocks
; << >> DiG 9.8.3-P1 << >> @10 .1.1.1 ftp-us-west-1.coredns.rocks
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER< < - opcode: QUERY , status: NOERROR , id: 8619
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0
;; 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
```
The above is the mismatch.
The following configuration snippet allows for the re-writing of the
`ANSWER SECTION` , provided that the `QUESTION SECTION` was re-written:
```
rewrite stop {
name regex (.*)-(us-west-1)\.coredns\.rocks {1}.service.{2}.consul
answer name (.*)\.service\.(us-west-1)\.consul {1}-{2}.coredns.rocks
}
```
Now, the `ANSWER SECTION` matches the `QUESTION SECTION` :
```
$ dig @10 .1.1.1 ftp-us-west-1.coredns.rocks
; << >> DiG 9.8.3-P1 << >> @10 .1.1.1 ftp-us-west-1.coredns.rocks
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER< < - opcode: QUERY , status: NOERROR , id: 8619
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0
;; 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
```
2018-04-25 15:48:32 -04:00
The syntax for the rewrite of DNS request and response is as follows:
2018-01-22 22:01:13 -05:00
```
rewrite [continue|stop] {
name regex STRING STRING
answer name STRING STRING
}
```
2018-04-25 15:48:32 -04:00
Note that the above syntax is strict. For response rewrites only `name`
rules are allowed to match the question section, and only by match type
`regex` . The answer rewrite must be after the name, as ordered in the
syntax example. There must only be two lines (a `name` follwed by an
`answer` ) in the brackets, additional rules are not supported.
An alternate syntax for the rewrite of DNS request and response is as
follows:
```
rewrite [continue|stop] name regex STRING STRING answer name STRING STRING
```
2017-03-06 16:32:17 -05:00
## EDNS0 Options
2017-02-07 16:53:16 -05:00
2017-03-06 16:32:17 -05:00
Using FIELD edns0, you can set, append, or replace specific EDNS0 options on the request.
2016-03-20 09:40:35 +00:00
2018-06-18 05:02:05 -04:00
* `replace` will modify any "matching" option with the specified option. The criteria for "matching" varies based on EDNS0 type.
* `append` will add the option only if no matching option exists
2017-03-06 16:32:17 -05:00
* `set` will modify a matching option or add one if none is found
2016-03-20 09:40:35 +00:00
2017-09-08 13:36:09 -07:00
Currently supported are `EDNS0_LOCAL` , `EDNS0_NSID` and `EDNS0_SUBNET` .
2016-03-20 09:40:35 +00:00
2018-01-04 12:53:07 +00:00
### EDNS0_LOCAL
2016-03-20 09:40:35 +00:00
2018-01-04 12:53:07 +00:00
This has two fields, code and data. A match is defined as having the same code. Data may be a string or a variable.
2017-08-24 09:34:07 -07:00
* A string data can be treated as hex if it starts with `0x` . Example:
2016-03-20 09:40:35 +00:00
2017-10-10 09:39:35 +02:00
~~~ corefile
. {
rewrite edns0 local set 0xffee 0x61626364
whoami
}
2016-03-20 09:40:35 +00:00
~~~
2017-03-06 16:32:17 -05:00
rewrites the first local option with code 0xffee, setting the data to "abcd". Equivalent:
2016-03-20 09:40:35 +00:00
2017-10-10 09:39:35 +02:00
~~~ corefile
. {
rewrite edns0 local set 0xffee abcd
}
2016-03-20 09:40:35 +00:00
~~~
2018-07-01 20:01:17 +01:00
* A variable data is specified with a pair of curly brackets `{}` . Following are the supported variables:
2018-01-04 12:53:07 +00:00
{qname}, {qtype}, {client_ip}, {client_port}, {protocol}, {server_ip}, {server_port}.
2017-08-24 09:34:07 -07:00
Example:
2018-07-01 20:01:17 +01:00
~~~
rewrite edns0 local set 0xffee {client_ip}
2017-08-24 09:34:07 -07:00
~~~
2018-01-04 12:53:07 +00:00
### EDNS0_NSID
2016-03-20 09:40:35 +00:00
2017-03-06 16:32:17 -05:00
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 `replace` or `set` , then the NSID in the option will be set to the empty string.
2017-09-08 13:36:09 -07:00
2018-01-04 12:53:07 +00:00
### EDNS0_SUBNET
2017-09-08 13:36:09 -07:00
This has two fields, IPv4 bitmask length and IPv6 bitmask length. The bitmask
2018-01-04 12:53:07 +00:00
length is used to extract the client subnet from the source IP address in the query.
2017-09-08 13:36:09 -07:00
Example:
~~~
2017-10-10 09:39:35 +02:00
rewrite edns0 subnet set 24 56
2017-09-08 13:36:09 -07:00
~~~
* If the query has source IP as IPv4, the first 24 bits in the IP will be the network subnet.
* If the query has source IP as IPv6, the first 56 bits in the IP will be the network subnet.
2018-05-11 13:50:59 -04:00
## Full Syntax
The full plugin usage syntax is harder to digest...
~~~
rewrite [continue|stop] {type|class|edns0|name [exact|prefix|suffix|substring|regex [FROM TO answer name]]} FROM TO
~~~
The syntax above doesn't cover the multi line block option for specifying a name request+response rewrite rule described in the **Response Rewrite** section.