Skip site navigation (1)Skip section navigation (2)

  
 
  

home | help
COREDNS-REWRITE(7)		 CoreDNS Plugins	      COREDNS-REWRITE(7)

NAME
     rewrite - performs internal message rewriting.

DESCRIPTION
     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.

SYNTAX
     A simplified/easy-to-digest syntax for rewrite is...

	    rewrite [continue|stop] FIELD [TYPE] [(FROM TO)|TTL] [OPTIONS]

     *	 FIELD indicates what part of the request/response is being re-written.

	 -   type  -  the  type  field of the request will be rewritten. FROM/TO
	     must be a DNS record type (A,  MX,  etc.);  e.g.,	to  rewrite  ANY
	     queries to HINFO, use rewrite type ANY HINFO.

	 -   name  - the query name in the request is rewritten; by default this
	     is a full match of the name, e.g., rewrite name  example.net  exam-
	     ple.org.  Other  match  types  are  supported,  see  the Name Field
	     Rewrites section below.

	 -   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.

	 -   edns0 - an EDNS0 option can be appended to the request as described
	     below in the EDNS0 Options section.

	 -   ttl - the TTL value in the response is rewritten.

	 -   cname - the CNAME target if the response has a CNAME record

	 -   rcode - the response code (RCODE) value in the response is  rewrit-
	     ten.

     *	 TYPE  this  optional  element can be specified for a name or ttl field.
	 If not given type exact will be assumed. If options should be specified
	 the type must be given.

     *	 FROM is the name (exact, suffix, prefix, substring, or regex)	or  type
	 to match

     *	 TO is the destination name or type to rewrite to

     *	 TTL  is  the  number of seconds to set the TTL value to (only for field
	 ttl)

     *	 OPTIONS

     for field name  further  options  are  possible  controlling  the	response
     rewrites.
       All name matching types support the following options

	     * `answer auto` - the names in the _response_ is rewritten in a best effort manner.
	     * `answer name FROM TO` - the query name in the _response_ is rewritten matching the from regex pattern.
	     * `answer value FROM TO` - the names in the _response_ is rewritten matching the from regex pattern.

     See below in the Response Rewrites section for further details.

     If you specify multiple rules and an incoming query matches multiple rules,
     the rewrite will behave as follows:

     *	 continue will continue applying the next rule in the rule list.

     *	 stop  will  consider  the  current rule the last rule and will not con-
	 tinue.  The default behaviour is stop

     *	 When multiple rules are matched, the request rewrite follows  the  line
	 order	in  the configuration, while the response rewrite(answer option)
	 is executed in reverse order.

