Muhtemelen bununla karşılaşmışsınızdır: betik çalışır, siteye giriş yapar, ürünü sepete ekler ve sonra IP değişir ve sunucu sanki oraya ilk kez gelmişsiniz gibi yanıt verir. Kullanıcının oturumu kapanır, sepet boşalır, token geçersiz hale gelir. Sinir bozucu, değil mi? Hem de nasıl. Ama bu sorunun net bir mühendislik çözümü var ve bu rehberde baştan sona ele alacağız.

Giriş: IP değişince neden oturum kapanıyor ve sepet boşalıyor?

Dürüst olalım: IP rotasyonu sonrası oturum düştüğünde ilk akla gelen, adres değişikliğini suçlamaktır. «IP değişti, sunucu bunu gördü ve her şeyi sıfırladı.» Bazen gerçekten de öyledir. Ancak çok daha sık sorun IP'nin kendisinde değil, kodunuzun yapısındadır. Kod, farklı oturumların durumlarını birbirine karıştırır, çerezleri kaybeder, yeni adresten eski token'ları gönderir. Biz bunun olmamasını sağlamayı öğreneceğiz.

Okur bunun sonucunda ne kazanacak?

Bu rehberin sonunda şunları yapabiliyor olacaksınız: Birincisi, sunucu tarafında gerçekten IP'ye bağlı olanın ne olduğunu ve neyin efsane olduğunu anlamak. İkincisi, katı bir eşleştirme kuralı oluşturmak: bir mantıksal oturum = bir çerez kümesi = bir IP. Üçüncüsü, farklı proxy'ler arasında durumu izole eden ve verileri karıştırmayan, Python ve Node.js üzerinde çalışan kod yazmak. Dördüncüsü, program çalıştırmaları arasında durumu kaydetmek ve ne zaman atmak gerektiğini bilmek.

Bu rehber kimin için?

Rehber orta seviyeye yöneliktir. Zaten Python veya JavaScript'te kod yazıyor, HTTP isteğinin ne olduğunu biliyor ve proxy'lerin ne işe yaradığını anlıyorsunuz. Hangi rotasyon türünü seçeceğinizi tartışmayacağız – bunun için ayrı kaynaklar var. Burada IP rotasyonunun zaten sizin belirlediğiniz kurallara göre gerçekleştiğini varsayıyor ve tek bir sorunu çözüyoruz: bu rotasyon sırasında durum nasıl kaybedilmez?

Önceden bilmek gerekenler

Temel şeyleri anlamak faydalıdır. Çerez nedir? Sunucunun tarayıcıdan veya istemciden hatırlamasını ve her istekle geri göndermesini istediği küçük bir veri parçasıdır. Oturum nedir? Sunucunun istekler arasında sizi tanıma yöntemidir. Token nedir? Kimliğinizi veya işlem yapma yetkinizi doğrulayan bir dizedir. Bu terimler hâlâ belirsizse endişelenmeyin: temel kavramlar bölümünde her birini sade bir dille anlatacağız.

Ne kadar süre gerekir?

Teoriyi okumak ve anlamak yaklaşık kırk dakika sürer. Kendi dilinizdeki kodu inceleyip çalıştırmak bir iki saat daha alır. Gerçek görevlerle denemeler yaparak tam anlamak iki üç saat sürebilir. Acele etmeyin. Daha sonra anlaşılmaz bir şekilde bozulacak bir kodu hızla kopyalamaktansa, ilkeyi yavaşça anlamak daha iyidir.

Ön hazırlık: araçlar ve ortam

Kod yazmadan önce çalışma ortamını düzenleyelim. Bu biraz zaman alacak ama sonradan saatlerce hata ayıklamaktan kurtaracak.

Gerekli araçlar

  • Python 3.10 veya üzeri – Python ile çalışıyorsanız. 2026'da 3.12 ve 3.13 güncel sürümler, ancak anlatılan her şey 3.10'dan itibaren çalışır.
  • Node.js 20 LTS veya üzeri – JavaScript ile çalışıyorsanız. 22 LTS de uygundur.
  • IP rotasyonlu proxy – adres havuzuna erişiminiz olmalı. Bağlantı formatı genellikle şöyledir: protokol, ana bilgisayar, port, kullanıcı adı ve parola.
  • Kod düzenleyici – herhangi biri olur, örneğin ücretsiz, sözdizimi vurgulamalı bir editör.
  • Terminal veya komut satırı – kütüphaneleri kurmak ve betikleri çalıştırmak için.

Sistem gereksinimleri

Gereksinimler mütevazı. Herhangi bir modern bilgisayar yeterlidir. Dört gigabayt RAM yeterlidir, ancak çok sayıda paralel oturum planlıyorsanız sekiz veya daha fazlası daha iyidir. Daha önemlisi istikrarlı bir internet bağlantısıdır, çünkü bağlantı koptuğunda çerezler düzgün kaydedilmeyebilir.

Kurulması gerekenler

Python için iki kütüphane kurun. Terminali açın ve requests paketi ile proxy desteği için gereken paketi kurma komutunu çalıştırın. Şöyle yazılır: önce paket yöneticisi kurulum komutu, ardından requests adı. Durumu serileştirmek için standart modül işinizi görür, ayrıca kurmaya gerek yoktur.

Node.js için üç paket kurun: istekler için axios, çerez deposunu yönetmek için tough-cookie ve proxy üzerinden bağlanmak için https-proxy-agent. Üçü de projenizde tek bir paket kurulum komutuyla kurulur.

