· kaynak dev.to (home feed)
Cloudflare, Python'un varsayılan urllib User-Agent'ını engelledi ve iki ay boyunca lisans doğrulamayı bozdu
Bir Python araç geliştiricisi, Cloudflare'in kenar sunucusunun urllib'nin varsayılan User-Agent'ını hata 1010 ile sessizce reddettiğini ve çevrimiçi lisans etkinleştirmenin, bir müşteri fark edene kadar iki ay boyunca bozulduğunu anlatıyor.

Ne oldu
Ticari bir Python kod karıştırıcı aracı olan pyobfus'ün geliştiricisi, dev.to'da ürünün çevrimiçi lisans etkinleştirmesinin yaklaşık iki ay boyunca sessizce başarısız olduğunu anlattı. Gönderiye göre kayıtlardaki son başarılı çevrimiçi doğrulama 8 Temmuz'da yapılmış ve sorun ancak 12 Eylül'de, Pro lisansı satın alan bir müşterinin "Erişim reddedildi" yazan bir etkinleştirme hatası hakkında e-posta göndermesiyle ortaya çıkmış. Kısa süre içinde çevrimiçi etkinleştirmenin o ana kadar yayımlanan her sürümde, her platformda, tüm müşteriler için başarısız olduğu anlaşıldı.
Cloudflare, urllib'nin varsayılan imzasını reddetti
Lisans istemcisi Python'un urllib.request modülü üzerine inşa edilmişti ve hiçbir zaman bir User-Agent başlığı ayarlamıyordu; bu yüzden her etkinleştirme isteği urllib'nin varsayılan dizisi olan Python-urllib/3.x ile kendini tanıtıyordu. Lisans sunucusu bir Cloudflare Worker olarak çalışıyor ve geliştiriciye göre Cloudflare'in kenar katmanı bu istekleri Worker'a ulaşmadan önce reddediyor, HTTP 403 ve Cloudflare'in tarayıcı imzasına dayalı engelleme olarak belgelediği "error code: 1010" içeren düz metin bir gövdeyle yanıt veriyordu.
Yapılan testler, kuralın genel bir tarayıcı olmayan istemci yasağı değil, dar kapsamlı olduğunu gösterdi. python-requests/2.x imzasıyla gönderilen istekler, tarayıcı tarzı bir dizi taşıyan istekler ve hiç User-Agent başlığı olmayan istekler Worker'a iletildi ve normal JSON yanıtını aldı. Yalnızca urllib varsayılanı reddedildi.
Neden iki ay boyunca alarm çalmadı
Geliştirici gecikmeyi istemci tarafındaki iki eksikliğe bağlıyor. Birincisi, istemci JSON yanıtları bekliyordu; ayrıştıramadığı düz metin bir 403 aldığında gövdeyi çöpe atıyor ve müşterilerin makul biçimde geçersiz lisans anahtarı olarak okuyacağı sabit kodlanmış bir "Erişim reddedildi" mesajı gösteriyordu. İkincisi, etkinleştirme yolunu izleyen hiçbir şey yoktu. Tek başarısızlık sinyali, bir müşterinin yazmaya karar vermesiydi.
Daha derine inmek aynı koddaki eski kusurları da ortaya çıkardı. Cihaz parmak izi platform.release() içeriyordu; bu yüzden rutin bir işletim sistemi güncellemesi makineye yeni bir kimlik veriyor, yerel önbelleği geçersiz kılıyor ve üç cihaz yuvasından birini daha tüketiyordu. Parmak izi ayrıca, Python bir donanım adresi okuyamadığında rastgele bir değer döndüren uuid.getnode()'a dayanıyordu. Ayrıca, sunucu tarafındaki bir iptal, çevrimdışı önbellek yedekleme mekanizması tarafından emiliyor ve istemci lisansı geçerli olarak bildirmeye devam ediyordu.
Düzeltme neyi değiştirdi
Düzeltmeler 13 Eylül'de pyobfus 0.5.26 ile yayımlandı. İstemci artık pyobfus-license/ ile başlayan ve ardından sürüm numarası gelen bir User-Agent gönderiyor. Hata işleme, bir altyapı engellemesini lisans reddinden ayırıyor: Worker'ın beklenen JSON'unu içermeyen bir 403, ağ düzeyinde bir arıza olarak değerlendiriliyor ve müşterilerin bunun yerine kullanabileceği çevrimdışı kayıt komutunu belirten bir mesaj gösteriliyor.
Zamanlanmış bir GitHub Actions iş akışı artık gündelik iki kez, müşterilerin kullandığı aynı istemci fonksiyonuyla gerçek uç noktayı çağırarak ve hiç yayımlanmamış iyi biçimlendirilmiş bir lisans anahtarı göndererek üretim ortamını yokluyor. Yoklama, yanıt gövdesinin beklenen bilinmeyen-anahtar JSON'uyla eşleşip eşleşmediğini kontrol ediyor; böylece eksik bir rota veya bir proxy'nin 404 sayfası sağlıklı olarak geçemiyor. Geliştirici bunu, eski User-Agent'ı geri yükleyerek ve erişilemez bir uç noktaya yönlendirerek dahil çeşitli yollarla kırmızıya zorlayarak doğruladı.
Önbellek işleme de yeniden yazıldı. İmzalı bir önbellek artık cihaz kimliğindeki değişikliklerden etkilenmiyor, buna karşılık sunucudan açık bir iptal veya süre sonu yanıtı yedekleme mekanizmasını engelliyor. Cihaz kimliği, bir kez üretilip kullanıcının ana dizininde saklanan rastgele bir değer ve sunucudaki dördüncü kayıt, en son doğrulanmış cihazın yerine geçiyor. Kullanıcılar yükseltme yapana kadar zaten kurulmuş kopyalar engellenen başlığı göndermeye devam edeceği için geliştirici, sürüm çıkmadan önce etkilenen bilinen müşterilere de e-posta gönderdi.
Neden önemli
urllib'nin varsayılan User-Agent'ı internetin Python tarafındaki en yaygın imzalardan biridir ve bir araç yayımlayan geliştiricinin, bir API'nin önündeki CDN'in buna nasıl davranacağı üzerinde hiçbir kontrolü yoktur. Bu olayın gösterdiği gibi, bir kenar katmanı politika değişikliği, iki tarafta da dağıtım olmadan, hata sayfası ve uyarı olmadan üretimdeki bir entegrasyonu kesebilir; genel bir yedek mesaj ise altyapı arızasını kullanıcı sorunu gibi gösterebilir. Pratik çıkarımlar basit: eve haber veren her şeye açık bir User-Agent ayarlayın, ayrıştırma başarısız olduğunda gerçek durum kodunu ve yanıt biçimini ortaya çıkarın ve bir sonraki sessiz engelleme aylar değil saatler içinde yakalanması için canlı yolu zararsız bir girdiyle yoklayın.
- #python
- #cloudflare
- #urllib
- #user-agent
- #http
- #licensing