DNS Lab.

도메인 이름 데이터 포맷, 레이블, 그리고 FQDN 본문

DNS 표준/DNS 용어

도메인 이름 데이터 포맷, 레이블, 그리고 FQDN

승홍 2020. 1. 12. 11:50

DNS 질의응답 패킷에서 쓰이는 도메인 이름 데이터는 우리가 아는 도메인 이름과는 다소 다른 모습을 가집니다.

 

도메인 이름을 표기한 'dnssec.tistory.com'은 사람이 사용하기 쉬운 형태인 텍스트(text) 문자열 형태로 표현한 것입니다. 네임서버가 다루는 DNS 도메인 이름 데이터, 그리고 DNS 질의응답 패킷에서 사용하는 도메인 이름 데이터는 '단순한 텍스트 문자열'이 아닙니다.

 

다음 그림은 도메인 이름 'dnssec.tistory.com'을 예로 들어, 도메인 이름의 구조를 보이는 개념도입니다. 도메인 이름 데이터의 모습이 그리 간단하지는 않아 보입니다.

 

그림) 도메인 이름 데이터 포맷 구조 개념도

 

레이블 (label), 도메인 이름의 구성 요소

 

레이블(label)의 데이터 유형은 문자열입니다. 문자열 데이터는 다수의 문자(character)로 조합된 데이터 입니다.

 

네트워크 프로토콜에서 문자열은 흔히 Length|String의 형태로 표현합니다. 즉, 문자열 데이터를 설정할 때 그 앞에 '문자열의 길이(length) 정보'를 두고 이후에 '문자열 데이터'를 설정합니다. 레이블도 이와 동일하게 Len|Label String의 형태를 갖는 문자열 입니다.

 

주의할 것은 '레이블 문자열(Label String)' 만 레이블인 것이 아니라는 점입니다. '레이블 길이'와 '레이블 문자열'을 모두 포괄한 것을 레이블이라 합니다. 레이블은 문자열 데이터이므로, 문자열 길이 정보까지 포함해야 합니다. 문자열 길이가 표시되지 않으면, 길게 이어지는 데이터 스트림 중에서 어디까지가 지정된 문자열에 해당하는지 파악할 수 없어 문자열 정보를 해석해 낼 수 없습니다.

 

DNS에서 원칙적으로는 레이블 문자열에 사용할 수 있는 문자에 제한은 없습니다. 다만, 레이블로 구성된 도메인 이름이 '호스트 이름(hostname)'으로 사용되는 경우에는 오직 영문자, 숫자(0 ~ 9), 하이픈('-') 만 사용하여 레이블 문자열을 구성해야 합니다. (참고 포스팅 : "호스트 이름, 도메인 이름")

 

도메인 이름은 반드시 하나 이상의 레이블로 구성됩니다. 레이블 하나만으로 구성된 도메인 이름도 있습니다. ""이라는 비어있는 하나의 레이블 문자열만 갖는 경우 입니다. 이것은 특수한 도메인 이름인 루트(root) 도메인 이름입니다.

 

DNS 패킷에서는 하나 이상의 레이블을 연이어 나열하여 도메인 이름을 설정합니다. 하지만 이것을 그대로 텍스트로 표현할 수 없으므로, 텍스트로 표현할 때 도메인 이름은 각 레이블 사이에 구분자로 점(dot, ".")을 두어 표기합니다.

 

구체적인 사례로써 텍스트로 표현되는 도메인 이름 dnssec.tistory.com. 경우, 각 레이블은 구분자 점(.)으로 구분되어 표기되어 있습니다. 이 도메인 이름의 데이터는 패킷에서 다음과 같은 형태를 가집니다.

0x06|dnssec|0x07|tistory|0x03|com|0x00

 

여기서 보는 것과 같이 Len|Labe String의 각 레이블이 그대로 연이서 나열되는 형태를 가집니다. 점(.)에 해당하는 부분은 없습니다. 점(.)은 도메인 이름을 텍스트 형태로 표기할 때 만 사용합니다.

 

위 데이터 중 마지막의 0x00 부분은 루트 레이블(root label) 입니다. 특수한 형태의 레이블 입니다. 0x00 레이블은 텍스트 표현으로는 '.'으로 표현합니다. 레이블 구분자 점(.) 이후에 레이블 문자열이 없다는 의미로 이렇게 표기합니다. 루트 레이블(root label)에 대한 자세한 사항은 아래에서 따로 다룹니다.

 

 

Q. 도메인 이름의 각 레이블은 최대 길이가 63 바이트라고 하는데 왜 그런가요?

 

각 레이블은 63 바이트 이내의 문자열이어야 합니다.

 

왜 63 바이트 길이 제한을 두었을까요?

 