İpucu: Proje için ayrı bir sanal klasör oluşturun. Python'da bu sanal ortamdır, Node.js'te bağımlılık dosyası olan ayrı bir dizindir. Böylece farklı projelerin kütüphanelerini karıştırmaz ve sürüm çakışmalarını önlersiniz.

Yedek oluşturma

Eğer çerezleri zaten dosyalara veya veritabanına kaydediyorsanız, denemelerden önce bir kopya alın. Serileştirme mantığını değiştireceğiz ve mevcut verilere zarar verme riski var. Kayıtlı durumların bulunduğu klasörü backup etiketli bir konuma kopyalamanız yeterli.

Kontrol: Kurulumdan sonra her şeyin çalıştığından emin olun. Terminalde Python veya Node.js sürümünü hızlıca kontrol edin. Hatasız bir sürüm numarası görmelisiniz. Ardından kurulu kütüphaneleri etkileşimli modda içe aktarmayı deneyin – içe aktarma sessizce gerçekleşiyorsa her şey hazırdır.

Temel kavramlar: IP'ye ne bağlı, ne efsane?

Bu en önemli teorik bölüm. IP ile gerçekten neyin bağlantılı olduğunu anlamadan yanlış hastalığı tedavi edersiniz. Veri türlerini sırayla inceleyelim.

Çerez oturumu

Çerez oturumu, sunucunun size bir çerez biçiminde oturum kimliği vermesi ve durumu kendi tarafında saklamasıdır. Örneğin, içinde uzun rastgele bir dize bulunan sessionid adlı bir çerez. Sunucu bu dizeye göre sizin kaydınızı kendi belleğinde bulur. Bu mekanizma IP'ye bağlı mı? Tek başına hayır. Çerez adresten bağımsız çalışır. Ancak birçok hizmet ek bir kontrol yapar: oturumun hangi IP'den oluşturulduğunu hatırlar ve aynı çerezle farklı bir adresten istek gelirse bunu şüpheli bulur. İşte tam bu noktada oturum kapanır.

CSRF token'ı

CSRF token'ı, istek sahteciliğine karşı korumadır. Sunucu bir token verir, siz form gönderirken veya önemli bir işlem yaparken bunu geri göndermek zorundasınız. Bu token neredeyse hiçbir zaman IP'ye bağlı değildir. Adrese değil oturuma bağlıdır. Sorun başka bir nedenle ortaya çıkar: oturum çerezinizi kaybettiyseniz CSRF token'ı da geçersiz hale gelir, çünkü sunucu onu oturumunuzla eşleştiremez. Yani sorun burada ikincildir – çerez kaybının bir sonucudur.

JWT

JWT, içinde bilgi taşıyan ve sunucu tarafından imzalanan bir tokendir. İstemci onu saklar ve her istekte başlıkta gönderir. Klasik JWT IP'ye hiç bağlı değildir. Kendi kendine yeterlidir: sunucu imzayı ve son kullanma tarihini kontrol eder, adres onu ilgilendirmez. Ancak sunucunun token'ı IP'ye kendi tarafında bağladığı veya adresi token'ın içine koyduğu uygulamalar da vardır. Bu durumlarda IP değişimi kontrolü bozar. Bu JWT'nin özelliği değil, belirli bir hizmetin kararıdır.

Sunucu tarafı oturumu

Sunucu tarafı oturumu, sunucunun kendi bünyesinde sakladığı ve sizin kimliğinizle ilişkilendirdiği durumun genel adıdır. Sepet, görüntüleme geçmişi, yetkilendirme durumu – bunların çoğu sunucu oturumunda bulunur. IP'ye bağlanma burada hizmetin ayarlarına bağlıdır. Bazıları güvenlik için oturumu ilk IP'ye sıkı sıkıya bağlar. Diğerleri adres değişikliğine tolerans gösterir. Önceden genellikle bilmezsiniz, bu yüzden kodu bağlantı varmış gibi yazarsınız – bu güvenli bir stratejidir.

Sepet

Sepet, sunucu oturumunun veya çerezlerin özel bir durumudur. Basit mağazalarda sepet, doğrudan istemcide bir çerezde saklanır. Karmaşık olanlarda ise oturuma bağlı olarak sunucuda tutulur. IP değişiminden sonra sepet boşalıyorsa, adresi kontrol eden bir sunucu oturumuna bağlıydı. Çözüm aynıdır: tek bir mantıksal oturum içinde IP'yi değiştirmeyin veya tüm çerez kümesini dikkatli bir şekilde saklayın.

Sonuç: IP gerçekten nerede devreye giriyor?

Resmi toplayalım. HTTP mekanizmasının kendisi olan çerezler, CSRF ve JWT IP'ye bağlı değildir. Bağlantı, hizmet tarafında ek bir kontrol olarak ortaya çıkar ve siz onu yönetemezsiniz. Yönetebileceğiniz tek şey, kendi tarafınızdaki oturum, çerez kümesi ve IP arasındaki eşleşmedir. Rehberin ana kuralı da buradan çıkar.

Kontrol: Anlayışınızı test edin. IP değişiminden sonra oturum düşüyorsa, ancak eski IP'ye dönünce her şey düzeliyorsa, sunucu adresi sıkı bir şekilde kontrol ediyordur. Eski IP'de bile düzelmiyorsa, kodda çerezleri kaybetmişsinizdir. Bunlar farklı tedavileri olan iki farklı tanıdır.