EXAMPLES
   NAME FIELD REWRITES
     The rewrite 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.

     The syntax for name rewriting is as follows:

	    rewrite [continue|stop] name [exact|prefix|suffix|substring|regex] STRING STRING [OPTIONS]

     The match type, e.g., exact, substring, etc., triggers rewrite:

     *	 exact (default): on an 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.  Regex patterns must not exceed 10000 characters.

     If  the  match type is omitted, the exact match type is assumed. If OPTIONS
     are given, the type must be specified.

     The following instruction allows rewriting names in the query that  contain
     the substring service.us-west-1.example.org:

	    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

     *	 Rewritten Request Name: ftp.service.us-west-1.consul

     The  following  instruction  uses	regular  expressions.  Names in requests
     matching the regular expression (.*)-(us-west-1).example.org  are	replaced
     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

     *	 Rewritten Request Name: ftp.service.us-west-1.consul

     The following example rewrites the schmoogle.com suffix to google.com.

	    rewrite name suffix .schmoogle.com. .google.com.

   RESPONSE REWRITES
     When rewriting incoming DNS requests' names (field name), CoreDNS re-writes
     the  QUESTION  SECTION  section  of  the  requests.  It may be necessary to
     rewrite the ANSWER SECTION of the	requests,  because  some  DNS  resolvers
     treat  mismatches between the 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  rewrote  the  request from ftp-us-west-1.coredns.rocks to ftp.ser-
     vice.us-west-1.consul and ultimately resolved it to  3  records.	The  re-
     solved  records,  in the ANSWER SECTION below, were not from coredns.rocks,
     but rather from service.us-west-1.consul.

	    $ 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

     The above is a mismatch between the question asked and the answer provided.

     There are three possibilities to specify an answer rewrite: - A rewrite can
     request a best effort answer rewrite by adding the option answer auto.  - A
     rewrite may specify a dedicated regex based response name rewrite with the
       answer name FROM TO option.  - A regex based  rewrite  of  record  values
     like CNAME, SRV, etc, can be requested by
       an answer value FROM TO option.

     Hereby FROM/TO follow the rules for the regex name rewrite syntax.

   AUTO RESPONSE NAME REWRITE
     The following configuration snippet allows for rewriting of the ANSWER SEC-
     TION according to the rewrite of the QUESTION SECTION:

		rewrite stop {
		    name suffix .coredns.rocks .service.consul answer auto
		}

     Any  occurrence  of  the rewritten question in the answer is mapped back to
     the original value before the rewrite.

     Please note that answers for rewrites of type exact are  always  rewritten.
     For a suffix name rule auto leads to a reverse suffix response rewrite, ex-
     changing FROM and TO from the rewrite request.

   EXPLICIT RESPONSE NAME REWRITE
     The following configuration snippet allows for rewriting of the ANSWER SEC-
     TION, provided that the QUESTION SECTION was rewritten:

		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

	    ;; 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

   REWRITING OTHER RESPONSE VALUES
     It  is  also  possible to rewrite other values returned in the DNS response
     records (e.g. the server names returned in SRV and MX records). This can be
     enabled by adding the answer value FROM TO option to a name rule as  speci-
     fied  below.  answer value takes a regular expression and a rewrite name as
     parameters and works in the same way as the answer name rule.

     Note that names in the AUTHORITY SECTION and ADDITIONAL SECTION  will  also
     be  rewritten following the specified rules. The names returned by the fol-
     lowing record types: CNAME, DNAME, SOA, SRV, MX, NAPTR,  NS,  PTR	will  be
     rewritten if the answer value rule is specified.

     The syntax for the rewrite of DNS request and response is as follows:

	    rewrite [continue|stop] {
		name regex STRING STRING
		answer name STRING STRING
		[answer value STRING STRING]
	    }

     Note  that  the  above  syntax is strict.	For response rewrites, only name
     rules are allowed to match the question section. The answer rewrite must be
     after the name, as in the syntax example.

   EXAMPLE: PTR RESPONSE VALUE REWRITE
     The original response contains the domain service.consul. in the VALUE part
     of the ANSWER SECTION

	    $ dig @10.1.1.1 30.30.30.10.in-addr.arpa PTR

	    ;; QUESTION SECTION:
	    ;30.30.30.10.in-addr.arpa. IN PTR

	    ;; ANSWER SECTION:
	    30.30.30.10.in-addr.arpa. 60    IN PTR    ftp-us-west-1.service.consul.

     The following configuration snippet allows for rewriting of  the  value  in
     the ANSWER SECTION:

		rewrite stop {
		    name suffix .arpa .arpa
		    answer name auto
		    answer value (.*)\.service\.consul\. {1}.coredns.rocks.
		}

     Now,  the	VALUE  in  the ANSWER SECTION has been overwritten in the domain
     part:

	    $ dig @10.1.1.1 30.30.30.10.in-addr.arpa PTR

	    ;; QUESTION SECTION:
	    ;30.30.30.10.in-addr.arpa. IN PTR

	    ;; ANSWER SECTION:
	    30.30.30.10.in-addr.arpa. 60    IN PTR    ftp-us-west-1.coredns.rocks.

   MULTIPLE RESPONSE REWRITES
     name and value rewrites can be chained by appending multiple answer rewrite
     options. For all occurrences but the first one the keyword answer might  be
     omitted.

	    answer (auto | (name|value FROM TO)) { [answer] (auto | (name|value FROM TO)) }

     For example:

	    rewrite [continue|stop] name regex FROM TO answer name FROM TO [answer] value FROM TO

     When  using  exact  name rewrite rules, the answer gets rewritten automati-
     cally, and there is no need to define answer name auto.  But  it  is  still
     possible to define additional answer value and answer value options.

     The  rule below rewrites the name in a request from RED to BLUE, and subse-
     quently rewrites the name in a corresponding response from BLUE to RED. The
     client in the request would see only RED and no BLUE.

	    rewrite [continue|stop] name exact RED BLUE

   TTL FIELD REWRITES
     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 (0). An administrator may
     want to increase the TTL to ensure it is cached, e.g., by increasing it  to
     15 seconds.

     In  the  below example, the TTL in the answers for coredns.rocks domain are
     being set to 15:

		rewrite continue {
		    ttl regex (.*)\.coredns\.rocks 15
		}

     By the same token, an administrator may use  this	feature  to  prevent  or
     limit caching by setting the TTL value really low.

     The  syntax  for  the  TTL  rewrite  rule is as follows. The meaning of ex-
     act|prefix|suffix|substring|regex is the same  as	with  the  name  rewrite
     rules.  An omitted type is defaulted to exact.

	    rewrite [continue|stop] ttl [exact|prefix|suffix|substring|regex] STRING [SECONDS|MIN-MAX]

     It  is  possible  to supply a range of TTL values in the SECONDS parameters
     instead of a single value.  If a range is supplied, the TTL value is set to
     MIN if it is below, or set to MAX if it is above.	The TTL  value	is  left
     unchanged	if  it	is already inside the provided range.  The ranges can be
     unbounded on either side.

     TTL examples with ranges:

	    rewrite ttl example.com. 30-300

	    rewrite ttl example.com. -30 # equivalent to rewrite ttl example.com. 0-30

	    rewrite ttl example.com. 30-

	    rewrite ttl example.com. 30 # equivalent to rewrite ttl example.com. 30-30

   RCODE FIELD REWRITES
     At times, the need to rewrite a RCODE value could arise. For example, a DNS
     server may respond with a SERVFAIL instead of  NOERROR  records  when  AAAA
     records are requested.

     In  the  below  example,  the  rcode value the answer for coredns.rocks the
     replies with SERVFAIL is being switched to NOERROR.

     This example rewrites all the *.coredns.rocks domain SERVFAIL errors to NO-
     ERROR

		rewrite continue {
		    rcode regex (.*)\.coredns\.rocks SERVFAIL NOERROR
		}

     The same result numeric values:

		rewrite continue {
		    rcode regex (.*)\.coredns\.rocks 2 0
		}

     The syntax for the RCODE rewrite rule is as follows.  The	meaning  of  ex-
     act|prefix|suffix|substring|regex	is  the  same  as  with the name rewrite
     rules.  An omitted type is defaulted to exact.

	    rewrite [continue|stop] rcode [exact|prefix|suffix|substring|regex] STRING FROM TO

     The values of FROM and TO can be any of the following, text  value  or  nu-
     meric:

	      0 NOERROR
	      1 FORMERR
	      2 SERVFAIL
	      3 NXDOMAIN
	      4 NOTIMP
	      5 REFUSED
	      6 YXDOMAIN
	      7 YXRRSET
	      8 NXRRSET
	      9 NOTAUTH
	      10 NOTZONE
	      16 BADSIG
	      17 BADKEY
	      18 BADTIME
	      19 BADMODE
	      20 BADNAME
	      21 BADALG
	      22 BADTRUNC
	      23 BADCOOKIE

