1 puan yazan GN⁺ 10 시간 전 | 1 yorum | WhatsApp'ta paylaş
  • Anubis, web sitesi koruması için proof-of-work yaklaşımını SHA-256'nın ötesine taşırken, istemci ve sunucunun aynı WebAssembly doğrulama mantığını çalıştıracağı şekilde tasarlanıyor
  • WebAssembly'nin kapalı olduğu ortamları da dışlamamak için JavaScript yeniden derleme yolu hazırlandı; ancak bu yol WebAssembly'den daha yavaş ve JIT de kapalıysa daha da yavaş olabilir
  • Linux dağıtımlarındaki wasm2js eski kaldığı için Homebrew sürümüyle çıktılar farklılaştı; yeniden üretilebilir derlemeler için wasi-sdk ile derlenmiş wasm2js paketle birlikte sunulmaya başlandı
  • C/C++ derlemelerinde __DATE__, __TIME__, $PATH içindeki wasm-opt ve istisna işleme kodundaki işaretçi sırası yüzünden aynı girdide bile bayt düzeyinde çıktı değişebilir
  • Nihai uygulama, --no-wasm-opt, setarch --addr-no-randomize, x86_64 ve arm64 için SHA-256 doğrulaması ve CI yeniden derleme kontrolleriyle mimari içi determinizm sağlıyor

Anubis'in WebAssembly proof-of-work'ü ve JavaScript yedek yolu

  • Anubis, yöneticilerin web sitesi korumasında SHA-256 dışında bir proof-of-work yöntemi kullanabilmesi için WebAssembly tabanlı proof-of-work doğrulaması eklemeyi planlıyor
  • Temel hedef, doğrulama mantığını istemci ve sunucu için ayrı ayrı uygulamak yerine tek bir yerde tanımlamak
    • İstemci ve sunucu, doğrulama mantığını çalıştırmak için aynı WebAssembly'ye bağlanıyor
    • Her iki tarafın da lockstep içinde çalıştığını doğrulayan bir yapı hedefleniyor
  • WebAssembly'nin kapalı olduğu istemciler de hesaba katılıyor
    • Kullanıcıları fiilen web sitesinden dışlamak istenmiyor
    • Anubis, kullanıcı deneyimi, yönetici deneyimi ve geliştirici deneyimi arasında denge kurmak zorunda
  • Seçilen geçici çözüm, WebAssembly'yi yeniden JavaScript'e derlemek
    • İlham kaynağı The Birth and Death of JavaScript
    • Ortaya çıkan JavaScript, eşdeğer WebAssembly'den daha yavaş
    • WebAssembly devre dışı bırakıldığında, JavaScript JIT'in de birlikte kapanabildiği durumlar var; bu da daha fazla yavaşlamaya yol açabiliyor
    • Düşük donanımlı sistemlerde bunun mevcut JavaScript'ten daha verimli olup olmadığı için ek araştırma gerekiyor

wasm2js neden paketlenmek zorunda kaldı

  • Gerekli araç, binaryen projesindeki wasm2js
  • wasm2js, Linux dağıtımlarında paket olarak bulunuyor; ancak dağıtım sürümü eski kaldığı için geliştirme ortamındaki Homebrew sürümüyle aynı çıktıyı üretemedi
  • Yeniden üretilebilir derlemeler için çıktının deterministik olması şart
    • Anubis deposuna commit edilen wasm2js ikilisine kullanıcıların ve paketleyicilerin güvenebilmesi için, aynı sürümü kendileri de derleyip aynı baytları elde edebilmesi gerekiyor
    • Mümkünse farklı kişilerin makinelerinde de aynı baytlar çıkmalı
  • Bunun için wasm2js'nin, wasi-sdk ile WebAssembly hedefi için derlenmiş bir kopyası depoya dahil ediliyor