1. Adım: Eşleştirme kuralını formüle edelim

Bu adımın amacı: ana prensibi pekiştirmek ve bunu kod yapısında nasıl ifade edeceğinizi anlamak.

Kural basitçe şöyledir: bir mantıksal oturum = bir çerez kümesi = bir IP. Bunun pratikte ne anlama geldiğini inceleyelim.

  1. Mantıksal oturum, tek bir sürekli işi temsil eden istekler zinciridir: girdiniz, giriş yaptınız, bir şeyler yaptınız, çıktınız. Bunların hepsi bir mantıksal oturumdur.
  2. Bir çerez kümesi, yalnızca bu mantıksal oturuma ait olan ve başka hiçbir şeye ait olmayan ayrı bir çerez deposudur.
  3. Bir IP – tek bir mantıksal oturum sırasında adres değişmez. Rotasyon yine de olduysa, mantıksal oturum sona ermiş sayılır.

Bunu kodda nasıl ifade ederiz? Çok açık: içinde hem çerez deposunu hem de proxy ayarını barındıran bir kapsayıcı nesne oluştururuz. Bu nesne yaşadığı sürece mantıksal oturum da yaşar. IP'yi değiştirme zamanı geldiğinde ya yeni bir kapsayıcı oluştururuz ya da hizmet adres değişikliğine toleranslıysa çerezleri yeni IP'ye sahip yeni kapsayıcıya dikkatlice taşırız.

⚠️ Dikkat: En sık yapılan mimari hata, tek bir ortak çerez kümesini saklayıp farklı proxy'ler kullanmaktır. Bu kesinlikle her şeyi bozar. Farklı mantıksal oturumlar birbirlerinin çerezlerini ezmeye başlar ve sunucu çelişkili veriler alır. Bunu asla yapmayın.

İpucu: Mantıksal oturumu bir insan olarak düşünün. Bir insanın tek bir kimliği (çerezleri) ve tek bir evi (IP) vardır. İki kişi aynı kimliği kullanamaz ve bir kişi aynı anda iki evde yaşayamaz. Bu benzetme sizi birçok hatadan kurtarır.

Kontrol: Gelecekteki yapınızı kağıda çizin. Her biri kendi çerez deposuna ve kendi proxy'sine sahip birkaç bağımsız blok elde etmelisiniz. Bloklar arasında ortak veri yok. Eğer böyleyse kuralı anlamışsınızdır.

2. Adım: Python'da uygulama – her proxy için Session

Bu adımın amacı: her mantıksal oturumun kendi requests.Session nesnesine, kendi CookieJar'ına ve kendi proxy'sine sahip olduğu, birbirinden izole çalışan bir kod yazmak.

requests kütüphanesinde Session nesnesi vardır. Kendisi başlı başına bir kapsayıcıdır: içinde çerez deposu bulunur ve ayarları tüm isteklere uygulayabilir. Bu, mantıksal oturumumuz için ideal bir temeldir.

Temel yapı

  1. Bir proxy'nin verilerini alıp hazır bir Session nesnesi döndüren bir fonksiyon oluşturun.
  2. Fonksiyonun içinde yeni bir Session nesnesi oluşturun.
  3. Nesneye proxies ayarını verin – http ve https protokolleri için proxy adresini içeren bir sözlük.
  4. Nesneyi döndürün. Artık izole bir kapsayıcınız var.

Kod şöyle görünür. Satır satır: requests'i import ederiz. proxy_url adlı bir dize alan make_session fonksiyonunu tanımlarız. İçinde s eşittir requests.Session() yazarız. Ardından s.proxies anahtarının http olduğu ve proxy_url'u gösterdiği, https anahtarının da proxy_url'u gösterdiği bir sözlüğe eşitlenir. Sonunda return s. İşte, fonksiyon hazır.

Bu durumu neden izole eder?

Her make_session çağrısı tamamen yeni bir nesne oluşturur. Yeni nesnenin cookiejar adı verilen kendi iç çerez deposu vardır. Bir oturumun aldığı çerezler, fiziksel olarak başka bir oturuma giremez, çünkü bunlar bellekte farklı nesnelerdir. Elde etmek istediğimiz de tam olarak buydu.

Oturumu kullanma

  1. İstediğiniz proxy ile fonksiyonu çağırarak oturum nesnesini elde edin.
  2. İstekleri bu nesnenin metodlarıyla yapın: s.get veya s.post.
  3. Sunucunun Set-Cookie başlığında gönderdiği çerezler otomatik olarak nesnenin içinde saklanır.
  4. Aynı nesne ile sonraki isteklerde bu çerezler otomatik olarak geri gönderilir.

İpucu: Tek bir mantıksal oturum içindeki her istek için yeni bir Session oluşturmayın. Bu durumda çerezler birikmez. Nesneyi tüm mantıksal oturum için bir kez oluşturun ve bu oturumun tüm isteklerinde kullanın.

Thread'ler arası izolasyon

Birden fazla thread ile çalışıyorsanız, her thread'in kendi Session nesnesi olmalıdır. Session nesnesi thread-safe değildir. Bu, iki thread aynı anda tek bir nesneye çerez yazarsa verilerin bozulabileceği anlamına gelir.

  1. Thread'e özel yerel veri mekanizmasını kullanın. Python'da bu threading.local nesnesidir.
  2. Her thread başlarken ona ayrı bir oturum oluşturun ve bunu thread'in yerel deposunda saklayın.
  3. Thread içinde yalnızca kendi oturumunuza erişin, başkalarına dokunmayın.

