개발자 도구 · URL 인코더 및 디코더
퓨니코드 및 퍼센트 인코딩: 비ASCII 도메인 및 경로 처리 방법
· 배경
국제화 퓨니코드 URL 인코딩
비ASCII 호스트 이름과 비ASCII 경로가 있는 URL은 완전히 다른 두 가지 인코딩을 사용합니다. 이 게시물에서는 호스트에 대한 IDNA 및 퓨니코드, 기타 모든 항목에 대한 퍼센트 인코딩, 분할이 존재하는 이유에 대해 설명합니다.
한 브라우저에는 'münchen.example'이 표시되고 다른 브라우저에는 'xn--mnchen-3ya.example'이 표시되는 주소 — 하나의 호스트, 두 개의 철자
München이라는 도시는 독일 도메인 이름에 나타납니다. 브라우저의 주소 표시줄에 münchen.example이 정상적으로 표시되는 것을 볼 수 있습니다. 다른 애플리케이션에서 주소를 복사하면 xn--mnchen-3ya.example로 표시됩니다. 이 문자열은 독일어 텍스트와 전혀 유사하지 않은 ASCII 전용 문자열입니다. 하나의 URL, 두 개의 철자 모두 절대적으로 유효합니다. 둘 다 틀린 것은 아닙니다. 완전히 다른 문자 집합을 사용하여 동일한 도메인을 나타냅니다. 차이점은 DNS 작동 방식과 인터넷 인프라가 호스트 이름 전송을 기대하는 방식에 대한 근본적인 제약을 반영합니다.
/café/과 같은 경로 세그먼트는 인코딩이 필요하지만 다른 시스템을 사용합니다. ASCII가 아닌 é는 경로에서 %C3%A9가 됩니다. 왜 차이점이 있나요? DNS 제약 조건에는 호스트 이름에 퓨니코드가 필요합니다.
호스트 이름에서 백분율 인코딩을 사용할 수 없는 이유 — DNS 레이블, 허용되는 문자 및 길이 제한
점으로 구분된 호스트 이름의 개별 세그먼트인 DNS 라벨에는 매우 엄격한 규칙이 있습니다. ASCII 문자, 숫자, 하이픈, 밑줄만 포함할 수 있습니다. 길이 제한이 있습니다. 각 레이블은 최대 63 옥텟일 수 있으며 전체 호스트 이름은 255 옥텟을 초과할 수 없습니다. 이는 국제 도메인 이름이 개념화되기 전 수십 년 전에 정의된 DNS 프로토콜 자체의 엄격한 제약 사항입니다. 결과 문자열이 더 긴 단어에 대한 레이블 제한을 초과할 가능성이 높기 때문에 퍼센트 인코딩은 호스트 이름에 대해 작동할 수 없습니다.
더 중요한 것은 DNS가 전 세계의 라우터와 서버에 의해 운영되는 글로벌 시스템이라는 것입니다. 그들 모두가 UTF-8 또는 유니코드를 이해하는 것은 아닙니다. %C3%A9와 같은 퍼센트 인코딩 문자는 여전히 3개의 ASCII 문자이므로 DNS 제약 조건에 맞습니다. 그러나 이러한 접근 방식은 모든 조회가 들어올 때 퍼센트 인코딩을 하고 나갈 때 디코딩해야 하므로 프로토콜 계층 자체에 복잡성이 추가된다는 것을 의미합니다. 특히 호스트 이름에 대해서는 더 나은 솔루션이 필요했습니다.
개요의 IDNA 및 퓨니코드 — 정성적으로 설명된 xn-- 접두사 및 부트스트링 알고리즘
애플리케이션 사양의 국제화된 도메인 이름인 IDNA는 ASCII가 아닌 도메인 이름을 DNS가 처리할 수 있는 ASCII로 인코딩하여 호스트 이름 문제를 해결합니다. 사용되는 인코딩은 퓨니코드(punycode)라고 하며, 접두사 xn-- 뒤에 부트스트링 인코딩 표현을 사용하여 유니코드 텍스트를 ASCII로 변환하는 압축 알고리즘입니다. 알고리즘은 결정적입니다. münchen은 매번 xn--mnchen-3ya가 됩니다. ASCII가 아닌 호스트 이름은 DNS 확인이 이루어지기 전에 이 방법으로 변환되어야 합니다.
xn-- 접두사는 다음 문자가 리터럴 ASCII 문자가 아니라 퓨니코드임을 DNS 및 IDNA 인식 소프트웨어에 신호로 보냅니다. example.xn--mnchen-3ya.com과 같은 도메인은 IDNA 인식 소프트웨어에서 example.münchen.com을 의미하는 것으로 이해됩니다. 퓨니코드는 ASCII 문자, 숫자, 하이픈만 사용하므로 문제 없이 DNS 라벨에 깔끔하게 맞습니다. 알고리즘은 비ASCII 정보를 이 ASCII 표현으로 압축합니다.
경로, 쿼리 및 조각은 백분율 인코딩 상태로 유지됨 — 다른 곳과 마찬가지로 UTF-8 바이트에서 %XX까지
경로, 쿼리 문자열, 조각 등 URL의 다른 모든 항목은 대신 백분율 인코딩을 사용합니다. ASCII가 아닌 문자는 먼저 UTF-8 바이트로 변환된 다음 각 바이트가 %HH로 기록됩니다. 여기서 HH는 16진수입니다. /café/ 경로는 /caf%C3%A9/.가 됩니다. 쿼리 문자열 ?name=josé는 ?name=jos%C3%A9가 됩니다. 퍼센트 인코딩은 HTTP 요청 URL, HTML 형식, API 등 웹의 모든 곳에서 표준입니다. DNS나 라우터를 통한 특별한 처리가 필요하지 않습니다.
퍼센트 인코딩을 사용하면 다른 특수 문자도 안전하게 표현할 수 있습니다. 공백은 %20이 되고, 슬래시(값 안에 나타나야 하는 경우)는 %2F가 됩니다. 이 계획은 일관되고 보편적입니다. DNS는 URL이나 퍼센트 인코딩을 이해하지 못하기 때문에 호스트 이름에는 사용되지 않습니다. ASCII 레이블만 이해합니다.
작업된 예: 두 가지가 모두 포함된 하나의 URL — 퓨니코드로 변환된 호스트, 퍼센트 인코딩된 경로, 나란히
URL "https://münchen.example/café?city=münchen". DNS 조회 전에 호스트 이름 münchen을 퓨니코드로 변환해야 합니다. https://xn--mnchen-3ya.example/café?city=münchen. 하지만 잠깐만요. 경로와 쿼리도 ASCII가 아닙니다. 그것도 변환합니다. https://xn--mnchen-3ya.example/caf%C3%A9?city=m%C3%BCnchen. 이제 호스트 이름은 퓨니코드이고 경로와 쿼리는 퍼센트 인코딩됩니다. 브라우저는 가독성을 위해 원래 유니코드 버전을 표시합니다. HTTP 요청은 인코딩된 버전.
URL 인코더 및 디코더 도구에서 ASCII가 아닌 텍스트가 포함된 경로를 붙여넣고 단일 값 모드(경로만)와 전체 주소 모드(전체 URL)를 비교합니다. 이 도구는 경로에 대한 퍼센트 인코딩 결과를 보여줍니다. 그러나 호스트 이름에는 별도의 퓨니코드 변환이 필요합니다. 대부분의 인코딩 도구는 해당 인라인을 처리하지 않으므로 도구 설명서에서 읽어보세요.
동형어 공격 및 브라우저에 때때로 퓨니코드가 표시되는 이유 - 표시 규칙 뒤에 숨은 보안 이유
악의적인 공격자는 "https://xn--80akhbyknj4f.example"(퓨니코드에서 "example.example"의 키릴어 버전)과 같이 라틴 문자와 시각적으로 동일하게 보이는 키릴 문자를 사용하여 도메인을 등록할 수 있습니다. 브라우저가 키릴 문자로 디코딩된 내용을 표시하는 경우 사용자는 차이점을 느끼지 못할 수 있습니다. 동형이의어 공격을 방지하기 위해 브라우저는 때때로 퓨니코드 버전을 디코딩하는 대신 표시합니다. 경고가 나타납니다. 이 도메인은 모두 또는 대부분 비ASCII이므로 문자를 인식하지 못할 수 있습니다.
URL 인코더 및 디코더는 보안 평가용이 아닌 인코딩 및 디코딩을 위한 도구입니다. 국제 도메인 이름으로 작업하는 경우 퓨니코드 표현이 네트워크에 표시된다는 점에 유의하세요.
여기서 다루지 않는 내용 — 퓨니코드 알고리즘을 직접 실행하거나 IDNA 2003 대 2008 차이점 실행
IDNA는 시간이 지남에 따라 여러 버전을 거쳤습니다. IDNA 2003 및 IDNA 2008은 특히 정규화 및 사양에 따라 허용되는 유니코드 문자와 관련하여 특정 극단적인 경우를 다르게 처리합니다. 일부 구형 시스템은 여전히 IDNA 2003를 사용하는 반면 다른 시스템은 더 나은 규정 준수를 위해 IDNA 2008로 마이그레이션했습니다. 여러 버전에서 호환되어야 하는 시스템을 구축하는 경우 차이점은 매우 중요합니다. 항상 시스템 요구 사항을 주의 깊게 확인하십시오.
Punycode는 부트스트링 압축을 사용합니다. 구현은 공용 언어로 존재하지만 호스트 이름 시스템으로 IDNA 정책을 확인합니다. 가정하기보다는 해상도와 디스플레이 동작을 테스트하십시오.
요약: 두 작업에 대한 두 가지 인코딩 — URL 인코더 및 디코더가 퍼센트 인코딩 부분을 처리하는 방법 및 퍼센트 인코더가 호스트 이름에 대한 잘못된 도구인 이유
DNS는 ASCII 레이블만 이해하고 엄격한 길이 및 문자 제한이 있는 오래된 프로토콜이기 때문에 호스트 이름에는 퓨니코드가 필요합니다. 경로, 쿼리 및 조각은 웹에서 보편적이고 이러한 제약이 없기 때문에 백분율 인코딩을 사용합니다. 완전히 다른 두 가지 문제에 대한 두 가지 별도의 솔루션입니다. ASCII가 아닌 URL을 발견하면 호스트 이름이 먼저 퓨니코드 변환을 받은 다음 나머지는 퍼센트 인코딩을 사용합니다.
대부분의 개발 작업에서 프레임워크나 라이브러리는 백그라운드에서 이 변환을 자동으로 처리합니다. 그러나 두 가지 다른 인코딩이 존재하는 이유를 이해하면 국제 URL을 디버깅하거나 자체 URL 처리 코드를 성공적으로 구현할 때 혼란을 방지할 수 있습니다.