# CNAME이 먼저인가, A 레코드가 먼저인가

> Clean Markdown view of GeekNews topic #25981. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=25981](https://news.hada.io/topic?id=25981)
- GeekNews Markdown: [https://news.hada.io/topic/25981.md](https://news.hada.io/topic/25981.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-01-20T18:39:31+09:00
- Updated: 2026-01-20T18:39:31+09:00
- Original source: [blog.cloudflare.com](https://blog.cloudflare.com/cname-a-record-order-dns-standards/)
- Points: 13
- Comments: 1

## Summary

**Cloudflare의 1.1.1.1 서비스가 DNS 응답 내 레코드 순서를 변경하면서 일부 클라이언트에서 해석 실패가 발생했습니다.** CNAME 레코드가 A/AAAA 레코드 뒤로 이동하자, glibc의 `getaddrinfo`나 Cisco 스위치의 DNSC 프로세스처럼 **순서에 의존하는 구현**이 오류를 일으켰습니다. RFC 1034가 CNAME 순서에 대해 명확히 규정하지 않은 점이 근본 원인으로 지적되며, Cloudflare는 CNAME을 항상 먼저 배치하도록 복귀하고 **IETF에 표준 명확화를 위한 Internet-Draft**를 제출했습니다.

## Topic Body

- 2026년 1월 8일, **Cloudflare의 1.1.1.1 서비스 업데이트**가 DNS 응답 내 레코드 순서를 바꾸면서 전 세계 일부 사용자에게 **DNS 해석 실패**가 발생  
- 문제의 원인은 **CNAME 레코드가 A/AAAA 레코드 뒤로 이동**한 코드 변경으로, 일부 **DNS 클라이언트 구현이 순서 의존적**이었기 때문  
- 특히 **glibc의 getaddrinfo 함수**와 **Cisco 스위치의 DNSC 프로세스**가 영향을 받아, 후자의 경우 **재부팅 루프**까지 발생  
- RFC 1034는 “CNAME이 앞에 올 수 있다(possibly preface)”고만 명시해, **레코드 순서에 대한 명확한 표준이 부재**함  
- Cloudflare는 **CNAME을 항상 먼저 배치하는 방식으로 복귀**하고, **IETF에 명확한 표준 정의를 위한 Internet-Draft**를 제출  

---

### 1. 사건 개요
- 2026년 1월 8일, 1.1.1.1의 **메모리 사용량 절감 업데이트**가 배포되면서 DNS 응답 내 **레코드 순서 변경**이 발생  
  - 변경은 2025년 12월 2일 코드베이스에 도입, 12월 10일 테스트 환경 배포, 2026년 1월 7일 글로벌 릴리스 시작  
  - 1월 8일 18:19 UTC에 사고 선언, 18:27에 롤백 시작, 19:55에 복구 완료  
- 대부분의 현대 DNS 클라이언트는 **응답 내 레코드 순서를 무시**하지만, 일부 구현은 **CNAME이 항상 먼저 와야 한다고 가정**  
- 이 순서가 바뀌자 일부 클라이언트가 **응답을 비어 있는 것으로 처리**하며 해석 실패 발생  

### 2. CNAME 체인과 캐시 동작
- 도메인 질의 시, 예를 들어 `www.example.com`은 여러 **CNAME 체인**을 거쳐 최종 IP로 해석됨  
  - 예: `www.example.com → cdn.example.com → server.cdn-provider.com → 198.51.100.1`  
- 각 CNAME 링크는 **TTL(Time-To-Live)** 을 가지며, 일부만 만료될 수 있음  
- 1.1.1.1은 **만료된 부분만 재조회**하고, 기존 캐시와 새 레코드를 **병합하여 응답 구성**  

### 3. 코드 변경의 세부 내용
- 기존 코드에서는 **CNAME 체인을 먼저 삽입**하고, 그 뒤에 A/AAAA 레코드를 추가  
  - `answer_rrs.extend_from_slice(&self.records); // CNAMEs first`  
- 변경된 코드에서는 **CNAME을 마지막에 추가**  
  - `entry.answer.extend(self.records); // CNAMEs last`  
- 이로 인해 응답 내에서 **CNAME이 하단으로 이동**, 일부 클라이언트가 이를 처리하지 못함  

### 4. 영향을 받은 구현 사례
- **glibc의 getaddrinfo 함수**는 응답을 순차적으로 파싱하며, **CNAME이 먼저 등장해야** 다음 이름을 추적 가능  
  - CNAME이 뒤에 오면 “예상 이름”이 갱신되지 않아 결과가 비어 있음  
- **Cisco Catalyst 스위치 3개 모델**의 **DNSC 프로세스**도 영향을 받아, 1.1.1.1을 사용 중인 경우 **치명적 오류로 재부팅 루프 발생**  
  - Cisco는 관련 **서비스 문서**를 공개  

### 5. 영향을 받지 않은 구현
- **systemd-resolved**는 응답을 **OrderedSet 구조체**로 파싱해, CNAME 위치와 관계없이 전체 집합을 탐색 가능  
  - 따라서 레코드 순서 변경에도 정상 동작  

### 6. RFC 1034의 모호성
- RFC 1034(1987)은 “응답은 하나 이상의 CNAME으로 **preface**될 수 있다”고 기술  
  - 그러나 **MUST/SHOULD** 같은 규범적 키워드가 없어 **명시적 요구사항이 아님**  
- RFC 2119(1997) 이후에야 이러한 키워드가 표준화되어, 당시 문서는 **명확한 의무 표현이 부재**  
- Cloudflare는 초기 구현에서 CNAME을 먼저 배치했으나, **테스트로 이를 보장하지는 않음**  

### 7. RRset과 메시지 섹션의 구분
- RFC 1034 §3.6은 **RRset(동일 이름·타입·클래스의 레코드 집합)** 의 순서는 중요하지 않다고 명시  
- 그러나 **서로 다른 RRset 간의 순서**에 대해서는 언급이 없음  
- §6.2.1의 예시도 **동일 이름의 A 레코드 두 개**만 다루며, CNAME과 A의 상대적 순서는 다루지 않음  
- 따라서 **CNAME과 A 레코드 간 순서 정의가 공백 상태**  

### 8. CNAME 체인 내부 순서 문제
- CNAME이 여러 단계일 경우, 체인 자체의 순서가 뒤섞여도 **순차 파싱이 실패**  
  - 예: `cdn.example.com CNAME server.cdn-provider.com`이 먼저 오면, `www.example.com CNAME cdn.example.com`을 찾지 못함  
- RFC 1034은 **CNAME 체인 순서에 대한 요구사항도 없음**  

### 9. 리졸버의 동작 기준
- RFC 1034 §5.2.2는 “리졸버는 CNAME을 만나면 새 이름으로 **쿼리를 재시작**해야 한다”고 명시  
- 그러나 이는 **전체 리졸버(예: 1.1.1.1)** 를 대상으로 한 설명이며,  
  **glibc 같은 스텁 리졸버**는 이 로직을 구현하지 않음  
- 결과적으로 일부 스텁 리졸버가 **RFC의 기대 동작을 따르지 않음**  

### 10. DNSSEC의 명시적 규정과 비교
- RFC 4035(DNSSEC)는 **RRSIG 레코드 포함 우선순위**를 “MUST”로 명시  
  - 단, 이는 “포함 여부”에 대한 규정이지 “순서”에 대한 것은 아님  
- DNSSEC은 **명확한 포함 규칙**을 제공하지만, **비서명 영역(Unsigned zones)** 에서는 여전히 RFC 1034의 모호성이 남음  

### 11. Cloudflare의 결론과 조치
- RFC상 CNAME 순서가 **필수는 아니지만**, 일부 클라이언트가 이를 **전제**하므로  
  **CNAME을 항상 먼저 배치**하는 정책으로 복귀  
- 향후 동일 문제 방지를 위해 **IETF에 Internet-Draft 제출**  
  - 문서: [draft-jabley-dnsop-ordered-answer-section](https://datatracker.ietf.org/doc/draft-jabley-dnsop-ordered-answer-section/)  
  - 목표: **DNS 응답 내 CNAME 처리 순서의 명확한 표준화**  
- Cloudflare는 이 사건을 통해 **40년 된 프로토콜의 모호성**이 여전히 실무에 영향을 미침을 확인  

### 12. 부가 정보
- Cloudflare는 1.1.1.1을 포함한 **Connectivity Cloud**를 통해  
  **기업 네트워크 보호**, **인터넷 규모 애플리케이션 가속**, **DDoS 방어**, **Zero Trust 구현 지원**을 제공  
- 무료 앱 1.1.1.1을 통해 **더 빠르고 안전한 인터넷 접속** 가능

## Comments



### Comment 49546

- Author: neo
- Created: 2026-01-20T18:39:31+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=46681611) 
- 나는 RFC의 문구가 그렇게 **모호하지 않음**을 느꼈음  
  “possibly preface”라는 표현은 “CNAME 레코드가 있다면 그걸 먼저 붙인다”는 의미로 읽히며, “원하면 아무 데나 붙여도 된다”는 뜻으로는 해석되지 않음
  - 나도 그렇게 생각함. “prefix할 수 있다”는 말이 “suffix해도 된다”는 뜻은 아님  
    하지만 이건 단순한 문장 해석 문제가 아니라, 세계에서 가장 중요한 DNS 서버 중 하나를 운영하는 팀이 **CNAME 응답 로직을 바꿨다**는 점이 핵심임  
    테스트에서 분명히 깨졌을 텐데, 아무도 “이 순서가 중요한가?”라고 묻지 않았다는 게 놀라움  
    Cloudflare가 최근엔 투명하게 문제를 공개하지만, 이번 건은 “재밌는 사실 공유”처럼 들림  
    대규모 시스템에서 이런 게 테스트를 통과했다는 건 꽤 큰 실수로 보임
  - 기사에서는 모호함이 다른 문장에서 비롯된다고 설명함 — “응답 섹션의 RR 순서 차이는 중요하지 않다”는 구절 때문임  
    예시가 일반화될 수 있어서, “모든 경우에 순서가 상관없다”로 오해될 여지가 있음  
    결국 한 사람의 “명확한 이해”가 다른 사람에게는 “문서를 다 읽었나?”로 보일 수 있음  
    이런 사례가 **규범적 언어(nomative language)** 의 중요성을 보여줌
  - 네가 모호하지 않다고 느낄 수 있지만 실제로는 모호했고, 이를 수정하려는 시도도 있었음  
    관련 논의는 [IETF 메일링 리스트](https://mailarchive.ietf.org/arch/msg/dnsop/2USkYvbnSIQ8s2vfTL4PrCXeUmM/)에서 볼 수 있음
  - 나도 네 의견에 동의함. RFC의 예시 6.2.1 해석이 잘못된 것 같음  
    “순서 차이는 중요하지 않다”는 말은 특정 예시에서만 해당되는 것이고, 일반 규칙을 무시하라는 뜻은 아님  
    RFC 1034가 RRset을 정의했다고 하지만 실제로는 그런 용어 정의가 없음  
    Cloudflare의 해석은 **예외 조항을 일반 규칙으로 오해한 것**으로 보임  
    다만 CNAME 체인의 순서에 대한 명확한 규정은 없어서, 그 부분은 약간의 모호함이 남아 있음
  - 그건 기사에서도 언급된 내용임. RFC가 **규범적 단어(MUST, SHOULD)** 가 표준화되기 전의 문서라는 점을 짚고 있음

- 이건 **Hyrum’s Law**와 **Postel’s Law**가 동시에 작용한 사례 같음  
  “API 사용자가 충분히 많으면, 시스템의 모든 관찰 가능한 동작에 누군가는 의존하게 된다”는 것과  
  “보내는 건 보수적으로, 받는 건 관대하게”라는 원칙이 충돌한 결과임
  - 하지만 Postel의 법칙은 이제 **해로운 원칙**으로 여겨지는 추세임
  - 맞음, 하지만 Hyrum’s Law의 핵심은 세상에 **수많은 엣지 케이스**가 존재한다는 점임  
    이번엔 glibc의 resolver가 깨졌다는 게 포인트임 — 결코 희귀한 상황이 아님  
    Cloudflare가 테스트를 제대로 안 했다는 게 진짜 뉴스임
  - 결국 이는 **사람 수준의 누수된 추상화(leaky abstraction)** 문제임
  - Hyrum’s Law를 완벽히 표현한 [xkcd 만화](https://xkcd.com/1172)가 있음

- 이번 버그는 나에게 오래된 기억을 떠올리게 했음  
  2011년 Cloudflare가 RFC를 무시하고 **도메인 apex에 CNAME을 허용**했을 때임  
  [그때의 블로그 글](https://blog.cloudflare.com/zone-apex-naked-domain-root-doma...)을 보면 “RFC 따위는 무시하고 현실 문제를 해결하겠다”고 했음  
  하지만 CNAME은 **이름 수준(alias)** 개념이라 apex에 두면 NS, MX, SOA 캐싱이 깨짐  
  당시 많은 엔지니어가 경고했지만 “move fast and break things”였음  
  그래도 이번엔 CNAME 체인과 A 레코드 순서를 세밀히 다루는 걸 보니 발전했음
  - 네 말에 공감함. 예전 BIND에서 “cannot have CNAME and other data” 오류를 수도 없이 봤음  
    CNAME과 alias 개념은 오래전부터 혼란을 줬고, RFC1034의 **비규범적 언어**가 그 혼란을 키웠음  
    이런 모호함이 누적된 결과지만, 대형 서비스 제공자가 이런 실수를 한 건 여전히 용납하기 어려움
  - 하지만 명세를 의도적으로 어긴 게 과연 “버그”인가?  
    오히려 **명세 자체가 문제**였다고 생각함

- glibc의 일반적인 DNS lookup이 **레코드 순서에 의존**한다는 게 놀라움  
  20년 넘게 큰 문제가 없었던 게 신기함  
  아마 대부분의 DNS 운영자들이 테스트 중에 순서가 중요하다는 걸 경험적으로 알았을 것임
  - 아마 이런 문제는 자주 있었지만, **규모가 작은 서비스**에서는 그냥 넘어갔을 것임  
    Cloudflare처럼 전 세계 수백만 기기에 영향을 준 경우는 처음이라 주목받은 것임  
    다만 Cloudflare가 이번에 glibc 같은 오픈소스 resolver에 **패치를 보냈는지**는 궁금함
  - 서버 측에서 순서를 유지하는 게 일반적이었고, 그렇지 않은 서버는 **호환성 문제**로 금방 수정했음  
    CNAME은 정말 **다루기 까다로운 존재**임 ([DJB의 노트](https://cr.yp.to/djbdns/notes.html) 참고)
  - 인터넷은 실제로 몇 개의 **주요 권한 서버 구현체**에 의존하고 있어서, 다들 같은 순서 규칙을 따름
  - 순서 제약을 없애려면 **DNS 이름을 빠르게 조회할 수 있는 자료구조**가 필요함  
    glibc 같은 단순 resolver는 캐시가 없기 때문에, 이걸 구현하려면 큰 코드 변경이 필요함

- Cloudflare가 “RFC는 CNAME 순서를 요구하지 않는다”고 주장한 건 **언어 꼬투리 잡기**처럼 들림  
  “MUST”가 없다고 해서 “아무 순서나 가능하다”는 건 억지임  
  잘못을 인정하고 넘어가는 게 세상을 더 낫게 만든다고 생각함  
  **언어 논쟁으로 책임을 회피**하는 건 오히려 신뢰를 잃게 함

- Cloudflare는 RFC1034를 제대로 이해하지 못한 듯함  
  그들의 DNS 인터페이스는 CNAME이 있으면 A, AAAA만 막고, 다른 레코드는 허용함  
  그래서 CNAME과 TXT가 함께 존재할 때 **캐시 의존적 결과**가 발생함  
  [internet.nl](https://github.com/internetstandards/)에서도 이런 문제를 발견했음  
  일부 사용자는 [mxtoolbox 가이드](https://mxtoolbox.com/dmarc/dmarc-setup-cname)를 따라 설정했는데, 이는 RFC1034와 충돌함
  - 그 가이드는 아마 두 가지 다른 설명이 섞인 것 같음  
    하나는 “DMARC 서비스를 CNAME으로 위임하는 법”, 다른 하나는 “직접 호스팅하는 법”임  
    스크린샷이 혼동을 일으킨 듯함

- Cloudflare가 결국 “CNAME은 다른 레코드보다 **앞에 와야 한다**”는 결론에 도달한 건 합리적임
  - 나도 그 결론이 반가움. 모두가 틀렸더라도, 때로는 **현실에 맞춰야 함**

- 회사에서 DNS를 관리하면서 여러 **DNS의 한계**를 체감했음  
  특히 SERVFAIL이 발생하면, 클라이언트가 어떤 서버가 문제인지 구분하지 못함  
  그 결과, 여러 DNS 서버와 캐시 계층이 **불필요한 재시도 폭주**를 일으킴  
  또한 search path가 잘못된 도메인으로 NXDOMAIN 질의를 반복함
  - 나도 비슷한 문제를 겪었음. 캐싱 서버만 보다가 하루 넘게 원인을 찾지 못했는데, 결국 **권한 서버(auth server)** 문제였음
  - BIND 9에는 이를 완화하는 **servfail-ttl 옵션**이 있음  
    [RFC2308 섹션 7.1](https://www.rfc-editor.org/rfc/rfc2308#section-7.1)에 따르면 SERVFAIL 응답을 캐시하는 게 허용되어 있음  
    오래된 표준이지만 여전히 유효한 접근임

- Cloudflare는 종종 **표준을 깨고**, 그걸 정당화하는 **새 RFC를 작성**함  
  RFC 8482 같은 사례는 업계의 **불명예**라고 생각함  
  “이번에도 혼란을 막기 위해 새 Internet-Draft를 제출했다”는 말이 아이러니하게 들림

- 1.1.1.1 같은 대규모 DNS 서버라면 glibc 같은 실제 resolver를 포함한 **통합 테스트**가 있어야 함  
  그런데 왜 이런 문제가 **프로덕션에서만 발견**된 걸까 의문임
  - 아마 캐시 만료 순서가 꼬인 뒤 glibc로 재질의할 때만 발생하는 **희귀한 조합**이었을 것임  
    개별 테스트는 통과했지만, 두 조건이 겹치는 케이스는 빠졌을 가능성이 큼