레이블은 Len|Label String으로 구성되는데, Len은 1바이트 필드이므로 28 = 256 이어서, 최대 표현할 수 있는 레이블 길이는 255 바이트 일 것 같은데, 그렇지 않고 이보다 훨씬 작은 길이인 63 바이트로 레이블 문자열 최대 길이가 제한되어 있습니다.

 

레이블 최대 길이 63 바이트에 대한 제한은 DNS 표준에서 일방적으로 정한 것은 아닙니다. 반대로 당시 인터넷 및 호스트 환경을 고려하여 설계하다 보니 레이블 최대 길이가 대략 63 바이트로 정해진 것이라 할 수 있습니다. 즉, 당시의 인터넷 및 호스트 규정에 대한 대대적인 수정 없이 DNS 체계를 인터넷에 도입 적용할 수 있도록 DNS 표준 규정을 정하였다고 볼 수 있습니다. 이 가운데 레이블 문자열의 최대 길이는 63 바이트로 정해졌습니다.

 

DNS 표준에 의한 도메인 이름 체계가 개발되기 전에 이미 당시 인터넷에서는 "호스트 이름"이 사용되고 있었습니다. 호스트(host) 시스템에서 사용하는 호스트 이름(hostname)은 최대 255 바이트로 제한되어 있습니다. 데이터 길이를 1 바이트 필드로 표기한다면 28 = 256 이므로 표현 가능한 데이터 길이는 0 ~ 255 바이트입니다. DNS 표준 설계시 이 사항이 고려되었을 것입니다.

 

'80년 초기 그 당시 DNS를 설계하던 입장에서 생각해 보기로 합니다. DNS 표준으로 도입하려는 도메인 이름 체계는 영역(domain) 구분을 두어 조성하는 이름 체계 입니다. dnssec.tistory.com. 경우, 루트(.) 도메인 영역의 하위 서브 도메인 영역 com., 그 아래 tistory.com 서브 도메인 영역에 속하는 이름 dnssec 임을 표현합니다. 이때 dnssec.tistory.com.이 호스트 이름으로 사용된다면 전체 이름인 dnssec.tistory.com.의 길이가 255 바이트를 초과하지 않아야 합니다. 이를 볼 때, 만약 각 레이블 길이의 최대 길이를 255 바이트로 규정한다면 뭔가 문제가 있을 것 같아 보입니다. 전체 도메인 이름 길이가 호스트 이름 최대 길이인 255 바이트 이내 이어야 한다면, 도메인 이름을 구성하는 레이블 문자열의 최대 길이는 좀 더 짧아야 할 것입니다. 그래야 다수 레이블로 구성된 도메인 이름 전체 길이가 255 바이트를 초과하지 않게 될 수 있으니까요.

 

DNS 표준은 초기에 레이블 형식을 정의하면서 레이블의 길이를 표기하는 1 바이트 필드를 2비트의 Label Type과 6 비트의 Label String Length 서브 필드로 구분하여 나누었습니다. 이렇게 정의하면 Label String의 길이를 표시하는 Label String Length가 6 비트 필드가 표현할 수 있는 레이블 문자열 최대 길이는 63 바이트가 됩니다 (26 - 1 = 63). 이것이 레이블 문자열 최대 길이가 63 바이트로 한정된 이유입니다.

 

Q. 그러면, 도메인 이름에 설정할 수 있는 레이블 최대 개수는 몇 개인가요?

 

도메인 이름을 구성하는 데 사용할 수 있는 레이블의 최대 개수에 대해서는 제한 규정은 없습니다.

다만, 도메인 이름 최대 길이 255 바이트 제한에 의해, 도메인 이름에 사용할 수 있는 레이블 개수가 제한 됩니다.

 

예시로써 레이블 문자열 길이가 모두 63 바이트인 레이블 문자열로만 도메인 이름을 구성한다고 가정 합니다. 이 경우, 도메인 이름 길이 255 바이트 한계 내에서 사용할 수 있는 레이블 개수는 3개 입니다. 4개의 63 바이트 레이블 문자열로 구성하는 도메인 이름은 257 바이트가 되므로, 3개의 63 바이트 레이블까지 사용하여 도메인 이름을 만들 수 있습니다. 구체적으로 계산해 보면 다음과 같습니다.

$ echo "$(( (1 + 63) * 3 + 1 ))"
192
$ echo "$(( (1 + 63) * 4 + 1 ))"
257
$

 

위 길이계산 식의 마지막에 +1이 더 있습니다. 이것은 패킷 내의 도메인 이름 데이터 포맷과 도메인 이름의 텍스트 표현 형식이 서로 상이하기 때문입니다. 구체적으로 dnssec.tistory.com. 이라는 도메인 이름 경우를 살펴보면 그 이유를 알 수 있습니다.

 

