- Zone IPv6 adalah notasi untuk membedakan antarmuka tujuan seperti
fe80::4%eth0 saat beberapa antarmuka menggunakan cakupan link-local fe80:: yang sama
- Dalam URL, alamat IPv6 dibungkus seperti
[fe80::4]:80 untuk membedakan port dari tanda titik dua, dan jika zone ikut disertakan maka notasi tanda kurung siku menjadi berbentuk [fe80::4%eth0]:80
net/url milik Go menafsirkan ]:80 sebagai escape URL %et yang salah, sehingga memunculkan error invalid URL escape
- RFC 6874 mendefinisikan literal IPv6 dengan zone sebagai
IPv6address "%25" ZoneID, sehingga di dalam URL, % harus di-percent-encode menjadi %25
- Jika Anubis ingin menunjuk ke alamat zone IPv6, notasi ini harus digunakan, dan kasus ini tetap menjadi edge case yang juga melibatkan kompatibilitas origin dan library seperti pada isu browser·nginx·Requests
Benturan antara zone IPv6 dan sintaks URL
- Alamat link-local IPv6 dapat berada dalam rentang
fe80::whatever pada tiap antarmuka, jadi ketika ada dua antarmuka jaringan, penggunaan scope/zone IPv6) diperlukan untuk membedakan tujuan fe80::4
- Format nilai zone berbeda-beda menurut sistem operasi; Linux menggunakan nama antarmuka, sedangkan Windows menggunakan ID antarmuka
- Dalam contoh,
eth0 adalah nama perangkat Ethernet, dan alamatnya dinyatakan seperti berikut
fe80::4%eth0
- Host dan port biasanya dipisahkan dengan titik dua, tetapi alamat IPv6 juga memakai titik dua untuk memisahkan grup heksadesimal, sehingga
fe80::4 dengan port 80 harus dibungkus dengan tanda kurung siku seperti berikut
[fe80::4]:80
- Jika zone ikut ditambahkan, formatnya menjadi berikut
[fe80::4%eth0]:80
- Jika ini dimasukkan langsung ke hostname URL sebagai
http://[fe80::4%eth0]:80, Go net/url akan salah menafsirkan %et sebagai escape URL yang tidak valid dan gagal memprosesnya
panic: parse "http://[fe80::4%eth0]:80": invalid URL escape "%et"
Solusi menurut standar dan masalah yang tersisa
- Nilai yang tidak sesuai dengan sintaks URL harus menggunakan percent-encoding;
%20 dalam URL adalah contoh pengodean untuk spasi ASCII yang tidak valid di dalam URL
- Karena
% pada zone IPv6 juga harus diencode, di Go harus ditulis seperti http://[fe80::4%25eth0]:80, sehingga hasil Hostname() akan menjadi fe80::4%eth0
- RFC 9844 memberikan panduan untuk menangani zone IPv6 di antarmuka pengguna, dan RFC 6874 mendefinisikan sintaks literal IPv6 dengan zone di dalam URL sebagai berikut
IP-literal = "[" ( IPv6address / IPv6addrz / IPvFuture ) "]"
ZoneID = 1*( unreserved / pct-encoded )
IPv6addrz = IPv6address "%25" ZoneID
- Edge case yang sama juga muncul pada tiket nginx, isu Requests, dan draf BCP HTTP link-local URI
- Browser saat ini tidak mendukung zone IPv6 karena hal itu merusak konsep “origin” yang dipakai dalam banyak perilaku yang rumit; draf tersebut adalah upaya untuk mendefinisikan origin zone IPv6 agar bisa digunakan browser
- Jika Anubis ingin menunjuk ke alamat zone IPv6,
% harus di-percent-encode, dan di bawah kebijakan untuk tidak melakukan fork pada library standar Go, UX buruk dari edge case ini harus diterima
1 komentar
Komentar Lobste.rs
TL;DR: komputer adalah sebuah kesalahanterasa seperti membuang bayi bersama air mandinyaSecara harfiah, ini seperti logika penjahat anime ala Trigun: karena manusia bisa melakukan kejahatan yang mengerikan, maka semua manusia harus dihapuskan
Memang ini ungkapan bercampur bercanda, tapi tetap menarik, dan rencananya akan saya jadikan topik presentasi berikutnya yang sedang saya siapkan
Meski begitu, inti pesannya terasa masuk akal. Situasi seperti ini sendiri cukup konyol
Namun, kasus yang tidak bisa menangani alamat IPv6 link-local dengan baik juga bukan sesuatu yang jarang
Sekarang
%memiliki makna berbeda hanya di bagian host URL, dan itu pun hanya ketika host tersebut adalah alamat IPv6 dan berada di dalam[...]Tata bahasanya mungkin tetap tidak sepenuhnya ambigu, tetapi itu bukan poin utamanya. Semakin banyak kasus pengecualian seperti ini, semakin besar kemungkinan parser URL melewatkan pengecualian tertentu, dan dari perbedaan antar parser, bug kotor atau masalah keamanan jadi lebih mudah menyelinap masuk
Secara pribadi saya lebih memilih URL menangani zone IPv6, tetapi karena dulu pernah ada pedoman bahwa
%harus di-URL-encode, jika sekarang dibalik maka ambiguitas nyata memang akan muncul. Disayangkanpct-encoded = "%" HEXDIG HEXDIGDi sini
HEXDIGdidefinisikan sebagai[a-fA-F], sehingga%etdiparse sebagai urutan yang tidak validSpesifikasi juga mengatakan bahwa karakter
%digunakan sebagai penanda oktet yang di-percent-encode, jadi jika ingin dipakai sebagai data di dalam URI, karakter itu harus di-percent-encode menjadi%25. Jika string yang sudah didekode didekode lagi, oktet data persen bisa disalahartikan sebagai awal percent-encoding, dan jika string yang sudah di-encode di-encode lagi, masalah kebalikannya juga bisa terjadi, sehingga implementasi tidak boleh meng-encode atau mendekode string yang sama lebih dari sekaliJadi memang menjengkelkan, tetapi dalam praktiknya saya rasa ini sulit disebut bug
%secara langsung pada alamat yang memiliki zone dianggap begitu buruk. Karakter yang di-encode memang diizinkan bahkan pada bagian host, dan jika%dipakai apa adanya pada alamat zone, ambiguitas memang muncul%sendiri bukan karakter yang tidak direservasi, jadi memang benar untuk meng-percent-encode-nyaBukan hal baru jika
net/urldannet/httpdi Go berbenturan dengan RFC URL. Keberadaannet/url.URL.Pathkhususnya, serta penggunaannya dinet/http, cukup menyebalkan karena merusak%2F.net/http.Redirectjuga memakaipath.Clean, sehingga//salah dilipat menjadi/Ada banyak alasan untuk ingin mem-fork bagian pustaka standar Go yang menangani URL, atau mengusulkan sesuatu seperti
net/url/v2. Namun dari yang terlihat di tulisan ini, penanganan alamat zone IPv6 di Go tampak masuk akal dan cenderung benar