Công cụ dành cho nhà phát triển · Bộ mã hóa và giải mã URL
Punycode so với mã hóa phần trăm: cách xử lý các miền và đường dẫn không phải ASCII
· Lý lịch
quốc tế hóa mã trừng phạt url-encoding
URL có tên máy chủ không phải ASCII và đường dẫn không phải ASCII sử dụng hai cách mã hóa hoàn toàn khác nhau. Bài đăng này giải thích IDNA và punycode cho máy chủ, mã hóa phần trăm cho mọi thứ khác và lý do tồn tại sự phân chia.
Địa chỉ hiển thị 'münchen.example' trong một trình duyệt và 'xn--mnchen-3ya.example' trong một trình duyệt khác — một máy chủ, hai cách viết
Thành phố München xuất hiện trong tên miền của Đức. Trong thanh địa chỉ của trình duyệt, bạn có thể thấy münchen.example được hiển thị bình thường. Sao chép địa chỉ từ một ứng dụng khác và nó xuất hiện dưới dạng xn--mnchen-3ya.example, một chuỗi chỉ ASCII trông không giống văn bản tiếng Đức. Một URL, hai cách viết, cả hai đều hoàn toàn hợp lệ. Điều đó cũng không sai; chúng đại diện cho cùng một miền bằng cách sử dụng các bộ ký tự hoàn toàn khác nhau. Sự khác biệt phản ánh hạn chế cơ bản về cách DNS hoạt động và cách cơ sở hạ tầng Internet mong muốn tên máy chủ được truyền đi.
Các đoạn đường dẫn như /café/ cần mã hóa nhưng sử dụng hệ thống khác. Non-ASCII é trở thành %C3%A9 trong đường dẫn. Tại sao lại có sự khác biệt? Các ràng buộc DNS yêu cầu mã trừng phạt cho tên máy chủ.
Tại sao tên máy chủ không thể sử dụng mã hóa phần trăm — nhãn DNS, ký tự được phép và giới hạn độ dài
Nhãn DNS, các phân đoạn riêng lẻ của tên máy chủ được phân tách bằng dấu chấm, có các quy tắc rất nghiêm ngặt. Chúng chỉ có thể chứa ASCII chữ cái, chữ số, dấu gạch nối và dấu gạch dưới. Chúng có giới hạn độ dài: mỗi nhãn có thể có tối đa 63 octet và tên máy chủ đầy đủ không được vượt quá 255 octet. Đây là những hạn chế cứng rắn từ chính giao thức DNS, được xác định cách đây hàng thập kỷ trước khi tên miền quốc tế thậm chí còn là một khái niệm. Mã hóa phần trăm không thể hoạt động đối với tên máy chủ vì chuỗi kết quả có thể vượt quá giới hạn nhãn đối với các từ dài hơn.
Quan trọng hơn, DNS là một hệ thống toàn cầu được vận hành bởi các bộ định tuyến và máy chủ trên toàn thế giới. Không phải tất cả đều hiểu UTF-8 hoặc Unicode. Ký tự được mã hóa phần trăm như %C3%A9 vẫn có ba ASCII ký tự, do đó, nó phù hợp với các ràng buộc DNS. Nhưng cách tiếp cận đó có nghĩa là mọi tra cứu đều phải mã hóa phần trăm trên đường vào và giải mã trên đường ra, làm tăng thêm độ phức tạp cho chính lớp giao thức. Một giải pháp tốt hơn là cần thiết cho tên máy chủ.
IDNA và punycode trong phác thảo — tiền tố xn-- và thuật toán chuỗi khởi động, được mô tả một cách định tính
IDNA, đặc tả Tên miền quốc tế hóa trong ứng dụng, giải quyết vấn đề tên máy chủ bằng cách mã hóa các tên miền không phải ASCII thành ASCII mà DNS có thể xử lý. Mã hóa được sử dụng được gọi là punycode, một thuật toán nén biến văn bản Unicode thành ASCII bằng cách sử dụng tiền tố xn-- theo sau là biểu diễn được mã hóa chuỗi khởi động. Thuật toán mang tính quyết định: münchen luôn trở thành xn--mnchen-3ya mỗi lần. Mọi tên máy chủ không phải ASCII đều phải được chuyển đổi theo cách này trước khi quá trình giải quyết DNS có thể xảy ra.
Tiền tố xn-- báo hiệu cho DNS và cho phần mềm IDNA nhận biết rằng các ký tự sau đây là mã trừng phạt, không phải chữ cái ASCII theo nghĩa đen. Một miền như example.xn--mnchen-3ya.com được hiểu là example.münchen.com bởi phần mềm nhận biết IDNA. Punycode chỉ sử dụng ASCII chữ cái, chữ số và dấu gạch nối, do đó, nó hoàn toàn phù hợp với nhãn DNS mà không gặp vấn đề gì. Thuật toán nén thông tin không phải ASCII vào biểu diễn ASCII này.
Đường dẫn, truy vấn và đoạn vẫn được mã hóa phần trăm — UTF-8 byte đến %XX, như ở nơi khác
Mọi thứ khác trong URL—đường dẫn, chuỗi truy vấn, đoạn—sử dụng mã hóa phần trăm thay thế. Ký tự không phải ASCII trước tiên được chuyển đổi thành UTF-8 byte, sau đó mỗi byte được viết dưới dạng %HH trong đó HH là thập lục phân. Đường dẫn /café/ trở thành /caf%C3%A9/. Chuỗi truy vấn ?name=josé trở thành ?name=jos%C3%A9. Mã hóa phần trăm là tiêu chuẩn ở mọi nơi trên web: trong HTTP URL yêu cầu, trong biểu mẫu HTML, trong API. Nó không cần xử lý đặc biệt bởi DNS hoặc bộ định tuyến.
Mã hóa phần trăm cũng cho phép các ký tự đặc biệt khác được thể hiện một cách an toàn. Khoảng trắng sẽ trở thành %20, dấu gạch chéo (nếu nó phải xuất hiện bên trong một giá trị) sẽ trở thành %2F, v.v. Đề án này là nhất quán và phổ quát. Nó không được sử dụng cho tên máy chủ vì DNS không hiểu URL hoặc mã hóa phần trăm; nó chỉ hiểu nhãn ASCII.
Ví dụ đã hoạt động: một URL với cả hai — máy chủ đã chuyển đổi thành punycode, đường dẫn được mã hóa phần trăm, cạnh nhau
Lấy URL "https://münchen.example/café?city=münchen". Tên máy chủ münchen phải được chuyển đổi thành punycode trước khi DNS tra cứu: https://xn--mnchen-3ya.example/café?city=münchen. Nhưng chờ đã—đường dẫn và truy vấn cũng không có ASCII. Chuyển đổi cả những tên đó: https://xn--mnchen-3ya.example/caf%C3%A9?city=m%C3%BCnchen. Bây giờ tên máy chủ là punycode, đường dẫn và truy vấn được mã hóa phần trăm. Một trình duyệt hiển thị Unicode gốc phiên bản dễ đọc; yêu cầu HTTP mang phiên bản được mã hóa.
Trong công cụ mã hóa & giải mã URL, hãy dán một đường dẫn chứa văn bản không phải ASCII và so sánh chế độ một giá trị (chỉ đường dẫn) với chế độ toàn bộ địa chỉ (đầy đủ URL). Công cụ này hiển thị cho bạn kết quả được mã hóa phần trăm cho đường dẫn. Tuy nhiên, tên máy chủ yêu cầu chuyển đổi mã trừng phạt riêng biệt; hầu hết các công cụ mã hóa không xử lý nội tuyến đó, vì vậy hãy đọc nó từ tài liệu công cụ.
Các cuộc tấn công đồng âm và tại sao các trình duyệt đôi khi hiển thị punycode - lý do bảo mật đằng sau các quy tắc hiển thị
Kẻ độc hại có thể đăng ký miền bằng cách sử dụng các chữ cái Cyrillic trông giống hệt với các chữ cái Latinh, như "https://xn--80akhbyknj4f.example" (một phiên bản Cyrillic của "example.example" trong punycode). Nếu trình duyệt hiển thị nó được giải mã dưới dạng văn bản Cyrillic, người dùng có thể không nhận thấy sự khác biệt. Để ngăn chặn các cuộc tấn công đồng âm, đôi khi các trình duyệt hiển thị phiên bản mã trừng phạt thay vì giải mã nó. Một cảnh báo xuất hiện: miền này tất cả hoặc hầu như không phải-ASCII và bạn có thể không nhận ra các ký tự.
Bộ mã hóa và giải mã URL là công cụ để mã hóa và giải mã, không phải để đánh giá bảo mật. Nếu bạn đang làm việc với các tên miền quốc tế, hãy lưu ý rằng cách trình bày mã trừng phạt là những gì mạng nhìn thấy.
Điều này không bao gồm những gì — chạy thuật toán punycode bằng tay hoặc sự khác biệt IDNA 2003 so với 2008
IDNA đã trải qua nhiều phiên bản theo thời gian: IDNA 2003 và IDNA 2008 xử lý một số trường hợp đặc biệt theo cách khác nhau, đặc biệt là về chuẩn hóa và ký tự Unicode nào được đặc tả cho phép. Một số hệ thống cũ vẫn sử dụng IDNA 2003 trong khi những hệ thống khác đã chuyển sang IDNA 2008 để tuân thủ tốt hơn. Sự khác biệt sẽ rất quan trọng nếu bạn đang xây dựng các hệ thống phải tương thích trên nhiều phiên bản. Luôn luôn kiểm tra các yêu cầu hệ thống của bạn một cách cẩn thận.
Punycode sử dụng tính năng nén chuỗi khởi động. Việc triển khai tồn tại bằng các ngôn ngữ phổ biến nhưng hãy xác minh chính sách IDNA bằng hệ thống tên máy chủ của bạn. Kiểm tra độ phân giải và hành vi hiển thị thay vì giả định.
Bài học rút ra: hai cách mã hóa cho hai công việc — cách bộ mã hóa và giải mã URL xử lý các phần được mã hóa phần trăm và tại sao bộ mã hóa phần trăm lại là công cụ sai cho tên máy chủ
Tên máy chủ cần punycode vì DNS là giao thức cũ chỉ hiểu nhãn ASCII và có các ràng buộc nghiêm ngặt về độ dài và ký tự. Đường dẫn, truy vấn và đoạn sử dụng mã hóa phần trăm vì nó phổ biến trên web và không có những ràng buộc đó. Chúng là hai giải pháp riêng biệt cho hai vấn đề hoàn toàn khác nhau. Khi bạn gặp phải non-ASCII URL, tên máy chủ sẽ được chuyển đổi mã trừng phạt trước tiên, sau đó phần còn lại sử dụng mã hóa phần trăm.
Đối với hầu hết công việc phát triển, khung hoặc thư viện của bạn tự động xử lý chuyển đổi này ở hậu trường. Tuy nhiên, việc hiểu lý do tồn tại hai cách mã hóa khác nhau sẽ ngăn ngừa sự nhầm lẫn khi gỡ lỗi các URL quốc tế hoặc triển khai thành công mã xử lý URL của riêng bạn.