0x06|dnssec|0x07|tistory|0x03|com|0x00

길이계산 : (1 + 6) + (1 + 7) + (1 + 3) + (1 + 0) = 20

 

여기서 보듯이, 각 레이블의 길이는 '레이블 길이 표현 1 바이트' + '레이블 문자열 길이'로 계산됩니다. 문제는 마지막 루트 레이블(root label) 경우 입니다. 도메인 이름의 마지막 레이블은 항상 루트 레이블 입니다. 루트 레이블은 Len|Label String 중에서 1 바이트인 Len 필드로만 구성되므로 그 길이는 항상 1 바이트이며 그 값은 0x00 입니다.

 

텍스트 형태로 표현된 도메인 이름 dnssec.tistory.com.의 길이는 19 바이트 입니다. 하지만 도메인 이름 포맷으로 설정되는 도메인 이름은 0x06|dnssec|0x07|tistory|0x03|com|0x00이며 그 길이는 20 바이트 입니다. 여기서 알 수 있는 것은 도메인 이름의 최대 길이 255 바이트 초과여부를 판단하는 기준은 텍스트로 표현된 도메인 이름이 아니라 패킷에 설정되는 도메인 이름 데이터라는 점 입니다.

 

그러면 텍스트 표현 도메인 이름으로 기준할 때 도메인 이름의 최대 길이는 어떻게 될까요? FQDN 이름을 기준할 때는 254 바이트 입니다. 하지만 마지막 루트 레이블('.')을 생략한 표현의 경우라면 253 바이트 입니다. 254 바이트의 FQDN 도메인 이름은 255 바이트의 도메인 이름 데이터 길이에 해당합니다. 

 

Q. 레이블의 레이블 종류(Label Type)라는 필드는 어떤 역할을 하나요?

 

각 레이블은 Len | Label 형태를 갖습니다. 위 그림에서 보듯이 Len 필드는 2개 부분으로 나뉘어 있습니다.

 

Len 필드의 첫 2 bit는 레이블 종류(label type)를 표시합니다. 0b00인 경우 Label은 일반 레이블입니다. 0b11인 경우, Label은 압축된 도메인 이름(compressed domain name) 경우에 사용되는 레이블에 대한 Offset 값을 의미합니다.

 

다음 표는 레이블 종류(Label Type) 필드의 값을 정리하여 보여 줍니다.

label type
(2비트)
개요
0b00...... 일반 레이블 (초기 표준, RFC1035)
0b01...... 미정의
0b10...... 미정의
0b11...... 압축된 도메인 이름(compressed domain)의 offset (초기 표준, RFC1035)

지금까지의 레이블 문자열 길이에 대한 설명은 레이블 종류(label type) 중 0x00 유형인 경우에 국한되어 있었습니다. 레이블 문자열을 직접 사용하는 일반적인 경우입니다.


반면, 레이블 종류(label type) 값이 
0b11인 경우, 이 레이블은 특별한 역할을 합니다. 이것은 DNS 메시지 압축(DNS Message Compression) 방식에 사용되는 레이블 입니다.

 

레이블 종류(label type) 값이 0b11이면, 이 레이블은 항상 2 바이트 길이를 가집니다.

 

초기 DNS 표준 문서 RFC1035, 4.1.4. Message compression 장에는 다음과 같이 레이블 종류(label type) 값이 0x11인 경우에 특수한 레이블 포맷을 정의하고 있습니다.

 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| 1  1|                OFFSET                   |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

레이블 종류(label type) 값이 0x11인 경우, 레이블은 16 비트 곧 2 바이트의 고정된 길이를 갖습니다. Offset 값은 14 비트 길이를 가지는 필드이며 표현할 수 있는 최대 값은 214 - 1 = 16,383입니다. 이 Offset 필드 값은 문자열 데이터가 아닙니다. DNS 메시지 중 어딘가에 있는 레이블 문자열의 위치를 표현하는 Offset 값 입니다. 자세한 사항은 DNS 메시지 압축(DNS Message Compression)에 대한 별도 포스팅에서 다루기로 합니다.

 

그림) Label Type = 0b11 경우, 레이블 Offset 포맷 개념도

루트 레이블 (root label)

도메인 이름은 다수의 연속된 레이블로 구성되어 있습니다. 점(dot, ".")을 구분자로 삼아  각 레이블을 순서대로 나열하여 도메인 이름을 형성합니다.

 

도메인 이름 dnssec.tistory.com에서 'dnssec', 'tistory', 'com'이 각각 레이블(label) 입니다. 하지만, 여기서 언급이 누락된 레이블이 하나 있습니다. 맨 마지막의 루트 레이블(root label)이 바로 그것 입니다.

 