Pratikte şöyle görünür: local = threading.local() adında global bir nesne oluştururuz. Thread çalışmaya başlarken local'ın session niteliği olup olmadığını kontrol ederiz. Yoksa, bu thread'e atanan proxy ile make_session çağrısı yaparak oluştururuz. Ardından thread içinde tüm istekler için local.session kullanırız.

⚠️ Dikkat: Bir Session nesnesini asla ortak kaynak olarak thread'ler arasında paylaştırmayın. İstekler sırayla gidiyor gibi görünse bile, zamanlayıcı en uygunsuz anda thread'leri değiştirebilir ve karışık çerezler elde edersiniz. Her thread'e kendi nesnesi.

Mantık içinde rotasyon

IP rotasyonu olduğunda ve yeni bir adres gerektiğinde şöyle yapın. Mevcut mantıksal oturumu sonlandırın: sunucu IP'ye sıkı sıkıya bağlıysa, yeni proxy ile yeni bir Session nesnesi oluşturun ve sıfırdan başlayın – yeniden giriş yapın. Sunucu adres değişikliğine toleranslıysa çerezleri aktarabilirsiniz; durum saklama adımında buna değineceğiz.

Kontrol: Farklı proxy'lerle iki oturum başlatın, IP'nizi ve çerezlerinizi gösteren bir test servisinde her birine giriş yapın. Her oturumun kendi IP'sini ve kendi çerez kümesini gördüğünden emin olun. Veriler karışmıyorsa izolasyon doğru çalışıyor demektir.

3. Adım: Aynısını Node.js'te yapmak

Bu adımın amacı: axios, tough-cookie ve proxy agent kullanarak JavaScript'te eşdeğer bir yapı kurmak.

Node.js ekosisteminde hazır Session seviyesinde bir nesne yoktur, bu yüzden onu üç parçadan oluşturacağız. Çerez deposunu tough-cookie'den alacağız. Proxy üzerinden bağlantıyı bir agent sağlayacak. İstekleri axios yapacak.

Kapsayıcıyı oluşturma

  1. tough-cookie kütüphanesinden CookieJar sınıfını içe aktarın.
  2. https-proxy-agent kütüphanesinden proxy agent oluşturma fonksiyonunu içe aktarın.
  3. axios'u içe aktarın.
  4. Proxy adresini alıp yapılandırılmış bir nesne döndüren makeClient fonksiyonunu oluşturun.

Fonksiyonun içinde yeni bir depo örneği oluşturun: const jar = new CookieJar(). Adresi ona ileterek bir proxy agent oluşturun: const agent = new HttpsProxyAgent(proxyAdresi). axios.create metoduyla, içine httpsAgent: agent ve httpAgent: agent vererek yapılandırılmış bir axios örneği oluşturun.

Çerezlerle otomatik çalışmayı bağlama

Çıplak axios, yanıttaki çerezleri depoya koymayı ve istek için onları çıkarmayı kendi başına yapamaz. İki yol vardır.

  1. İlk yol: axios ile tough-cookie'yi birbirine bağlayan hazır bir sarmalayıcı kullanmak; ayrı bir paket olarak kurulur. Verilen jar deposu üzerinden çerezleri otomatik olarak okur ve yazar.
  2. İkinci yol: istek ve yanıt interceptors'larıyla bunu manuel olarak yapmak. İstekten önce, ilgili adres için depodan çerez dizesini alıp Cookie başlığına koyarız. Yanıttan sonra Set-Cookie başlığını alır ve her çerezi depoya yazarız.

İpucu: Başlangıçta hazır sarmalayıcıyı kullanın – hata yapma olasılığınız azalır. Manuel seçeneği, süreci ince ayar kontrol etmeniz gerektiğinde, örneğin her çerezi loglamak istediğinizde saklayın.

Paralel görevler arasında izolasyon

Node.js'te model farklıdır – burada thread'ler değil, tek olay döngüsündeki asenkron görevler vardır. Ancak prensip aynıdır: her mantıksal oturumun kendi jar'ı ve kendi agent'ı olan ayrı bir client nesnesi vardır.

  1. Her paralel görev için makeClient'ı ayrı ayrı çağırın.
  2. İstemcileri bir dizide veya haritada saklayın; anahtar, görev kimliğidir.
  3. Birden fazla istemci için aynı jar'ı asla aynı anda kullanmayın.

⚠️ Dikkat: Asenkron kodda, bir client'ı birden fazla promise zinciri arasında yanlışlıkla paylaştırmak kolaydır. Bu durumda çerezler mantıksal oturumlar arasında karışmaya başlar. Her zincirin, ayrı bir makeClient çağrısıyla oluşturulmuş kendi client'ını kullandığını her zaman doğrulayın.

Node.js'te rotasyon

Mantık Python ile aynıdır. Yeni bir IP gerektiğinde ve hizmet oturumu adrese bağladığında, yeni proxy ve yeni boş jar ile yeni bir client oluşturun, yeniden giriş yapın. Hizmet toleranslıysa, eski jar'ın içeriğini yeni agent'a sahip yeni client'a aktarın.

