요약

  • RFC 7112는 프래그먼트 오프셋이 0인 조각이 첫 상위 계층 헤더까지의 전체 헤더 체인을 담도록 요구합니다. 그러면 스테이트리스 필터가 결정적인 헤더가 다른 조각에 있는 동안 추측하는 대신, 충분한 프로토콜 맥락을 보고 유한한 규칙을 적용할 수 있습니다.
  • 첫 번째 프래그먼트의 완전성은 데이터그램 전체의 완전성이 아닙니다. 운영자는 여전히 출발지 구성, 경로 MTU, 패킷을 처리한 장비와 규칙, 이후 프래그먼트 오프셋, 겹침과 타임아웃, 목적지 재조합, ICMPv6 Parameter Problem 코드 3, 최종 서비스 결과에 대해 별도의 증거가 필요합니다.

설명보다 먼저 도착한 패킷

한 개의 TCP 포트로 가는 트래픽은 수락하고 다른 포트로 가는 트래픽은 거부하는 단순한 규칙을 가진 에지 방화벽을 상상해 보십시오. 평범한 비분할 IPv6 패킷은 장비에 IPv6 헤더, 필요한 확장 헤더들, 그리고 최종적으로 TCP 헤더를 제공합니다. 포트가 보이므로 장비는 재조합 큐를 저장하지 않고도 이 패킷에 규칙을 적용할 수 있습니다.

단편화는 이 깔끔한 순서를 깨뜨릴 수 있습니다. IPv6 확장 헤더는 가변 길이이며, 기본 헤더와 전송 프로토콜 사이에 두 개 이상 나타날 수 있습니다. 체인이 충분히 길거나 첫 조각이 충분히 작으면 오프셋 0의 프래그먼트가 TCP 또는 UDP 헤더가 나타나기 전에 끝날 수 있습니다. 패킷은 네트워크 주소는 제시하면서 필터의 판단이 의존하는 필드는 보류하는 것입니다.

RFC 7112는 이렇게 생긴 딜레마를 기술합니다. 스테이트리스 방화벽이 불완전한 첫 프래그먼트를 전달하면, 결과적으로 나타날 전송 헤더가 규칙에 걸렸을 트래픽을 허용했을 수 있습니다. 반대로 조각을 폐기하면 통과했을 트래픽을 거부했을 수도 있습니다. 첫 조각이 정책이 요구하는 증거를 담고 있지 않기 때문에 어느 쪽이든 의도한 정책을 제대로 시행하지 못할 수 있습니다.

해결책은 모든 방화벽이 모든 패킷을 재조합하도록 만드는 것이 아니었습니다. 규격에 맞는 출발지가 첫 프래그먼트에 넣을 수 있는 내용을 제한하는 것이었습니다. 호스트가 IPv6 데이터그램을 단편화할 때 RFC 7112는 전체 IPv6 헤더 체인을 첫 프래그먼트에 포함해야 한다고 규정합니다. 프래그먼트는 중간 장비나 수신자에게 판단을 요청하기 전에 패킷을 스스로 소개해야 합니다.

‘전체’의 정확한 끝점

‘전체 헤더 체인’이라는 표현은 넓어 보입니다. 그러나 RFC는 이를 좁은 끝점으로 한정합니다.

체인은 최초의 IPv6 헤더로 시작하고, 0개 이상의 IPv6 확장 헤더를 통과하며, 첫 상위 계층 헤더에서 끝나거나 그런 헤더가 없으면 No Next Header 값에서 끝납니다. 평범한 경우 상위 계층은 TCP, UDP 또는 ICMPv6입니다. 터널 안의 두 번째 IPv6 헤더나 ESP 헤더는 이 정의에서 상위 계층 종단으로 취급됩니다.

