1 puan yazan GN⁺ 4 시간 전 | 1 yorum | WhatsApp'ta paylaş
  • IPv6 zone, birden fazla arayüz aynı fe80:: link-local aralığını kullandığında fe80::4%eth0 örneğinde olduğu gibi hedef arayüzü ayırt etmeye yarayan bir gösterimdir
  • URL'de IPv6 adresleri, port ile iki noktaları ayırmak için [fe80::4]:80 biçiminde köşeli parantez içine alınır; zone da eklenince köşeli parantez gösterimi [fe80::4%eth0]:80 biçimine dönüşür
  • Go'nun net/url paketi ]:80 bölümünü %et şeklinde hatalı bir URL escape olarak yorumlayıp invalid URL escape hatası verir
  • RFC 6874, zone içeren IPv6 literal'ini IPv6address "%25" ZoneID olarak tanımladığı için URL içinde % karakteri %25 olarak percent-encode edilmelidir
  • Anubis'in IPv6 zone adresini gösterebilmesi için bu gösterimi kullanması gerekir; ancak bu durum, tarayıcı, nginx ve Requests ile ilgili sorunlarda da görüldüğü gibi origin ve kütüphane uyumluluğunu etkileyen bir uç durum olarak kalır

IPv6 zone ile URL sözdiziminin çakışması

  • IPv6'nın link-local adresleri her arayüzde fe80::whatever aralığında bulunabilir; bu yüzden iki ağ arayüzü olduğunda fe80::4 hedefini ayırt etmek için IPv6 scope/zone) kullanmak gerekir
  • zone değerinin biçimi işletim sistemine göre değişir; Linux'ta arayüz adı, Windows'ta ise arayüz kimliği kullanılır
  • Örnekte eth0 Ethernet aygıtının adıdır ve adres şu şekilde gösterilir
fe80::4%eth0
  • Host ve port normalde iki nokta ile ayrılır, ancak IPv6 adresleri de hex gruplarını ayırmak için iki nokta kullandığından, port 80'deki fe80::4 adresi şu şekilde köşeli parantez içine alınmalıdır
[fe80::4]:80
  • zone da eklendiğinde biçim şu olur
[fe80::4%eth0]:80
  • Bunu doğrudan URL host adı içine koyan http://[fe80::4%eth0]:80, Go net/url içinde %et ifadesini geçersiz bir URL escape olarak yorumladığı için başarısız olur
panic: parse "http://[fe80::4%eth0]:80";: invalid URL escape "%et"

Standarttaki çözüm ve kalan sorunlar

  • URL sözdizimine uymayan değerler için percent-encoding kullanılmalıdır; örneğin URL içindeki %20, URL'de geçerli olmayan ASCII boşluk karakterinin kodlanmış halidir
  • IPv6 zone içindeki % karakterinin kendisi de kodlanmalıdır; bu yüzden Go'da http://[fe80::4%25eth0]:80 yazıldığında Hostname() sonucu fe80::4%eth0 olarak döner
  • RFC 9844, kullanıcı arayüzlerinde IPv6 zone kullanımına ilişkin rehber sunar; RFC 6874 ise URL'de zone içeren IPv6 literal sözdizimini şu şekilde tanımlar
IP-literal = "[" ( IPv6address / IPv6addrz / IPvFuture  ) "]"

ZoneID = 1*( unreserved / pct-encoded )

IPv6addrz = IPv6address "%25" ZoneID
  • Aynı uç durum nginx bileti, Requests sorunu ve HTTP link-local URI BCP taslağı içinde de karşımıza çıkıyor
  • Tarayıcılar şu anda IPv6 zone'u desteklemiyor; bunun nedeni, pek çok ince davranışın temelinde yer alan “origin” kavramını bozması ve söz konusu taslağın tarayıcıların bunu kullanabilmesi için IPv6'nın zone origin'ini tanımlamaya çalışması
  • Anubis'in IPv6 zone adresini gösterebilmesi için % karakterini percent-encoding ile kodlaması gerekiyor; Go standart kütüphanesini fork etmeme politikası sürdüğü sürece bu uç durumun kötü UX'ine katlanmak gerekiyor