Kontrol: Farklı proxy'lerle iki istemci oluşturun. IP'yi ve çerezleri yansıtan bir test servisine istekler yapın. İlk istemcinin bir IP'yi ve kendi çerezlerini, ikincinin ise diğer IP'yi ve kendi çerezlerini gördüğünden emin olun. Karşılaşma olmamalıdır.

4. Adım: Durumu çalıştırmalar arasında saklama

Bu adımın amacı: çerezleri diske kaydetmeyi ve programın bir sonraki çalıştırılışında, yaşam sürelerini dikkate alarak geri yüklemeyi öğrenmek.

Çoğu zaman betiği durdurup daha sonra, yetkilendirmeyi kaybetmeden yeniden başlatmak gerekir. Bunun için çerezleri serileştirmek – metne dönüştürüp bir dosyaya veya veritabanına kaydetmek gerekir.

Python'da serileştirme

requests'teki CookieJar nesnesini birkaç yolla kaydedebilirsiniz. En taşınabilir olanı, çerezleri basit bir sözlükte toplayıp JSON formatına yazmaktır.

  1. s.cookies aracılığıyla oturum nesnesindeki tüm çerezleri dolaşın.
  2. Her çerez için adını, değerini, alan adını, yolunu ve son kullanma tarihini toplayın.
  3. Bunları bir sözlük listesine koyun.
  4. Listeyi JSON formatında bir dosyaya yazın.

Geri yüklerken tersini yapın: dosyayı okuyun, listeyi dolaşın ve her çerezi, alan adı ve yolunu belirterek cookie ayarlama yöntemiyle yeni oturum nesnesine ekleyin.

İpucu: Çerezlerle birlikte proxy kimliğini veya en azından hangi mantıksal oturuma ait olduklarını belirten bir not saklayın. Böylece yanlış IP'ye sahip başka çerezleri geri yüklemez ve eşleştirme kuralını ihlal etmezsiniz.

Node.js'te serileştirme

tough-cookie kütüphanesinin yerleşik bir serileştirme yöntemi vardır. jar nesnesinin, tüm depoyu bir JSON nesnesine dönüştüren asenkron bir metodu vardır. Ters metot, bu nesneden jar'ı geri yükler.

  1. Deponun serileştirme metodunu çağırın ve bir nesne elde edin.
  2. Nesneyi bir dizeye dönüştürün ve bir dosyaya kaydedin.
  3. Başlatma sırasında dosyayı okuyun, dizeyi tekrar nesneye ayrıştırın.
  4. Nesneyi ileterek seriden çıkarma (deserialization) metoduyla jar'ı geri yükleyin.

Bu, Python'dan daha kullanışlıdır çünkü tough-cookie, son kullanma tarihi ve güvenlik bayrakları dahil tüm gerekli alanları kendisi saklar.

Çerezlerin yaşam süresi

Her çerezin bir son kullanma tarihi vardır. Oturum çerezleri vardır – tarayıcı kapanana kadar yaşarlar ve belirgin bir tarihleri yoktur. Kalıcı çerezler vardır – belirli bir son kullanma tarihleri vardır. Yalnızca süresi dolmamış kalıcı çerezleri diske kaydetmek mantıklıdır. Oturum çerezleri yeniden başlatmanın ardından genellikle sunucuda geçersizdir.

  1. Kaydetmeden önce her çerezin son kullanma tarihini kontrol edin.
  2. Süresi dolmuş olanları atın.
  3. Geri yüklerken tarihleri tekrar kontrol edin ve bayatlamışları yüklemeyin.

Durumu ne zaman atmak daha kolaydır

Kaydedilmiş çerezlere tutunmak her zaman gerekmez. Bazen temiz bir başlangıç daha hızlı ve daha güvenilirdir.

  • Son çalıştırmadan bu yana uzun zaman geçtiyse, sunucudaki oturum büyük olasılıkla süresi dolmuştur; geri yüklenecek bir şey yoktur.
  • Sunucu, geri yüklenen çerezlerle ilk istekte yetkilendirme hatası döndürdüyse, onları atın ve yeniden giriş yapın.
  • Durum dosyasının bütünlüğünden emin değilseniz, garip davranışları hata ayıklamaktansa temiz bir sayfadan başlamak daha iyidir.

⚠️ Dikkat: Çerez ve token içeren dosyalar erişim verileri içerir. Bunları güvenli bir yerde saklayın, ortak depoya koymayın, korumasız kanallardan göndermeyin. Böyle bir dosyanın sızması, hesaba erişimin sızmasıyla eşdeğerdir.

Kontrol: Durumu kaydedin, programı tamamen kapatın, yeniden başlatın, durumu geri yükleyin ve yetkilendirme gerektiren bir istek yapın. Sunucu, yetkili bir kullanıcıya yanıt verir gibi yanıt veriyorsa kaydetme çalışıyor demektir. Oturum kapatıyorsa, son kullanma tarihlerini ve alan adı/yol geri yüklemesinin doğruluğunu kontrol edin.

5. Adım: Mimari hataların incelenmesi

Bu adımın amacı: üç ana hatayı ayrıntılı olarak incelemek; böylece bunları kendi kodunuzda tanır ve önlersiniz.

Birinci hata: tüm proxy'ler için ortak CookieJar

Bu, kötülüğün kökenidir. Geliştirici, tasarruf edeceğini düşünerek tek bir çerez deposu oluşturur ve farklı proxy'ler kullanır. Olan şudur: ilk IP'deki oturumun çerezleri, ikinci IP'deki isteğe gider. Sunucu, başka bir adres altında oluşturulmuş bir çerez görür ve oturumu ya sıfırlar ya da davranışı şüpheli bulur.