상위 계층의 페이로드는 체인에 포함되지 않습니다. TCP 헤더는 반드시 나타나야 하지만 TCP 애플리케이션 데이터는 그렇지 않습니다. 그래서 RFC 7112는 큰 페이로드를 금지하지 않고, 첫 프래그먼트가 전체 트랜잭션을 담도록 요구하지도 않습니다. 패킷 필터가 필요로 할 수 있는 선택자를 드러내도록 파싱 경계를 한 단계 앞으로 옮길 뿐입니다.

이 구분은 증거 주장을 담금질합니다. 완전한 첫 프래그먼트는 Next Header 순서가 TCP에 이르고 보이는 목적지 포트 필드가 특정 값을 가진다는 것은 보여줄 수 있습니다. 그러나 이후의 애플리케이션 레코드가 무엇을 말하는지는 보여줄 수 없습니다. 헤더 체인이 완성된 이후에도 심층 패킷 검사조차 단편화된 내용을 해석하지 못할 수 있으며, RFC 7112는 이 한계를 명시합니다.

따라서 최소한의 공통 규칙은 “단편화를 안전하게 만든다”보다 작습니다. 패킷의 프로토콜 소개를 여러 프래그먼트에 걸쳐 쪼개지 말라는 것입니다. 그 이후의 모든 문제는 별개의 질문입니다.

오프셋 0은 위치이지 신원이 아니다

RFC 7112는 첫 프래그먼트를 기계적으로 정의합니다. 프래그먼트 오프셋이 0과 같다는 것입니다. 이 정의가 유용한 이유는 장비가 로컬에서 읽을 수 있기 때문입니다. 그러나 과잉 해석하기도 쉽습니다.

오프셋 0은 데이터그램을 만든 사람, 프로그램 또는 조직이 누구인지 증명하지 않습니다. 보이는 IPv6 출발지 주소는 암호학적 신원이 아닙니다. 유효한 헤더 순서는 승인 토큰이 아닙니다. 공격자도 합법적 구현체처럼 문법적으로 완전한 첫 프래그먼트를 만들 수 있습니다.

이 규칙은 헤더 필드에 의존하는 규칙에 필요한 충분한 증거를 제공할 뿐, 그 필드를 해석할 정책 자체를 제공하지 않습니다. 어떤 네트워크는 보이는 포트를 허용할 수 있고, 다른 네트워크는 거부할 수 있습니다. 어떤 중간 장비는 규격에 맞지 않는 첫 프래그먼트를 폐기하도록 설정되어 있을 수 있고, 다른 장비는 호환성을 위해 통과시킬 수 있습니다. 목적지 호스트는 여전히 자신의 수신 동작을 적용합니다.

그래서 첫 프래그먼트의 완전성 요구는 얇은 조정 계층에 맞습니다. 공유 사양은 검사 가능한 패킷 조건을 정의합니다. 그러나 모든 네트워크의 정책을 선택하도록 기관, 저자 또는 미들박스를 임명하지는 않습니다. 참여자들은 같은 구조를 읽고 현지 처리 권한을 유지합니다.

하나의 프래그먼트를 둘러싼 여섯 개의 장부

“첫 프래그먼트가 허용되었다”만 적은 사고 보고서는 무슨 일이 있었는지 설명하는 데 필요한 증거를 잃습니다. 적어도 여섯 개의 장부는 분리되어 있어야 합니다.

첫째는 출발지 구성입니다. 어떤 구현체가 패킷을 보냈는가? 어떤 확장 헤더 순서를 만들었는가? 프래그먼트 헤더를 어디에 두었고, 오프셋 0이 실제로 상위 계층 헤더까지 이어졌는가? 출발지 근처의 캡처는 터널링이나 캡슐화로 패킷이 바뀐 이후의 관찰보다 강한 증거입니다.

둘째는 경로 MTU 상태입니다. 전체 체인을 첫 프래그먼트에 담도록 요구하면 체인이 경로 MTU 안에 들어가야 합니다. RFC 7112는 경로 MTU 탐색이 없는 호스트는 체인을 1280바이트로 제한해야 한다고 말합니다. 따라서 불완전한 첫 프래그먼트는 단순한 방화벽 불일치가 아니라 헤더 구성 오류, 오래된 MTU 믿음, 병리적 확장 체인을 드러낼 수 있습니다.

