「ドメイン名って255文字まで使えたっけ?」と悩むことが度々あるため、最大長がどのように決められているのか確認しました。
TL;DR
DNSのドメイン名の最大長は、ドメイン名をどう表記して数えるかによって多少変わります。
- よく見る表記
qiita.com
(9文字)なら最大253文字 - ルートを明記した形
qiita.com.
(10文字)なら最大254文字 - エスケープを使った形
qi\ita.c\111m.
だと見た目には伸びるが、文字でなくオクテットとして数えれば同じ - 各ラベルをドット区切りでなく長さで表した形
[(5, "qiita"), (3, "com"), (0, "")]
(11オクテット)なら最大255オクテット ← これがRFC1035で決められた制限
仕様の確認
DNSのドメイン名について、RFCを確認してみます。
RFCを漁らなくても、下記ページに最大長やその理由(注釈3を参照)が簡潔に纏まっていました。
ドメイン名のしくみ - JPNIC
長さの制限
ドメイン名の仕様は RFC 1035 "Domain names - implementation and specification" に書かれています。
3.1. Name space definitions
Domain names in messages are expressed in terms of a sequence of labels. Each label is represented as a one octet length field followed by that number of octets. Since every domain name ends with the null label of the root, a domain name is terminated by a length byte of zero. The high order two bits of every length octet must be zero, and the remaining six bits of the length field limit the label to 63 octets or less.
To simplify implementations, the total length of a domain name (i.e., label octets and label length octets) is restricted to 255 octets or less.
Although labels can contain any 8 bit values in octets that make up a label, it is strongly recommended that labels follow the preferred syntax described elsewhere in this memo, which is compatible with existing host naming conventions. Name servers and resolvers must compare labels in a case-insensitive manner (i.e., A=a), assuming ASCII with zero parity. Non-alphabetic codes must match exactly.
- メッセージ内のドメイン名はラベルの列で表される
- ドメイン名の末尾はルートのnullラベル
- 各ラベルは長さを表す1オクテットを先頭に置き、その長さぶんのオクテットが続く
- 長さは63オクテット以下
- 任意の8ビット値を使える(が慣習に沿うことを強く推奨)
- ラベルの比較時に、ASCIIにおける英文字の大小は区別しない
- ドメイン名の長さは255オクテット以下に制限する(実装単純化のため)
もっとも、上記は内部的な表現であって人間向けの表現にはなっていません。表現が変われば255でなくなる可能性があります。
人間向けの表現
人間向けの表現への直し方は RFC 1034 "Domain names - concepts and facilities" のほうに書いてありました。
3.1. Name space specifications and terminology
...
When a user needs to type a domain name, the length of each label is omitted and the labels are separated by dots ("."). Since a complete domain name ends with the root label, this leads to a printed form which ends in a dot. We use this property to distinguish between:
- a character string which represents a complete domain name (often called "absolute"). For example, "poneria.ISI.EDU."
- a character string that represents the starting labels of a domain name which is incomplete, and should be completed by local software using knowledge of the local domain (often called "relative"). For example, "poneria" used in the ISI.EDU domain.
Relative names are either taken relative to a well known origin, or to a list of domains used as a search list. Relative names appear mostly at the user interface, where their interpretation varies from implementation to implementation, and in master files, where they are relative to a single origin domain name. The most common interpretation uses the root "." as either the single origin or as one of the members of the search list, so a multi-label relative name is often one where the trailing dot has been omitted to save typing.
...
- ユーザーがドメイン名を入力する際は、各ラベルは長さを省略してドット
.
で分割する - 完全なドメイン名はルートラベルで終わるため、末尾にドットが来る形で表示される
- 不完全なら何かしらのドメインで補完される(そのドメインに相対的になる)
- 一般にはオリジンをルートと解釈して、そこからの相対名として末尾のドットをよく省略する
これにより、ドメイン名の長さは内部的な表現より2つ少なくなります。そのぶん最大長も減り253文字となります。
- ラベルの長さを省略して間にドットを入れるため、1オクテット減る
- ルートを省略すれば、末尾のドットぶんの1オクテット減る
任意の8ビット値の表現
あまり重要ではありませんが、ドメイン名(のラベル)には任意の8ビット値を使えるということで、その表記方法も軽く調べました。
RFC 1035 の 5.1 には、任意のデータを表記するために \X
や \DDD
を使えると書いてあります。ただ、これはマスターファイルの節に書かれているため、それ以外のところでも通用するのかが不明です。
RFC 4343 "Domain Name System (DNS) Case Insensitivity Clarification" の 2.1 では、表記できない文字のエスケープについて軽く触れています。マスターファイル以外にも適用されるようなので、適宜 \X
や \DDD
を使っても大丈夫そうです。
実験
仕様でなく実装の確認になってしまいますが、digコマンドでクエリを投げられるかどうか試してみます。
文字数(末尾ドット無し)
253文字まで減らせばOKでした。
$ # 254文字 → NG
$ dig '123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.1234'
dig: '123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.1234' is not a legal name (ran out of space)
$ # 253文字 → OK
$ dig '123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123'
; <<>> DiG 9.10.6 <<>> 123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 22745
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; ...
文字数(末尾ドットあり)
前の実験と同じ名前がOKで、文字数としては1つずれました。
$ # 255文字 → NG
$ dig '123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.1234.'
dig: '123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.1234.' is not a legal name (ran out of space)
$ # 254文字 → OK
$ dig '123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123.'
; <<>> DiG 9.10.6 <<>> 123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123.
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 40333
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; ...
エスケープあり
オクテット数で解釈して問題なければ、表示上は1000文字を超えても怒られませんでした。
$ # 普通に書けるドメイン名 → OK
$ dig 'qi\ita.c\111m'
; <<>> DiG 9.10.6 <<>> qi\ita.c\111m
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15141
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;qiita.com. IN A
;; ...
$ # 1004文字(254オクテット、末尾ドットあり) → OK
$ dig '\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051.\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051.\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051.\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049.'
; <<>> DiG 9.10.6 <<>> \049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051.\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051.\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051.\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048\049\050\051\052\053\054\055\056\057\048;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 32035
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901. IN A
;; ...
まとめ
DNSのドメイン名の最大長について、RFCを見て確認しました。(ついでにdigコマンドで試しました)
RFC1035だと一見255オクテットまでいけそうですが、これはドメイン名の表現が異なります。よく見る表現に直した場合は2つ短くなり、長さは253文字までとなります。ルートを明記する場合はまた変わって254文字までです。
とりあえず253文字までと覚えておけばそんなに問題は起きませんが、微妙な状況を扱う際はどのように長さを測るかまで考える必要があります。