Çözüm basit: her proxy'ye kendi çerez deposu. İstisna yok. Bunu kod adımlarında zaten belirttik: her mantıksal oturum için ayrı bir Session veya ayrı bir jar'a sahip ayrı bir client.

İkinci hata: paralel isteklerde yarış durumu

Yarış durumu, iki işlemin aynı anda aynı verilere erişip birbirine müdahale etmesidir. İki thread aynı CookieJar'a yazarsa, bir kayıt diğerinin üzerine yazabilir. Sonuç: çerezlerin bir kısmı rastgele kaybolur ve hata her seferinde tekrarlanmaz, bu da hata ayıklamayı çileden çıkarıcı hale getirir.

  1. Her thread'e, anlattığımız gibi thread yerel verileri aracılığıyla kendi oturumunu verin.
  2. Asenkron kodda, bir client'ı bağımsız görev zincirleri arasında paylaştırmayın.
  3. Herhangi bir nedenle nesne hâlâ ortaksa, aynı anda yalnızca bir thread'in onunla çalışmasını sağlamak için bir kilit kullanın.

İpucu: Yarış durumundan kaçınmanın en iyi yolu, hiç ortak değiştirilebilir veriye sahip olmamaktır. Mantıksal oturumlara göre izolasyon, sorunu kökten çözer: veriler ortak değilse yarış olamaz.

Üçüncü hata: yönlendirmelerde Set-Cookie kaybı

Sunucu bir yönlendirme ile yanıt verdiğinde, genellikle aynı yanıtta Set-Cookie başlığıyla önemli çerezler ayarlar. Bazı istemci ayarları, otomatik yönlendirme sırasında bu çerezleri kaybeder – depoya ulaşmazlar.

  1. İstemcinizin çerezleri yalnızca son yanıtta değil, yönlendirme zincirinin her adımında kaydettiğinden emin olun.
  2. requests'te, Session nesnesi kullanılırken bu varsayılan olarak çalışır – çerezler yol boyunca toplanır. Gereksiz yere yönlendirme takibini kapatmadığınızı kontrol edin.
  3. axios'ta çerezlerle manuel çalışıyorsanız, her ara yanıtta Set-Cookie'yi işleyin. Bir sarmalayıcı kullanıyorsanız, yönlendirmeleri yakaladığını doğrulayın.

⚠️ Dikkat: Yetkilendirme başarılıysa ancak sonraki istek oturumu kapatıyorsa, sık karşılaşılan neden tam olarak yönlendirme sırasında kaybedilen çerezdir. Tüm Set-Cookie başlıklarının loglanmasını açın ve beklenen çerezlerin depoya ulaşıp ulaşmadığını kontrol edin.

Kontrol: Hedef serviste yönlendirmeye neden olan bir eylem bulun, örneğin form üzerinden giriş. Zinciri izleyin ve her adımdan sonra çerezleri karşılaştırın. Verilen tüm çerezler deponuzda olmalıdır. Biri kaybolduysa, sızıntıyı bulmuşsunuzdur.

6. Adım: Hepsini bir iş akışında birleştirmek

Bu adımın amacı: öğrenilenleri, başlangıçtan rotasyona kadar tek bir öngörülebilir iş akışında birleştirmek.

Artık tüm detaylara sahipsiniz. Bunları tekrarlanabilir bir eylem zincirinde toplayalım.

  1. Havuzunuzdan bir proxy alın ve bunun için izole bir mantıksal oturum oluşturun – Python'da Session veya Node.js'te client.
  2. Bu mantıksal oturum için kayıtlı bir durum varsa ve süresi dolmadıysa çerezleri geri yükleyin. Aksi halde yeniden giriş yapın.
  3. Gerekli istekleri bu oturumun nesnesi üzerinden gerçekleştirin. Çerezler otomatik olarak birikir.
  4. Bir çökme durumunda ilerlemeyi kaybetmemek için durumu periyodik olarak diske kaydedin.
  5. IP rotasyonu zamanı geldiğinde mantıksal oturumu doğru şekilde sonlandırın.
  6. Hizmet IP'ye sıkı sıkıya bağlıysa, yeni adreste temiz bir sayfadan yeni bir mantıksal oturum başlatın.
  7. Hizmet toleranslıysa, yeni proxy ile yeni bir kapsayıcı oluşturun ve eski kapsayıcıdaki çerezleri ona aktarın.

İpucu: Bir olay günlüğü tutun: oturum ne zaman oluşturuldu, hangi IP ile, rotasyon ne zaman oldu, oturum kapanması yaşandı mı? Böyle bir günlük, aksi halde saatlerce arayacağınız bir örüntüyü beş dakikada gösterir.

Kontrol: Tam döngüyü çalıştırın: oturum oluşturma, giriş yapma, birkaç işlem, kaydetme, rotasyon, devam etme. Her adımda durumun öngörülebilir davrandığından ve oturum kapanmasının yalnızca beklediğiniz durumda gerçekleştiğinden emin olun.

Sonucu doğrulama: final kontrol listesi