셋째는 중간 처리입니다. 어떤 장비, 인터페이스, 소프트웨어 버전이 패킷을 봤는가? 어느 규칙 버전이 활성이었는가? 불완전 체인 처리가 켜져 있었는가, 꺼져 있었는가, 호환 모드로 동작했는가? 벤더가 “RFC 7112를 지원한다”는 플릿 수준의 진술은 이런 홉별 질문에 답하지 않습니다.

넷째는 목적지 처리입니다. RFC 7112는 수신 호스트가 요구를 위반하는 첫 프래그먼트를 폐기하고, 평소 ICMPv6 규칙에 따라 ICMPv6 오류를 보내야 한다고 말합니다. 그러나 호스트는 하위 호환 옵션을 노출할 수도 있습니다. 목적지에 도달한 상태는 상류 방화벽의 의도로부터 추론할 수 없습니다.

다섯째는 진단 전달입니다. 호스트나 중간 시스템이 이 이유로 프래그먼트를 폐기하고 오류를 보내면, RFC는 포인터 0인 ICMPv6 Parameter Problem 타입 4, 코드 3을 지정합니다. 오류가 생성되었는지, 속도 제한이 걸렸는지, 반환 경로에서 필터링되었는지, 출발지가 관찰했는지는 또 다른 사실의 사슬입니다.

여섯째는 완성된 서비스 결과입니다. 전송 교환이 성공했는가? 재전송이 다른 패킷화를 선택했는가? 애플리케이션이 타임아웃되었는가? 첫 프래그먼트 검사를 통과하는 것은 그 어느 결과도 증명하지 않습니다.

이 장부들이 표준 주장을 실행 코드의 영수증으로 바꿉니다. 그렇지 않으면 “규격 준수”와 “차단”은 사건을 찾는 라벨에 불과합니다.

허용과 재조합은 다른 기계

RFC 8200은 패킷 다이어그램에서 이 구분을 보이게 합니다. 경로상의 노드가 필요로 할 수 있는 일부 헤더는 모든 프래그먼트에 반복됩니다. 그 뒤를 이어 프래그먼트 헤더가 단편화된 구성을 표시합니다. 프래그먼트 헤더 다음의 확장 헤더들과 상위 계층 헤더는 첫 프래그먼트에 있어야 합니다. 이후의 프래그먼트 패킷은 각자 자신의 오프셋과 데이터를 담습니다. 목적지에서 재조합은 출발지 주소, 목적지 주소, 프래그먼트 식별자를 오프셋과 길이와 함께 사용해 원래 패킷을 복원합니다.

첫 프래그먼트 규칙은 그 과정의 입구를 다룹니다. 과정 자체를 결산하지는 않습니다.

이후 프래그먼트가 영원히 도착하지 않을 수 있습니다. 프래그먼트의 길이가 유효하지 않을 수 있습니다. 재조합이 크기 한도를 넘을 수 있습니다. 두 조각이 겹치면 RFC 8200은 데이터그램 전체를 폐기하도록 요구합니다. 정확한 중복 조각은 감지되어 버려질 수 있고 다른 조각들은 남습니다. 재조합 타이머는 60초 후 만료될 수 있습니다. 각 조건은 자기 증거와 자기 처리를 가집니다.

그렇기 때문에 첫 프래그먼트를 폐기한 뒤 이후 프래그먼트를 전달하는 것이 곧 정책 우회는 아닙니다. 오프셋 0 조각이 없으면 목적지는 원래 패킷을 복원할 수 없습니다. RFC 7112는 스테이트리스 방화벽 예에서 이 사실을 사용합니다. 첫 프래그먼트를 폐기하면 이후 조각이 경로를 계속 따라가더라도 정책을 시행할 수 있습니다. 그러나 이후 조각의 전달을 완전한 데이터그램의 수락으로 오기록해서는 안 됩니다.

