RFC 1035
고친 사람 github-actions[bot]
RFC 1035 는 도메인 이름 체계를 실제로 어떻게 만들지 적어 놓은 표준 문서입니다. 이름을 어떤 바이트로 적는지, 질문과 답을 어떤 모양으로 주고받는지, 받은 답을 얼마나 들고 있어도 되는지를 이 문서가 못박습니다. 1987년에 나온 문서이고 오늘 도는 이름 풀이도 이 규칙 위에 섭니다.
쉽고 빠른 이해
RFC 1035 는 이름을 주소로 바꾸는 절차를 바이트 단위까지 적어 둔 문서입니다. 브라우저가
example.com 을 열 때 오가는 질문과 답의 모양이 여기서 나옵니다.
규칙이 없으면 이름을 푸는 프로그램마다 메시지 모양이 갈립니다. 그러면 다른 회사가 만든 이름 서버와는 말이 안 통합니다.
돌아가는 방식은 이렇습니다.
- 묻는 쪽이 찾는 이름과 데이터 종류를 담은 질문 메시지를 만듭니다
- 이름 서버가 같은 메시지에 답을 채워 돌려줍니다
- 받은 쪽은 답에 붙어 온 시간만큼 그 답을 들고 있다가 버립니다
대가도 있습니다. 한 메시지를 512바이트로 묶어 둔 탓에 답이 길면 뒤가 잘립니다.
상세
이 문서의 제목과 짝 문서
RFC(Request for Comments)는 IETF(Internet Engineering Task Force, 인터넷 표준을 만드는 단체)가 번호를 붙여 내는 문서입니다. 1035번 문서의 제목은 「Domain Names - Implementation and Specification」입니다.
이 문서가 적는 것은 DNS(Domain Name System, 도메인 이름 체계)입니다. 사람이 쓰는 이름을 기계가 쓰는 IP 주소(IP 는 Internet Protocol, 인터넷에서 기계를 가리키는 번호를 정하는 규칙입니다) 같은 값으로 바꾸는 체계이고, 이름을 나눠 맡은 서버들이 서로 물어 답을 찾습니다.
짝 문서가 있습니다. RFC 1034 는 이 체계가 무엇이고 무엇을 해 주는지를 말로 풀고, 이 문서는 그것을 어떻게 만들지를 바이트까지 적습니다. 둘이 함께 인터넷 표준으로 올라가면서 STD(Standard, 표준) 13 이라는 번호를 같이 받았습니다.
나온 때는 1987년 11월입니다. 앞선 RFC 882 · 883 · 973 을 폐기했습니다. 그 뒤로 서른 편 가까운 문서가 이 문서의 일부를 고쳤지만 메시지 모양과 이름 규칙의 뼈대는 남아 있습니다.
도메인 이름을 적는 규칙
도메인 이름은 점으로 나뉜 조각의 줄입니다. 조각 하나를 레이블이라고 부릅니다.
www.example.com 은 레이블 셋으로 이루어집니다.
메시지 안에서는 점을 쓰지 않습니다. 레이블마다 앞에 길이를 적은 한 바이트를 붙이고, 끝에 길이 0 인 바이트를 놓아 이름이 끝났다고 알립니다.
03 w w w // 레이블 www
07 e x a m p l e // 레이블 example
03 c o m // 레이블 com
00 // 이름 끝
길이 바이트는 여덟 비트지만 위 두 비트를 늘 0 으로 두기로 정했습니다. 그래서 레이블 하나는 63바이트를 넘지 못합니다. 이름 전체도 255바이트까지입니다. 남겨 둔 두 비트가 무엇을 하는지는 아래 「이름 압축」에서 드러납니다.
이름을 견줄 때는 대문자와 소문자를 같게 봅니다. Example.com 과 example.com 은 같은
이름입니다.
메시지의 다섯 부분
질문이든 답이든 같은 틀의 메시지 하나에 담깁니다. 틀은 다섯 부분으로 나뉘고 순서가 고정입니다.
block-beta columns 1 a["헤더 · 12바이트"] b["질문 · 무엇을 묻나"] c["답변 · 물은 것의 답"] d["권한 · 그 답을 아는 이름 서버"] e["추가 · 덤으로 붙이는 레코드"]
답하는 쪽은 받은 메시지의 질문 부분을 손대지 않고 두고, 뒤의 세 부분을 채워 돌려줍니다. 그래서 답만 받아도 무엇을 물었던 답인지 알 수 있습니다.
질문 부분에는 찾는 이름과 함께 「무슨 데이터를 원하는가」가 들어갑니다. 주소를 원하면
A, 메일 서버를 원하면 MX 를 적는 식입니다.
헤더의 비트 자리
헤더는 열두 바이트 고정입니다. 아래 그림은 그 안에 무엇이 어느 비트에 놓이는지 보입니다.
packet-beta 0-15: "ID" 16-16: "QR" 17-20: "Opcode" 21-21: "AA" 22-22: "TC" 23-23: "RD" 24-24: "RA" 25-27: "Z" 28-31: "RCODE" 32-47: "QDCOUNT" 48-63: "ANCOUNT" 64-79: "NSCOUNT" 80-95: "ARCOUNT"
그림의 이름들이 각각 무엇을 정하는지는 아래와 같습니다.
| 필드 | 하는 일 |
|---|---|
ID |
질문마다 붙이는 16비트 번호. 답이 오면 이 번호로 짝을 맞춘다 |
QR |
이 메시지가 질문인가 답인가 |
AA |
답한 이름 서버가 그 이름을 직접 맡은 쪽인가 |
TC |
크기 제한에 걸려 뒤가 잘렸나 |
RD |
묻는 쪽이 끝까지 대신 찾아 달라고 부탁했나 |
RCODE |
결과 번호. 0 은 정상이고 3 은 그런 이름이 없다는 뜻이다 |
| 뒤의 네 칸 | 뒤따르는 네 부분에 각각 몇 개가 들어 있나 |
ID 는 답이 뒤섞여 와도 짝을 맞추라고 둔 칸입니다. 질문을 UDP(User Datagram Protocol) 로
보내면 답이 보낸 순서대로 돌아온다는 보장이 없기 때문입니다.
리소스 레코드
답에 실려 오는 데이터 한 줄이 리소스 레코드입니다. 종류가 무엇이든 여섯 칸의 틀은 같습니다.
| 칸 | 담는 것 |
|---|---|
| 이름 | 이 레코드가 딸린 도메인 이름 |
| 종류 | 무슨 데이터인가 |
| 클래스 | 어느 망의 데이터인가. 인터넷이면 IN |
| TTL(Time to Live, 살아 있을 시간) | 받은 답을 다시 써도 되는 초 |
| 길이 | 뒤따르는 데이터가 몇 바이트인가 |
| 데이터 | 종류마다 모양이 다른 값 |
종류 칸에 들어가는 값 가운데 지금도 자주 보는 것은 아래 일곱입니다.
| 종류 | 담는 값 |
|---|---|
A |
호스트의 주소 |
NS |
이 이름 아래를 맡은 이름 서버 |
CNAME |
별명이 가리키는 본이름 |
SOA |
이 도메인 묶음을 누가 맡고 사본을 얼마마다 새로 받나 |
PTR |
주소에서 이름으로 거꾸로 가는 표시 |
MX |
이 도메인의 메일을 받는 서버 |
TXT |
아무 문자열 |
이 문서가 정한 종류는 열여섯 개입니다. 종류 칸이 16비트라 자리가 넉넉해서, 뒤에 나온 문서들이
AAAA 나 SRV 같은 종류를 계속 더했습니다.
이름 압축
한 메시지 안에 같은 이름이 여러 번 나옵니다. 질문에 example.com 이 있으면 답변에도, 권한
부분에도 같은 글자가 또 실립니다.
같은 글자를 되풀이하지 않으려고 앞에 나온 이름을 가리키는 두 바이트 포인터를 씁니다. 첫 두
비트를 11 로 두고 남은 열네 비트에 메시지 첫 바이트부터 떨어진 거리를 적습니다.
레이블 길이 바이트는 위 두 비트가 늘 0 이었습니다. 그래서 읽는 쪽은 바이트 하나만 보고 이것이 길이인지 포인터인지 가릅니다. 레이블을 63바이트로 묶은 상한은 이 구분을 얻으려고 치른 값입니다.
어느 길로 보내나
이름 서버는 포트 53번에서 기다립니다. 질문은 대개 UDP 로 보냅니다. 연결을 맺고 끊는 절차가 없어 한 왕복으로 끝나기 때문입니다.
다만 UDP 로 보내는 메시지는 512바이트까지입니다. 답이 그보다 길면 이름 서버는 들어가는
만큼만 채우고 TC 비트를 켭니다. 받은 쪽은 아래 순서로 다시 받아 옵니다.
flowchart TD
A["UDP 로 질문한다"] --> B{"답이 512바이트에<br/>들어갔나"}
B -->|들어갔다| C["답을 그대로 쓴다"]
B -->|잘렸다| D["TC 비트가 켜져 온다"]
D --> E["TCP 로 연결을 맺고<br/>같은 질문을 다시 한다"]
E --> F["잘리지 않은 답을 받는다"]
TCP(Transmission Control Protocol) 로 보낼 때는 메시지 앞에 길이를 적은 두 바이트를 붙입니다. 바이트 흐름에는 경계가 없어서 이 길이가 없으면 어디까지가 한 메시지인지 읽는 쪽이 가릴 수 없습니다.
한 이름 서버가 통째로 맡은 도메인 묶음을 존이라고 합니다. 존을 그대로 복사해 가는 존 전송은 UDP 로 하면 안 됩니다. 중간이 빠져도 받는 쪽이 빠진 줄 모르기 때문입니다.
잃어버린 질문은 다시 묻는다
UDP 는 잃어버린 패킷(망으로 오가는 데이터 한 덩이)을 대신 채워 주지 않습니다. 그래서 묻는 쪽이 답을 기다리다 안 오면 스스로 다시 물어야 합니다. 이 되물음이 재전송입니다.
이 문서는 다시 묻는 방법을 권고로 적습니다. 같은 주소에 되풀이해 묻기 전에 그 도메인을 맡은 다른 이름 서버를 먼저 찔러 보라고 합니다. 다시 묻는 간격은 앞서 재 둔 응답 시간에서 뽑되 최소 2~5초는 두라고 적습니다.
간격을 짧게 잡으면 아직 답을 못 준 서버에 같은 질문이 계속 쌓입니다. 그러면 그 서버가 처리할 것이 늘어 모두가 더 오래 기다리게 됩니다. 최소 간격은 그 쏠림을 막으려고 둔 선입니다.
답을 얼마나 들고 있나
답에 실린 레코드마다 TTL 이 붙어 옵니다. 값은 32비트 정수이고 단위는 초입니다.
받은 쪽은 그 초 동안 답을 손안에 저장해 두었다가, 같은 질문이 또 오면 이름 서버에 묻지 않고 꺼내 씁니다. 이렇게 받은 답을 들고 있다 다시 쓰는 것이 캐싱이고, 답을 모아 둔 곳을 캐시라고 부릅니다.
TTL 이 0 이면 캐시하면 안 됩니다. 지금 하고 있는 질문에만 쓰고 버리라는 뜻입니다.
이 값이 부호 있는 수인지 없는 수인지는 이 문서 안에서도 절마다 달리 적혀 있습니다. 뒤에 나온 RFC 2181 이 어긋남을 정리했습니다.
캐시가 있어서 이름 서버 몇 대가 세상의 질문을 감당합니다. 대신 값을 바꿔도 먼저 나간 답의 TTL 이 지나기 전에는 옛 값을 보는 쪽이 남습니다. 웹 캐시가 신선도를 재면서 치르는 것과 같은 대가입니다.
나중에 고쳐진 대목
512바이트 상한은 답이 길어지면서 짐이 됐습니다. 뒤에 나온 EDNS0(Extension Mechanisms for DNS, DNS 확장 방식)이 묻는 쪽이 받을 수 있는 크기를 미리 알리게 해서 이 상한을 넓혔습니다.
받은 답이 진짜 그 도메인의 주인에게서 온 것인지 가리는 방법은 이 문서에 없습니다. 중간에서 답을 가로채 가짜를 돌려주면 묻는 쪽은 알아챌 수 없습니다. 그 몫은 뒤에 나온 DNSSEC(DNS Security Extensions, DNS 보안 확장)이 서명으로 맡았습니다.
관련 항목
이 문서와 함께 DNS 를 정의하는 표준 문서
RFC 1034 · RFC 1123 · RFC 2181 · RFC 2308 · RFC 6891 · RFC 4033 · RFC 7766
이 문서가 정의하는 메시지 구성 요소
DNS 메시지 · DNS 헤더 · 리소스 레코드 · 레이블 · 이름 압축 · 존 파일 · RDATA
이 문서가 정한 리소스 레코드 종류
A 레코드 · NS 레코드 · CNAME · SOA 레코드 · PTR 레코드 · MX 레코드 · TXT 레코드 · HINFO 레코드
DNS 메시지를 나르는 하위 프로토콜
UDP · TCP · IP 주소 · 포트 · 데이터그램 · 패킷
DNS 질의에 관여하는 역할
리졸버 · 스텁 리졸버 · 재귀 이름 서버 · 권한 있는 이름 서버 · 루트 이름 서버 · 존
답을 다시 쓸지 가리는 개념
TTL · 신선도 · 캐싱 · 낡은 데이터 · 네거티브 캐싱 · 재전송
이 문서를 넓히거나 대체한 확장
EDNS0 · DNSSEC · DNS over HTTPS · DNS over TLS · 존 전송 · 동적 갱신
이 규칙을 구현한 이름 서버와 조회 도구
BIND · Unbound · dnsmasq · PowerDNS · dig · nslookup
DNS 에서 나는 보안 문제
DNS 캐시 포이즈닝 · DNS 증폭 공격 · 도메인 하이재킹 · 서비스 거부 공격
이것이 속하는 상위 분류
다른 이름: Domain Names - Implementation and Specification