TXT and RAW rrs in MaraDNS' csv2 zone files can store any arbitrary binary data. Additionally, it is possible to arbitrarily divide up TXT records in to chunks (chunks, which RFC1035 call "character-string"s, are described below).
a.example.com. TXT 'This is some text' ~It is also possible, to place almost any printable ASCII characters between quotes. The '~' (tilde) character is not allowed unless csv2_tilde_handling has a value of 0; the '|' (pipe), '#' (hash) and non-printable ASCII control characters are not allowed in TXT data if the ~ is used to separate records. If there are any bytes with a value of 0x80 or more, the data must be UTF-8 encoded Unicode. For example:
b.example.com. TXT 'This is an example UTF-8 character: I ♥ MaraDNS'(If your font does not have this Unicode symbol, it is a heart)
The printable ASCII characters not allowed in quotes are the ' character, the '|' character, the '~' (tilde) character, and the '#' character. See BACKSLASH ESCAPE SEQUENCES below for information on adding these characters to TXT or RAW fields.
c.example.com. TXT This_is_100%_unquoted_text_+symbols!It is also possible to mix quoted and unquoted text, such as this:
d.example.com. TXT This' is a mix 'of_unquoted' and quoted 'text!Which will have its data look like this:
This is a mix of_unquoted and quoted text!When mixing quoted and unquoted data, it is important to have all whitespace inside quotes.
The following characters can be backslashed:
Here are some examples of backslashed data. In this example, we see backslash sequences being used to store non-UTF-8 hi-bit data:
e.example.com. TXT \x80\x81\x82\x83 ~This same data can also be created as follows:
f.example.com. TXT \200\201\202\203 ~Octal and hex information can be mixed:
g.example.com. TXT \200\x81\202\x83 ~Literal single quotes can be placed in resource records:
h.example.com. TXT 'perl -e '\''print "A Perl of a TXT record!\n"'\' ~The above example produces this record:
perl -e 'print "A Perl of a TXT record!\n"' ~To render the '~' character, use the escape sequence \x7e (outside of quotes). For example:
h1.example.com. TXT 'http://ocf.berkeley.edu/'\x7e'set' ~Produces this record:
http://ocf.berkeley.edu/~setTo render the '|' character, use the escape sequence \x7c:
h2.example.com. TXT 'ls '\x7c' more' ~Produces this record:
ls | moreTo render the '#' character, use the escape sequence \x23:
h3.example.com. TXT 'Press '\x23' for customer service' ~Produces this record:
Press # for customer service
i.example.com. TXT 'Not only did the quick brown fox jump over the lazy dog, but the lazy dog jumped over the cat.' ~Without affecting this resource record, the same data can be split over multiple lines:
j.example.com. TXT 'Not only did the quick brown fox jump '\ 'over the lazy dog, but the lazy dog'\ ' jumped over the cat.' ~Some points:
k.example.com. TXT 'Not only did the quick brown fox jump '\ # The fox 'over the lazy dog, but the lazy dog'\ # The dog ' jumped over the cat.' ~ # The catNote that, since the third comment is not preceded by a backslash, this indicates the end of the resource record.
There can also be multiple lines dedicated to comments (and, optionally, even blank lines) in the middle of TXT and RAW record data:
k2.example.com. TXT 'This is some data '\ # Here we have some comments followed by a blank line # Now we have some more comments, # followed by the rest of the data 'and this is the rest of the data' ~
o.example.com. TXT 'TXT record with only one chunk' ~It is also possible to have a record with multiple chunks. Chunks are delimited by an unquoted ';' character:
p.example.com. TXT 'This is chunk one';'This is chunk two' ~Or:
q.example.com. TXT 'This is chunk one';\ # Our first chunk This_is_chunk_two;\ # Our second chunk 'This is chunk three' ~ # Our final chunkQuoted ; characters simply add a ; to the record data.
If a single TXT chunk is longer than 255 bytes long, the csv2 parser will report an error in the zone file: Single TXT chunk too long
In order to resolve this, place unquoted ; characters in the record data so that each chunk is under 255 octets (bytes or characters) in length.
It is possible to have zero length chunks:
r.example.com. TXT 'chunk one';;'chunk three' ~ # Chunk two zero-lengthIn particular, is is possible to have zero length chunks at the beginning and end of a TXT record:
s.example.com. TXT ;'chunk two'; ~ # Chunks one and three zero-lengthDo not place semicolons at the beginning nor end of TXT records unless you wish to have these zero-length chunks.
Chunk support only exists for TXT records. An unquoted ; character will cause a syntax error in a RAW record.
t1.example.com. RAW 40 \x10\x01\x02'Kitchen sink'\x2b' data' ~
t.example.com. RAW 40 \020\001\002Kitchen' sink+ data' ~
u.example.com. RAW 40 \x10\x01\x02Kitchen\x20sink+\x20data ~
v.example.com. RAW 40 \x10\001\x02\ 'Kitchen sink+ data' ~
w.example.com. RAW 40 \x10\ # Meaning: 16 \x01\ # Coding: 1 \x02\ # Sub-coding: 2 'Kitchen sink+ data' ~ # Data: 'Kitchen sink+ data'
MaraDNS can store a 2048-bit RSA DKIM key. Longer keys are not supported because of the 512-byte limit for traditional DNS packets.
A DKIM record is a long “multi chunk” TXT record; DKIM records are stored in a special _domainkey.example.com record. As per RFC6376 section 22.214.171.124, “Strings in a TXT RR MUST be concatenated together before use with no intervening whitespace”; a single TXT “chunk” can only be up to 255 bytes in length, but we need more than 255 bytes to store a 2048 bit RSA key (6 bits per character, so we need 342 characters to store just the key) and a little more overhead to store the other bits in our DKIM record. But, it doesn’t matter where we split the chunks as long as each individual chunk is under 256 bytes in size.
Here is a real-world DKIM key stored in a MaraDNS zone file:
x._domainkey.% +600 TXT 'v=DKIM1; k=rsa; '\ 'p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCg'\ 'KCAQEAuhKjx2Aepa3rllxUEZLgF3x'\ '68SWvZ8pEgnjZvxtqp94Vkra3AUC4C8dRLKf5SvT'\ 'xFtIl6pF27jn+M/w2MzYwPFjBgqVf'\ 'p2lf7xuKsrus63m0T9Sq958nIt1yuUlLDr71bFs7'\ 'ZuZyQid0ciCc2JF5lwHno10cAvuNJ';'y1Q'\ 'tFJa+lRJI6/kzY20Hi/ZTzFzctqgqaRZnSoJlTZHf'\ 'Oy0uwfmF5ejkJ8xvHbEJp6TEc'\ '30DwsqrjVWSFLnUWYBv7lrAPB9sAHN7fCayhEuORn'\ 'Ap+YUhjjMPWyPla1pvTS9h/LTE7g'\ '2d+jR/zOkRpV2Ak/4KpeP9dpsRJEOsPEaWGG1pQXgPw'\ 'IDAQAB'