C/C++ derlemelerinde yeniden üretilebilirliğin kolayca bozulduğu noktalar

  • Aynı kaynak baytları ve aynı girdi verilse bile derleyici çıktısı her zaman aynı baytları üretmeyebilir
  • C/C++ tarafında yalnızca __DATE__ ve __TIME__ gibi yerleşik makrolar bile deterministik olmayan çıktıya neden olabilir
    • Örnek hello.cpp, derleme anındaki tarih ve saati yazdıracak şekilde hazırlanmış
    • Bir derleme Jun 18 2026 00:00:59, bir diğeri ise Jun 18 2026 00:01:11 çıktısı verdi
    • Kaynak kod aynı baytlardı, ancak derleyici çıktısı farklıydı
  • Küçük ölçekli bir derleyici teorik olarak deterministik olabilir; ancak gerçek dünyadaki derleyicilerde çok daha karmaşık değişkenler bulunuyor

Clang'ın $PATH içindeki wasm-opt'u sessizce çalıştırması sorunu

  • binaryen, wasm2js dışında WebAssembly derleyici çıktısını optimize eden wasm-opt aracını da içeriyor
  • Clang, derleme sırasında wasm-opt'u shell out ile çalıştırıyor
    • Normalde bu, performans iyileştirmesi için makul bir davranış
    • Ancak bu vakada, $PATH içindeki wasm-opt sürüm farkı yeniden üretilebilirliği bozdu
  • DGX Spark üzerindeki wasm-opt, /usr/bin/wasm-opt sürüm 108'di; iş istasyonundaki Homebrew wasm-opt ise sürüm 130'du
  • wasi-sdk ve binaryen, WebAssembly Exceptions extension'a dayanıyor
    • Can I use verisine göre tarayıcı kullanıcılarının %93,86'sı bunu destekleyen bir tarayıcı motoru kullanıyor
    • C++, istisnaların yoğun kullanıldığı bir dil olduğu için WebAssembly'nin yerel istisna işleme desteği boilerplate'i azaltabiliyor
  • wasmtime ve wazero'da istisna desteğinin açıkça etkinleştirilmesi gerekiyor
    • wasmtime için -W exceptions=y verilebiliyor
    • wazero için özel bir runner harness gerekiyor
  • arm makinedeki eski wasm-opt, istisna işleme komutlarıyla karşılaşınca kapanıyor ve derleme başarısız oluyordu
  • Bağlama aşamasına --no-wasm-opt verilerek bu yeniden üretilemeyen yol ortadan kaldırıldı

Adres yerleşiminin istisna işleme kodu üretimine etkisi

  • Kullanılan Clang sürümü, wasm2js derleme sürecindeki istisna işleme yolunda adreslere duyarlı kod üretimi sergiledi
  • Ham işaretçi değerleri, bazı try_table bloklarının çıktı sırasını etkiliyordu
    • Her derlemede yaklaşık 29 baytlık fark oluşuyordu
    • Hesaplamanın kendisi neredeyse aynı olsa da bayt sırası ve catch referansları değişiyordu
  • arm64 makinede aynı sabit sürüm wasm2js derlense bile işaretçi yineleme sırası iş istasyonundan farklı olduğu için aynı sorun ortaya çıktı
  • Geçici çözüm iki parçadan oluşuyor
    • setarch --addr-no-randomize ile ilgili derlemede adres alanı rastgeleleştirmesi kapatılıyor
    • Güvenilen makinelerde x86_64 ve arm64 için ayrı ayrı known-good SHA-256 checksum'ları üretiliyor
  • CI, ./utils/wasm/wasm2js içinde ./build.sh çalıştırdıktan sonra checksum'ı doğruluyor
    • shasums.x86_64 ile eşleşirse x86_64 checksum doğrulaması geçmiş sayılıyor
    • shasums.arm64 ile eşleşirse arm64 checksum doğrulaması geçmiş sayılıyor
    • Hiçbiri eşleşmezse wasm-opt_130.wasm ve wasm2js_130.wasm için SHA-256 yazdırılıyor ve işlem başarısız oluyor
  • Bu CI işi hem x86_64 hem de arm64 host'larda çalışıyor
  • Tüm host'lar arasında yeniden üretilebilirlik henüz sağlanmış değil; sorun upstream LLVM hatası olarak duruyor
  • Mevcut durumda en azından aynı mimari içinde derlemeler deterministik çalışıyor