따라서 유용한 운영 어휘는 구체적입니다. “첫 프래그먼트가 헤더 체인 검증을 통과했다”는 하나의 진술입니다. “모든 프래그먼트가 유효한 데이터그램을 이루었다”는 또 하나의 진술입니다. “전송 대화가 성공했다”는 세 번째입니다. 이들을 합치면 실패도 오경보도 모두 가려집니다.

코드 3은 영수증이지 보증이 아니다

RFC 7112는 이 위반에 전용 진단을 부여했습니다. ICMPv6 Parameter Problem 코드 3, “IPv6 First Fragment has incomplete IPv6 Header Chain”입니다. 포인터 필드는 0입니다. 이 코드는 침묵하는 모호성을 출발지가 원칙적으로 관찰할 수 있는 것으로 바꿉니다.

그러나 규범적 동사가 중요합니다. 수신 호스트는 폐기해야 하고 오류를 보내야 합니다. 중간 시스템은 폐기할 수 있고 보낼 수 있습니다. 능력이 있는 중간 시스템은 폐기 동작에 대한 설정을 제공해야 합니다. ICMPv6 생성은 여전히 기존 오류 메시지 규칙의 제약을 받습니다. 출발지 주소 위조, 속도 제한, 필터링도 발신자에게 도달하는 것을 바꿀 수 있습니다.

따라서 코드 3의 부재는 모든 홉이 패킷을 수락했다는 증거가 아닙니다. 코드 3의 존재는 인벤토리에 이름이 올라간 장비가 그것을 생성했다는 증거도 아닙니다. 이 영수증은 캡처 지점, 타임스탬프, 인용된 패킷, 인터페이스, 카운터, 설정 버전과 짝을 이룰 때 유용해집니다.

규모가 커지면 운영자는 코드를 센서로 다루어야 합니다. 소프트웨어 배포 후 갑작스러운 증가는 불법 프래그먼트를 만드는 출발지를 가리킬 수 있습니다. 방화벽 변경 후 감소는 출발지가 수리되었거나, 진단 자체가 사라졌음을 뜻할 수 있습니다. 폐기 카운터, 샘플링된 패킷, 반환 경로 텔레메트리가 분리되어 있어야만 그 차이가 보입니다.

원자적 프래그먼트는 별개의 예외

Fernando Gont의 RFC 6946은 관련이 있지만 다른 모호성을 다룹니다. IPv6 원자적 프래그먼트는 프래그먼트 헤더를 담고 있으면서 프래그먼트 오프셋과 M 플래그가 모두 0입니다. 이 패킷은 다른 조각을 기다리지 않습니다. 과거 일부 구현은 같은 출발지·목적지·식별자 튜플을 공유하는 조각들과 함께 이를 재조합 큐에 넣어 공격 표면을 만들었습니다.

RFC 6946은 원자적 프래그먼트를 다른 프래그먼트와 독립적으로 처리한다고 말합니다. RFC 8200은 그 동작을 편입했습니다. 이것은 RFC 7112 규칙의 다른 형태가 아닙니다.

이 구분은 조사 중에 중요합니다. 불완전한 첫 프래그먼트는 오프셋 0이지만, 보통 헤더 체인이 잘못 쪼개진 실제 단편화 데이터그램을 가리킵니다. 원자적 프래그먼트는 프래그먼트 헤더를 담은 완전한 데이터그램입니다. 겹치는 프래그먼트는 또 다른 조건입니다. 같은 파서가 세 가지를 모두 만날 수 있지만, 각각은 다른 상태 전이와 다른 처방을 함축합니다.