루트 레이블은 특수한 레이블입니다. 루트 레이블은 항상 0x00 값을 가집니다. 모든 레이블은 Len|Label 형태의 포맷을 갖습니다. 이는 루트 레이블에도 그대로 적용됩니다. 루트 레이블 경우 레이블(Label) 문자열은 "NULL 문자열" 입니다. "NULL 문자열" 은 길이가 0인 문자열 입니다. "NULL 문자"와는 다릅니다. 개념상 유의해야 할 부분입니다. "NULL 문자"는 길이가 1 바이트이고 "NULL 문자"의 코드 값은 1 바이트의 0x00 입니다. ASCII 문자 코드 테이블의 첫번째 문자가 바로 이 "NULL 문자" 입니다. 이에 비해 "NULL 문자열" 은 아무런 값이 없고 길이도 없어 그 길이는 0 바이트입니다. 루트 레이블(root label)은 NULL 문자열 입니다. 그래서 Len 값이 0x00이고 그 레이블 문자열은 데이터가 비어있는 "NULL 문자열" 입니다.

 

루트 레이블을 고려하면 도메인 이름 dnssec.tistory.com을 구성하는 레이블은 'dnssec', 'tistory', 'com', 그리고 마지막의 루트 레이블 입니다.

 

이렇게 모든 도메인 이름의 마지막 레이블은 항상 루트 레이블 입니다. 모든 도메인은 루트 도메인 영역에 속해 있다는 것을 의미합니다.

 

FQDN (Fully Qualified Domain Name)

모든 도메인 이름의 마지막 레이블은 항상 루트 레이블입니다.

 

루트 레이블은 텍스트 형태로 표기할 때 "."으로 표기합니다. 레이블의 문자열 값이 없다는 것을 표시하는 표기입니다. 레이블 사이를 구분하는 점(dot, ".") 뒤에 따라오는 레이블이 아무런 문자를 가지지 않는 것을 표시하는 표기 방식입니다.

 

흔히 도메인 이름은 "dnssec.tistory.com" 과 같이 표기합니다. 하지만 이러한 표기는 마지막의 루트 레이블을 생략한 표기 방식입니다. 루트 레이블을 생략했기 때문에 이 도메인 이름이 루트 도메인 영역에 속해 있는 이름인지 아니면 "com.cn."이나 "com.br."과 같이 어떤 도메인 영역 하위에 속한 이름인지 확실히 알 수 없습니다.

 

도메인 이름 "dnssec.tistory.com"의 전체 내용을 표기한다면 "dnssec.tistory.com."이 되어야 합니다. 루트 레이블(".")을 명기하는 것입니다.

 

"dnssec.tistory.com."으로 루트 레이블까지 명시하여 표기한 도메인 이름 표기 방식FQDN (Fully Qualified Domain Name) 이라 합니다. 이 용어를 한국어로 어떻게 번역해야 할 지 좀 난감합니다. 의역한다면 대략 "완전한 도메인 이름", "약칭이 아닌 온전한 전체 이름", 또는 "절대적 도메인 이름" 정도가 되지 않을까 싶습니다. 루트 레이블까지 포함한 전체 도메인 이름을 명확히 명시한 도메인 이름이라는 의미입니다.

참고하세요 : Fully qualified domain name - Wikipedia

 

FQDN을 기준으로 본다면, "dnssec.tistory.com"으로 표기한 도메인 이름은 상대적 도메인 이름으로써 도메인 이름의 일부분만을 표기한 도메인 이름이라 할 수 있습니다. 도메인 이름 "dnssec.tistory.com"은 "dnssec.tistory.com.cn."이란 도메인 이름의 일부분 일 수도, 아니면 "dnssec.tistory.com.br."의 일부분 일 수도 있습니다. 이 도메인 이름이 최종적으로 소속된 도메인 영역이 어디인지 표기되지 않았기 때문입니다. (중국 .cn 도메인은 com.cn. 이라는 서브 도메인 영역을, 브라질 .br 도메인 역시 com.br. 서브 도메인 영역을 가지고 있습니다.) 이에 반해 FQDN "dnssec.tistory.com."은 이 이름이 루트에서 바로 위임된 'com', 그리고 'com' 에서 'tistory.com'로 위임된 도메인 영역에만 속하는 유일한 도메인 이름 임을 의미 합니다. FQDN "dnssec.tistory.com."은 "dnssec.tistory.com.cn." 일 수 없습니다.

 

FQDN 방식으로 표기된 도메인 이름은 인터넷 상에서 유일한 이름을 명확히 표현하는 역할을 합니다. 인증서 발급 신청 경우와 같이, 표기하는 도메인 이름에 대해 아주 정확한 도메인 이름 정보가 필요한 경우에 FQDN 방식으로 도메인 이름을 표기할 것을 요구하는 것은 이러한 이유 때문입니다.

 

Comments