EDNS0 OPTIONS
     Using  the  FIELD	edns0,	you  can set, append, replace, or unset specific
     EDNS0 options in the request.

     *	 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

     *	 set will modify a matching option or add one if none is found

     *	 unset will remove the matching option if one exists

     Currently supported are EDNS0_LOCAL, EDNS0_NSID and EDNS0_SUBNET.

   EDNS0_LOCAL
     This  has	two fields, code and data. A match is defined as having the same
     code. Data may be a string or a variable.

     *	 A string data is treated as hex if it starts with 0x. Example:

	    . {
		rewrite edns0 local set 0xffee 0x61626364
		whoami
	    }

     rewrites the first local option with  code  0xffee,  setting  the	data  to
     "abcd". This is equivalent to:

	    . {
		rewrite edns0 local set 0xffee abcd
	    }

     *	 A  variable data is specified with a pair of curly brackets {}. Follow-
	 ing are the supported variables: {qname}, {qtype}, {clientip}, {client-
	 port}, {protocol}, {serverip}, {serverport}.

     *	 If the metadata plugin is enabled, then labels are supported  as  vari-
	 ables	if  they are presented within curly brackets.  The variable data
	 will be replaced with the value associated with that label. If that la-
	 bel is not provided, the variable will be silently substituted with  an
	 empty string.

     Examples:

	    rewrite edns0 local set 0xffee {client_ip}

     The  following  example  uses  metadata and an imaginary "some-plugin" that
     would provide "some-label" as metadata information.

	    metadata
	    some-plugin
	    rewrite edns0 local set 0xffee {some-plugin/some-label}

     A local option may be removed by unsetting its code. Example:

	    rewrite edns0 local unset 0xffee

   EDNS0_NSID
     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.  The option can be
     removed with the unset action.

   EDNS0_SUBNET
     This has two fields,  IPv4 bitmask length and IPv6 bitmask length. The bit-
     mask length is used to extract the client subnet from the source IP address
     in the query.

     Example:

	    rewrite edns0 subnet set 24 56

     *	 If the query's source IP address is an IPv4 address, the first 24  bits
	 in the IP will be the network subnet.

     *	 If  the query's source IP address is an IPv6 address, the first 56 bits
	 in the IP will be the network subnet.

     This option can be removed by using unset:

	    rewrite edns0 subnet unset

   EDNS0 REVERT
     Using the revert flag, you can revert the	changes  made  by  this  rewrite
     call, so the response will not contain this option.

     This example sets option, but response will not contain it

	    . {
		rewrite edns0 local set 0xffee abcd revert
	    }

     If  only some calls contain the revert flag, then the value in the response
     will be changed to the previous one. So, in this example, the response will
     contain abcd data at 0xffee

	    . {
		rewrite continue {
		    edns0 local set 0xffee abcd
		}

		rewrite edns0 local replace 0xffee bcde revert
	    }