1 yorum

 
Lobste.rs görüşleri
  • clangın gizlice $PATH içindeki wasm-optu çalıştırdığını ilk kez öğrendim ve bunun gerçekten saçma olduğunu düşündüm
    Bunun zig ccyi de etkileyip etkilemediğini kontrol ettim; neyse ki yalnızca clang linker driver olarak kullanıldığında çalışıyormuş, yani durum bu değilmiş
    clang adres yerleşimine bağlı olarak sıralama belirliyorsa, ben bunu şahsen bir bug sayarım ve en güncel sürümlerde de yeniden üretilebiliyorsa bu şekilde rapor ederdim

    • Xe başka bir yerde bunu upstream'e bildireceğini söylemişti ve bu kesinlikle bir LLVM determinizm bug'ı
      Bu tür sorunları ortadan kaldırma çabası yıllardır sürüyor
    • Windows'ta clang.exeyi güvenilir biçimde bir cross-compiler olarak kullanmaya çalışırsanız daha da çıldırtıcı oluyor
      clang, native sistem için derleme yapacağını varsaydığı yaklaşık 500 farklı yola sahip
  • Eleştirmek istemiyorum; bunun açık kaynak olduğunu ve OP'nin popüler bir hizmeti ücretsiz sunduğunu takdir ediyorum
    Yine de webin bu hale gelmesinden gerçekten nefret ediyorum. Artık bir web sitesine her girdiğimde Anubis yükleme sayfasının pat diye çıkması sıradanlaştı; popüler her sitede proof-of-work splash screen gösteren bir web isteyip istemediğimizden emin değilim
    AI crawler'lar durmadan akın ederken alternatifin ne olduğunu da bilmiyorum ama proof-of-work'ün gerçekten AI crawler'ları engellediğine dair kanıt olup olmadığını da merak ediyorum. Bunların devasa fonları var ve zaten bir sayfayı okumak için çok daha fazla hesaplama yapıyorlar; bu yüzden proof-of-work çözme maliyeti çok küçük görünüyor

    • Proof-of-work'ün AI crawler'ları engellediğine dair kanıt var. Bununla ilgili yazılar burada da birkaç kez paylaşıldı
      Anubis pilotunda bu, istenmeyen trafik için açıkça etkili bir caydırıcı olmuş ve neredeyse varsayılan sayılabilecek kurallarla üç uygulamaya gelen isteklerin yaklaşık %90'ını sürekli engellemiş. DDR %71.0, ArcLight %94.6, Catalog %92.4 olmuş
      30 Mayıs'ta bot trafiği patladı ve 3 Haziran'da Anubis uygulanana kadar Catalog fiilen hizmet veremez hale geldi; 1 Haziran'daki zirvede 2,1 milyon benzersiz IP'den 3,4 milyon HTTP isteği geldi ve sayfa yükleme süresi 70 saniyenin üstüne çıktı. 4 Haziran'da Anubis uygulandıktan sonra hizmet yeniden kullanıcılar için erişilebilir oldu; uygulamanın işlediği toplam istek sayısı 125 bin, sayfa yükleme süresi ise 2,12 saniye oldu
      https://lobste.rs/s/ncyfcp/anubis_pilot_project_report_june_2025
      Başka bir vakada da Anubis dağıtılır dağıtılmaz sorun çözülmüş, izleme ekranında tam zaman görülebilmiş ve sonrasında tek bir uyarı bile gelmemiş. Saldırı sürüyormuş ama sunucu yükü en düşük düzeyde kalmış; Anubis'in yalnızca AI scraper engellemesi değil, aynı zamanda DDoS koruması olarak da çalıştığı düşünülüyor
      https://lobste.rs/s/67ijih/day_anubis_saved_our_websites_from_ddos
    • Mutlaka proof-of-work gerekmez. https://shithub.us üzerinde durumsuz, JS-free bir engelleyici dağıttım; scraper'ların bunu aşması, en az basit bir proof-of-work kadar maliyetli olabilir
      https://orib.dev/tmp/bandwidth.png
    • Crawler'ların tam olarak ne olduğu ve ne amaçla yapıldığı kimse tarafından bilinmiyor ama birçoğu oldukça tembel olduğu için alışılmadık işlemleri pek iyi başaramıyor gibi görünüyor
      Bazı insanlar sadece meta refresh etiketiyle ya da tıklanması gereken bir butonla bile onları engelliyor. Yani Anubis işe yarıyor ama mesele proof-of-work'ün kendisi değil, beklenmedik davranış olması
    • Böyle bir web kesinlikle istemiyorum
      JavaScript'i kapalı bir tarayıcıyla web kullandığım dönemlerden bile daha can sıkıcı hale geliyor. Webin sadece belge odaklı kalmasını isterdim ama artık her yerde Cloudflare, Anubis ve captcha geçitlerinden geçmek gerekiyor
    • Herhangi bir APT'nin Anubis yanıt hesaplamasını hızlandırabileceği daha en başından biliniyordu. Geçen yılki proof of concept'te de bu yazıyordu
      Botların her zaman WAF'ı aşmanın bir yolunu bulacağı, gerçek kullanıcılarınsa yükleme ekranında CPU döngülerini boşa harcayacağı söyleniyordu
  • Üzücü ama şaşırtıcı değil. Compiler toolchain'leri, “yerel bağlam zaten doğru olmak zorunda” türünden saçma örtük bağımlılıklara uzun bir geçmiş boyunca yaslandı
    Yine de LLVM bu tür bağımlılıkları ortadan kaldırmada öncü olmuştu; bu yüzden clang'da bunu görmek garip geliyor. Örneğin bunun sayesinde Rust compiler, ayrı bir cross-compiler kavramı olmadan da mümkün hale geldi
    Bunu, mevcut build araçlarına yaslanmadan bir işletim sistemini bootstrap etmeye çalıştığınız anda hemen görüyorsunuz. Bir kernel oluşturmak, o kernel için libc ve compiler üretip çalıştırmak, ardından yeni OS üzerinde her şeyi baştan derlemek; bunların hepsi örtük varsayımlarla dolu, gülünç derecede karmaşık ve hassas bir süreç
    Bu nadir bir sorun alanı olduğu için çoğunlukla yalnızca OS ve compiler geliştiricilerine dokunuyor; bu yüzden de iyi araçlar ya da best practice'ler neredeyse yok ve her compiler+OS kombinasyonunda tüm sistemi gerçekten anlayan kişi sayısı dünya genelinde belki 5'tir

    • Bunu duyunca şaşırdım. LLVM'nin, GCC'nin aksine host ile target'ı soyutlayıp cross-compilation düşünülerek tasarlandığını sanıyordum
      Zig toolchain'inin de bu yeteneklerin bir kısmını LLVM'den aldığını sanıyordum; tabii daha temiz bir ayrım için çok iş yapmış olmalarını anlıyorum. Şimdi artık LLVM kullanmıyorlar mı diye de merak ediyorum
      Ama clang'da da aynı sorun varsa, LLVM'den daha temiz bir mimari miras alınmamış mı diye düşündürüyor
  • Nix kullandığını sanıyordum; ortam değişkenliğinin en azından bir kısmını azaltmak için neden Nixten söz etmediğini ya da onu kullanmadığını merak ediyorum
    Mesela $PATH içindeki wasm-opt sorunu gibi bir şey Nix ile hafifletilebilirmiş gibi geliyor; kullandı da ben mi kaçırdım?

  • Safça, wasm'i asm.js'ye taşımanın “kolay” olacağını düşünmüştüm; bugün yeni bir şey öğrenmiş oldum

    • Ben de öyle sanıyordum. Ne yazık ki gerçekte beklediğinizden çok daha karmaşık
  • Blog başlığı clickbait gibi ama içerik iyi
    Clickbait'ten gerçekten nefret ediyorum