1 yorum

 
GN⁺ 4 시간 전
Lobste.rs görüşleri
  • TL;DR: bilgisayarlar bir hataydı türü bir sonuca varmak bana biraz banyo suyuyla birlikte bebeği de atmak gibi geliyor
    Kelimenin tam anlamıyla Trigun gibi bir animedeki kötü karakter mantığına benziyor; insanlar korkunç suçlar işleyebiliyor diye tüm insanları ortadan kaldırmak gerektiğini söylemek gibi
    Şaka yollu bir ifade olduğunu biliyorum ama ilginç geldi ve şu sıralar hazırladığım bir sonraki sunumun konusu yapmayı düşünüyorum
    • Başlığın oldukça dramatik ve clickbait olduğu doğru
      Yine de ana fikre katılıyorum. Böyle bir durumun başlı başına epey gülünç olduğu hissi var
  • URL içinde link-local kapsamlı IPv6 adreslerinin düzgün işlenememesi bir hata
    Ama link-local IPv6 adreslerinin düzgün ele alınamadığı durumlar da nadir sayılmaz
    • Öte yandan URL içindeki IPv6 adreslerinde zone işlemek ciddi ölçüde karmaşıklık ekliyor
      Çünkü artık %, yalnızca URL'nin host kısmında, üstelik sadece host bir IPv6 adresiyse ve [...] içindeyse farklı bir anlam taşıyor
      Sözdizimi hâlâ belirsiz olmak zorunda değil ama asıl mesele bu değil. Bu tür istisna vakalar arttıkça URL parser'larının belirli istisnaları kaçırma olasılığı yükseliyor ve parser'lar arasındaki farklardan kirli bug'lar ya da güvenlik sorunları sızması kolaylaşıyor
      Ben şahsen URL'de IPv6 zone desteğini tercih ederim ama bir zamanlar % işaretinin URL encode edilmesi gerektiğine dair yönlendirme varken bunu şimdi geri almak gerçekten belirsizlik yaratıyor. Üzücü bir durum
  • RFC 3986 ile uyumlu bir kütüphane ya da implementasyon kullanıyorsanız bu sorunla karşılaşırsınız. Çünkü spesifikasyon percent-encoded dizileri şöyle tanımlıyor
    pct-encoded = "%" HEXDIG HEXDIG
    Burada HEXDIG, [a-fA-F] olarak tanımlandığı için %et geçersiz bir dizi olarak parse ediliyor
    Spesifikasyon ayrıca % karakterinin percent-encoded octet'lerin göstergesi olarak kullanıldığını, bu yüzden URI içinde veri olarak kullanılacaksa %25 olarak percent-encode edilmesi gerektiğini söylüyor. Zaten decode edilmiş bir string tekrar decode edilirse percent veri octet'leri, percent-encoding başlangıcı sanılabilir; zaten encode edilmiş bir string tekrar encode edilirse de bunun tersi sorun oluşabilir. Bu nedenle implementasyonların aynı string'i birden fazla kez encode ya da decode etmemesi gerektiği belirtiliyor
    O yüzden can sıkıcı olduğu doğru ama pratikte buna bug demek zor bence
  • Zone içeren adreste % karakterini doğrudan kullanmanın neden bu kadar korkunç görüldüğünü anlamıyorum. Encoded karakterlere host kısmında da izin veriliyor ve zone adresinde % işaretini olduğu gibi kullanmak belirsizlik yaratıyor
    % karakterinin kendisi unreserved bir karakter olmadığı için percent-encode edilmesi doğru yaklaşım
    Go'nun net/url ve net/http paketlerinin URL RFC'leriyle çatışması yeni bir şey değil. Özellikle net/url.URL.Path varlığı ve bunun net/http içindeki kullanımı oldukça sinir bozucu, çünkü %2F'yi bozuyor. net/http.Redirect de path.Clean kullandığı için // ifadesini hatalı biçimde / olarak sadeleştiriyor
    Go standart kütüphanesinde URL işleyen kısımları fork etmek istemek ya da net/url/v2 gibi bir şey önermek için birçok neden var. Ama bu yazıdaki kadarıyla, Go'nun IPv6 zone adresi işleme biçimi makul ve doğru görünüyor