@Sven's answer, with the edit, is already right but just to phrase things directly.
TL;DR yes underscore is valid in a CNAME
record on both sides, read below for why.
RFC 1034 and others define records based on "domain names" which are labels with any character, so including _
.
But some records have stricter rules for either the owner name and/or the resource data (RDATA). There only an hostname will be accepted and indeed the rules are now (they were relaxed in the past where an hostname could not started with a digit) that you can use any ASCII letter (no case sensitivity), any ASCII digits, and the hyphens, plus some extra position rules: no hyphen at start or end and no double hyphens at position 3 and 4 (because of "reservation" for IDNs that are of the form xn--
which is only case allowed).
For example the owner name of an A
or AAAA
record is an hostname, not a domain name.
So
test.example.com A 192.0.2.1
is valid why all of these are not:
_test.example.com A 192.0.2.1
-test.example.com A 192.0.2.1
test-.example.com A 192.0.2.1
It is easy to test things with the named-checkzone
program (part of the bind
nameserver software but may be used and installed separately and others nameservers may have similar checking tools and there are probably online interfaces for that too anyway), just put records in a file and run it on:
$ cat z1.txt
test.example.com. 1 IN A 192.0.2.1
_test.example.com. 1 IN A 192.0.2.1
-test.example.com. 1 IN A 192.0.2.1
test-.example.com. 1 IN A 192.0.2.1
$ /usr/local/sbin/named-checkzone example.com z1.txt
z1.txt:2: _test.example.com: bad owner name (check-names)
z1.txt:3: -test.example.com: bad owner name (check-names)
z1.txt:4: test-.example.com: bad owner name (check-names)
(the number before the IN
is the TTL, this is unrelated to our problem here, but needed just to pass syntax validation of a record).
For other records, it is the opposite: for NS
there are no restrictions on the owner, but restrictions on the "target" that is the data. The data can only be an hostname, not a domain name, because you need to point to authoritative nameservers that are physical hosts that respond to DNS queries.
Now about CNAME
, here are the relevant quotes from RFC 1034, in section 3.6:
"owner: which is the domain name where the RR is found." which means by default any name, not just an hostname (as source of the CNAME record)
"RDATA: which is the type and sometimes class dependent data which describes the resource:"
"CNAME a domain name."
So both the owner of a CNAME
(what is on the left of it), and the resource data attached to it, its destination/target (what is on the right of it) are domain names, and not hostnames only. Basically any character, so including _
is allowed on both sides.
Again, easy to test with named-checkzone
:
$ cat z2.txt
_foo 1 CNAME _bar
$ /usr/local/sbin/named-checkzone example.com z2.txt
zone example.com/IN: has 0 SOA records
zone example.com/IN: has no NS records
zone example.com/IN: not loaded due to errors.
No errors whatsoever about the CNAME
(the other errors are expected since in my fake zone I did not put any SOA
or NS
records like a true zone would have)