텔레메트리가 프래그먼트 헤더를 가진 모든 패킷을 단순히 “단편화됨”으로 라벨링하면 이 구분이 파괴됩니다. M 플래그, 오프셋, 식별자, 관찰된 체인 종단, 프래그먼트 수, 재조합 키를 유지하십시오. 패킷 형식은 이미 그 열들을 제공합니다. 운영자가 그것을 버리지 않는 일만 남습니다.

패치에서 기본 사양으로

RFC 7112는 2014년 RFC 2460을 갱신했습니다. RFC 8200은 2017년 RFC 2460을 대체하며 첫 프래그먼트 요구를 IPv6 사양 자체에 편입했습니다. 그 단편화 절차는 프래그먼트 헤더 이후의 모든 확장 헤더와 상위 계층 헤더가 첫 프래그먼트에 있어야 한다고 말합니다. 그 오류 조건은 상위 계층 헤더까지의 헤더가 없는 첫 프래그먼트는 폐기되어야 하고 Parameter Problem 코드 3을 유발해야 한다고 말합니다.

RFC 9099는 이후 이 규칙을 운영 보안 조언으로 옮겼습니다. 방화벽과 보안 장비는 전송 헤더를 포함한 전체 체인이 빠진 첫 프래그먼트를 폐기해야 합니다. 목적지 노드도 마찬가지입니다. 이런 가시성이 없으면 적대적 측이 스테이트리스 필터링을 우회할 수 있습니다.

이 발표 이력은 사양 변경의 증거이며, 모든 배포된 구현체가 같은 날 바뀌었다는 증거가 아닙니다. 어플라이언스는 호환성 스위치를 유지할 수 있습니다. 호스트는 오류 생성에서 서로 다를 수 있습니다. 캡슐화는 관련 관찰 지점을 옮길 수 있습니다. 하드웨어 파서는 패킷이 형식적으로 유효하더라도 유한한 확장 헤더 깊이를 가질 수 있습니다.

특정 네트워크에 대해 방어 가능한 주장은 오직 그 실행 경로에서 나옵니다. 조작된 테스트, 패킷 캡처, 카운터, 오류 메시지, 버전이 붙은 설정, 서비스 결과입니다. RFC는 무엇을 테스트할지 정의합니다. 결과를 채워 넣지는 않습니다.

Fernando Gont의 문서화된 역할

RFC 7112는 Fernando Gont, Vishwas Manral, Ron Bonica를 저자로 명시합니다. 그 Standards Track 지위는 IETF 검토와 합의를 반영합니다. Gont는 커뮤니티 문서의 유일한 발명자가 아니며, 저자 자격이 어떤 네트워크의 구현이나 필터링 정책에 대한 권한도 부여하지 않습니다.

그의 더 넓은 기록은 인물 렌즈를 부풀리지 않으면서 유의미하게 만듭니다. RFC 6946은 원자적 프래그먼트 처리 변경의 저자로 그를 명시합니다. 현재 IETF Datatracker 프로필은 40개의 RFC를 나열하고 프로토콜 보안과 오픈소스 구현에 대한 작업을 기술합니다. 그 연속성은 하나의 방법입니다. 패킷 상태의 모호성을 찾아내고, 구현체들이 하나로 뭉개 놓은 상태들을 분리하며, 운영자가 테스트할 수 있는 조건을 제공하는 것입니다.

그 방법은 전기보다 내구성이 있습니다. 첫 프래그먼트에 적당한 입증 부담을 부여합니다. 패킷은 로컬 판단에 필요한 프로토콜 경계를 밝혀야 합니다. 방화벽은 판단할 수 있습니다. 목적지는 재조합할 수 있습니다. 애플리케이션은 성공하거나 실패할 수 있습니다. 그 어떤 기능도 다른 기능이 되지 않습니다.

프래그먼트는 자기 이야기 전체를 한 번에 말할 필요가 없습니다. 다음 기계가 자신이 어떤 질문에 답하고 있는지 알 수 있을 만큼 정직하게 이야기를 소개하면 됩니다.

출처