1 poin oleh GN⁺ 4 jam lalu | 1 komentar | Bagikan ke WhatsApp
  • 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

 
GN⁺ 4 jam lalu
Komentar Lobste.rs
  • Kesimpulan seperti TL;DR: komputer adalah sebuah kesalahan terasa seperti membuang bayi bersama air mandinya
    Secara 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
    • Judulnya memang sangat dramatis dan clickbait
      Meski begitu, inti pesannya terasa masuk akal. Situasi seperti ini sendiri cukup konyol
  • Tidak bisa menangani alamat IPv6 lingkup link-local dengan benar di URL memang sebuah kesalahan
    Namun, kasus yang tidak bisa menangani alamat IPv6 link-local dengan baik juga bukan sesuatu yang jarang
    • Sebaliknya, menangani zone pada alamat IPv6 di dalam URL memang menambah kompleksitas cukup besar
      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. Disayangkan
  • Jika itu pustaka atau implementasi yang kompatibel dengan RFC 3986, masalah ini memang akan muncul. Karena spesifikasi mendefinisikan urutan percent-encoding seperti ini
    pct-encoded = "%" HEXDIG HEXDIG
    Di sini HEXDIG didefinisikan sebagai [a-fA-F], sehingga %et diparse sebagai urutan yang tidak valid
    Spesifikasi 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 sekali
    Jadi memang menjengkelkan, tetapi dalam praktiknya saya rasa ini sulit disebut bug
  • Saya kurang paham kenapa menulis % 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-nya
    Bukan hal baru jika net/url dan net/http di Go berbenturan dengan RFC URL. Keberadaan net/url.URL.Path khususnya, serta penggunaannya di net/http, cukup menyebalkan karena merusak %2F. net/http.Redirect juga memakai path.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