Bu listeyi gözden geçirin. Tüm maddeler tamamlandıysa sisteminiz doğru çalışıyor demektir.

  • Her mantıksal oturumun, kendi çerez deposuna sahip ayrı bir kapsayıcı nesnesi vardır.
  • Her kapsayıcıya, oturumun tüm yaşamı boyunca tam olarak bir proxy bağlıdır.
  • Bir oturumun çerezlerinin başka bir oturuma karışabileceği hiçbir yer yoktur.
  • Çok thread'li kodda her thread, thread yerel verileri aracılığıyla kendi oturumunu kullanır.
  • Asenkron kodda her bağımsız zincirin kendi client'ı vardır.
  • Çerezler, yönlendirmelerin tüm adımlarında doğru şekilde toplanır.
  • Durum, son kullanma tarihleri dikkate alınarak çalıştırmalar arasında kaydedilir ve geri yüklenir.
  • IP değiştiğinde mantıksal oturum ya yeniden başlar ya da çerezler bilinçli olarak aktarılır.
  • Çerez ve token içeren dosyalar güvenli şekilde saklanır.

Nasıl test edilir

  1. Geçerli IP'nizi ve gönderilen çerezleri gösteren bir test servisi bulun.
  2. Farklı proxy'lerle iki oturum oluşturun ve verilerin tamamen izole olduğundan emin olun.
  3. Giriş yapın, durumu kaydedin, programı yeniden başlatın, geri yükleyin – yetkilendirmenin hâlâ geçerli olduğunu doğrulayın.
  4. Bir rotasyonu simüle edin ve oturumun nasıl davrandığını gözlemleyin.

Başarı göstergeleri: farklı oturumların verileri asla karışmaz, oturum kapanması yalnızca sunucunun IP'ye sıkı bağlanması durumunda gerçekleşir, geri yüklenen durum çalışır ve paralel çalışmada yarış durumları oluşmaz.

Sık karşılaşılan hatalar ve çözümleri

Sorun: IP değişiminden sonra kullanıcının oturumu kapanıyor. Neden: sunucu oturumu adrese sıkı sıkıya bağlıyor. Çözüm: tek bir mantıksal oturum içinde IP'yi değiştirmeyin; değiştirme gerekiyorsa yeni adreste oturumu yeniden başlatın.

Sorun: farklı oturumların çerezleri karışıyor. Neden: birden fazla proxy için ortak CookieJar. Çözüm: her mantıksal oturuma ayrı bir depo verin, asla paylaştırmayın.

Sorun: paralel çalışmada hata her seferinde ortaya çıkıyor. Neden: birden fazla thread'in ortak bir nesneye yazarken yarış durumu oluşması. Çözüm: thread yerel verileriyle oturumları thread'lere göre izole edin veya bir kilit kullanın.

Sorun: yetkilendirme başarılı oluyor ama hemen düşüyor. Neden: yönlendirme sırasında çerez kaybı. Çözüm: yönlendirme zincirinin tüm adımlarında çerez toplamayı kontrol edin ve Set-Cookie loglamayı etkinleştirin.

Sorun: geri yüklenen durum çalışmıyor. Neden: süresi dolmuş veya oturum çerezleri kaydedilmiş ya da alan adı ve yol yanlış belirtilmiş. Çözüm: yalnızca geçerli kalıcı çerezleri kaydedin ve doğru alan adı ve yol ile geri yükleyin.

Sorun: CSRF token'ı sürekli geçersiz. Neden: token'ın bağlı olduğu oturum çerezi kaybedilmiş. Çözüm: önce oturum çerezlerinin bütünlüğünü sağlayın, token otomatik olarak geçerli hale gelecektir.

Sorun: JWT, rotasyondan sonra çalışmayı durduruyor. Neden: belirli bir hizmet, token'ı kendi tarafında IP'ye bağlamış. Çözüm: token'ın yaşamı boyunca IP'yi değiştirmeyin veya yeni adreste yeni bir token alın.

Ek olanaklar ve optimizasyon

Temel düzen çalıştığında, onu güçlendirebilirsiniz.

Hazır oturum havuzu

Her seferinde yeni bir oturum oluşturmak yerine, önceden hazırlanmış ve yetkilendirilmiş, her biri kendi proxy'sine sahip mantıksal oturumlardan oluşan bir havuz tutun. Boş bir oturumu alın, kullanın, havuza geri verin. Bu, gereksiz yere tekrarlanan yetkilendirme olmadığı için işi hızlandırır.

Otomatik canlılık kontrolü

Hizmete hafif bir istek yapıp oturumun canlı olup olmadığını kontrol eden bir işlev ekleyin. Sunucu, yetkisiz bir kullanıcıya yanıt veriyorsa oturum yeniden yetkilendirmeye işaretlenir. Böylece bayatlamayı, önemli bir işlemi bozmadan önce yakalarsınız.

İpucu: Canlılık kontrolünü her istekten önce değil, bir zamanlamayla veya uzun duraklamalardan sonra yapın. Çok sık kontrol yapmak gereksiz yük oluşturur ve fayda sağlamaz.

Merkezi durum deposu

Büyük projeler için dosyalar yerine çerez deposu olarak bir veritabanı kullanın. Anahtar – mantıksal oturum kimliği, değer – serileştirilmiş durum. Bu, ölçeklendirmeyi kolaylaştırır ve saklamayı daha güvenli hale getirir.

Metrikler ve gözlemlenebilirlik

Kaç kez oturum kapanması olduğunu, kaç oturumun yeniden oluşturulması gerektiğini ve geri yüklemenin ne sıklıkla başarılı olduğunu sayın. Bu rakamlar sisteminizin sağlığını gösterir ve nerede optimize edilecek bir şey olduğunu söyler.