CNAME FIELD REWRITES
     There might be a scenario where you want the CNAME target of  the	response
     to  be  rewritten. You can do this by using the CNAME field rewrite. Answer
     records preceding the CNAME target are kept unchanged, the CNAME target  is
     rewritten,  and  the subsequent records are replaced with the lookup result
     of the rewritten CNAME target.

     The syntax for the CNAME rewrite rule is as follows.  The	meaning  of  ex-
     act|prefix|suffix|substring|regex	is  the  same  as  with the name rewrite
     rules.  An omitted type is defaulted to exact.

	    rewrite [continue|stop] cname [exact|prefix|suffix|substring|regex] FROM TO

     Consider the following CNAME rewrite rule with regex type.

	    rewrite cname regex (.*).cdn.example.net. {1}.other.cdn.com.

     If you were to send the following DNS request without the	above  rule,  an
     example response would be:

	    $ dig @10.1.1.1 my-app.com

	    ;; QUESTION SECTION:
	    ;my-app.com. IN A

	    ;; ANSWER SECTION:
	    my-app.com. 		 200  IN  CNAME  my-app.example.
	    my-app.example.		 200  IN  CNAME  my-app.com.cdn.example.net.
	    my-app.com.cdn.example.net.  300  IN  A	 20.2.0.1
	    my-app.com.cdn.example.net.  300  IN  A	 20.2.0.2

     If you were to send the same DNS request with the above rule set up, an ex-
     ample response would be:

	    $ dig @10.1.1.1 my-app.com

	    ;; QUESTION SECTION:
	    ;my-app.com. IN A

	    ;; ANSWER SECTION:
	    my-app.com. 		 200  IN  CNAME  my-app.example.
	    my-app.example.		 200  IN  CNAME  my-app.com.other.cdn.com.
	    my-app.com.other.cdn.com.	 100  IN  A	 30.3.1.2

     Note  that  the  answer  will  contain a completely different set of answer
     records after rewriting the CNAME target.

CoreDNS 			   March 2026		      COREDNS-REWRITE(7)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=coredns-rewrite&sektion=7&manpath=FreeBSD+Ports+15.1.quarterly>

home | help