SSS: sık sorulan sorular

Her IP değişiminde yeni bir oturum nesnesi oluşturmak şart mı? Hizmet adresi sıkı kontrol ediyorsa evet, çünkü eski oturum yeni IP'de zaten kabul edilmeyecektir. Hizmet toleranslıysa, çerezleri yeni proxili bir kapsayıcıya taşıyıp devam edebilirsiniz.

Birden fazla mantıksal oturum için aynı proxy kullanılabilir mi? Kod açısından evet, ancak her mantıksal oturumun yine de kendi ayrı çerez deposu olmalıdır. Yalnızca bağlantı ayarları ortak olabilir, durum ortak olamaz.

Neden tüm çerezleri tek bir yerde saklayıp alan adına göre filtrelemiyoruz? Çünkü sorun alan adında değil, belirli bir mantıksal oturuma ve IP'ye bağlanmaktadır. Aynı alan adındaki bir oturumun çerezleri, aynı alan adındaki başka bir oturuma karışmamalıdır.

Hizmetin oturumu IP'ye bağlayıp bağlamadığını nasıl anlarız? Bir deney yapın: bir IP'de giriş yapın, adresi değiştirin ve bir istek gönderin. Oturum kapanıyorsa muhtemelen bir bağlantı vardır. Eski IP'ye dönün: düzeliyorsa sunucu ilk adresi hatırlıyor demektir.

Diske kaydederken oturum çerezleriyle ne yapmalı? Bunları genellikle kaydetmenin bir anlamı yoktur, çünkü sunucu bağlantı koptuktan sonra onları geçersiz sayar. Süresi dolmamış kalıcı çerezleri kaydedin.

Kütüphane yönlendirme sırasında çerezleri kaydetmiyorsa ne yapmalı? Yönlendirme zincirinin her ara yanıtında Set-Cookie başlığını manuel olarak işleyin ve çerezleri kendi deponuza ekleyin.

Her thread'in kendi oturumu varsa kilit gerekli mi? Hayır. Veriler ortak değilse yarış durumu olamaz ve kilit gerekmez. Kilit yalnızca tek bir nesneye zorunlu ortak erişim olduğunda gereklidir.

Geri yüklenebilir durum ne kadar süre saklanabilir? Sunucu oturumu canlı saydığı sürece. Kesin süre hizmete bağlıdır. Zaman içinde tahmin yürütmektense canlılığı bir istekle kontrol etmek daha pratiktir.

Hangisi daha önemli – çerezleri mi yoksa token'ı mı kaydetmek? Hizmetin yetkilendirme mekanizmasına bağlıdır. Bazen token yeterlidir, bazen tüm çerez kümesi gerekir. Tüm durumu bir bütün olarak kaydetmek daha güvenlidir; böylece gerekeni kaçırmazsınız.

Çerezler Python ve Node.js arasında taşınabilir mi? Evet, ad, değer, alan adı, yol ve süre alanlarını içeren JSON gibi ortak, nötr bir formatta kaydedilirse. O zaman her iki sistem de onları okuyabilir.

Sonuç

Şimdi öğrendiklerinizi özetleyelim. IP değişiminden sonra oturumun kapanmasının nedeninin değişimin kendisi değil, sunucu kontrolleri ve mimarinizdeki hatalar olduğunu anladınız. Çerezlerin, CSRF ve JWT'nin kendi başlarına adrese bağlı olmadığını, bağlantıyı belirli bir hizmetin eklediğini öğrendiniz. Ana kuralı benimsediniz: bir mantıksal oturum = bir çerez kümesi = bir IP.

Ardından çalışan bir kod yazdınız. Python'da, her proxy için kendi CookieJar'ına sahip ayrı bir Session nesnesi ve thread bazında izolasyon. Node.js'te, her mantıksal oturum için ayrı bir client ile axios, tough-cookie ve proxy agent kombinasyonu. Durumu çalıştırmalar arasında kaydetmeyi, çerezlerin son kullanma tarihlerini dikkate almayı ve durumu ne zaman atmanın daha kolay olduğunu öğrendiniz.

Üç sinsi hatayı incelediniz: ortak CookieJar, paralel çalışmada yarış durumu ve yönlendirmelerde Set-Cookie kaybı. Artık, ham bir çözümü yayınlamanızı engelleyecek bir prod öncesi kontrol listeniz var.

Sırada ne yapmalı?

Küçükten başlayın. Tek bir gerçek senaryo alın, bunun için izole bir mantıksal oturum uygulayın ve durumun kaybolmadığından emin olun. Sonra diske kaydetmeyi ekleyin. Sonra birden çok oturuma ölçekleyin. Her adımda sonucu kontrol ederek ilerleyin.

Nereye doğru geliştirebilirsiniz?

Bundan sonra gözlemlenebilirliğe daha çok odaklanmalısınız: oturum canlılığı metrikleri ve olay günlüğü ayarlayın. Ardından, hizmet adres değişikliğine toleranslı olduğunda durumu bilinçli olarak aktarmayı öğrenin. Ve son olarak, işi hızlandırmak için hazır oturum havuzu kurun. Bu adımların her biri sisteminizi daha dayanıklı ve öngörülebilir hale getirir. Her şey yoluna girecek – prensibi zaten anladınız, gerisi pratik meselesi.