Ham API ile k6 yük testlerinde CAPTCHA nasıl çözülür

k6 captcha - How to Solve CAPTCHA in k6 Load Tests With the Raw API

Bir k6 captcha adımı, ham HTTP API üzerinden geçmek zorundadır; çünkü k6 Node değildir ve SDK içine kurulamaz. Kolay kısım budur: iki çağrı, gönderme ve yoklama. Testinizin bir işe yarayıp yaramadığını belirleyen kısım ise çözümün nerede çalıştığıdır. Onu default fonksiyonuna koyarsanız her sanal kullanıcı her iterasyonda çözer; bu da uygulamanız yerine çözücüyü ölçer ve bunu hiç kaldırmak için tasarlanmamış bir makineyi boğar. Onu setup aşamasına koyarsanız temiz sayılar elde edersiniz, ama bilmeniz gereken dürüst bir sınırla birlikte.

Neye ihtiyacınız var

  • k6, herhangi bir güncel sürüm. Kurulacak paket yoktur, çünkü içine kurulacak bir şey yoktur.
  • Test ettiğiniz korumalı uç noktanın sitekey'i ve sayfa URL'si.
  • k6, çözücüyle aynı makinede çalışıyorsa CapSkip Local modda, bir yük üreticide veya CI'da çalışıyorsa Server modda çalışır. Ayrıntılı bilgi için bkz: bağlantı ayarları.

Çözmenin doğru tercih olduğu durumlar

Herhangi bir kod yazmadan önce bunu açıkça söyleyelim. Test edilen site sizinse, genellikle daha iyi hamle yük üreticinin doğrulamayı geçmesine izin vermektir: adresini allowlist'e ekleyin veya staging ortamınızın tanıdığı bir header gönderin ve widget'ı tamamen atlayın. Siz uygulamanızı ölçmeye çalışıyorsunuz ve çözülen her doğrulama başkasına ait bir gecikme ekler.

Çözmek iki durumda doğru tercihtir. Vurmanız gereken uç nokta korumalıdır ve o korumayı kontrol etmezsiniz, ya da korumalı yolun kendisi test edilen şeydir ve onu atlamak gerçek trafiğin hiç kullanmadığı bir rotayı test etmek olur. İkisi de gerçektir ve bu yazının geri kalanı tam olarak bunun içindir.

SDK burada neden işe yaramaz

k6 betikleri JavaScript'e benzer ama Node üzerinde çalışmaz. require uygulaması k6’nın kendisine aittir; dokümantasyon ise bu sınır konusunda oldukça açıktır: yerleşik k6 modüllerini, yerel dosyaları ve uzak betikleri yükler, ancak Node modül çözümleme algoritmasını desteklemez. npm yok, node_modules yok, fs yok ve crypto yok. Dolayısıyla CapSkip paketi import edilemez, uzanabileceğiniz başka hiçbir şey de edilemez.

Bu, kulağa geldiğinden daha az maliyetlidir. API, 2captcha uyumludur ve iki uç noktaya sahiptir; bu yüzden k6’nın kendi http modülü bunu yaklaşık on beş satırda karşılar. Yük üreticiniz sonuçta sıradan bir Node süreci çıkarsa, Node.js CAPTCHA çözücü sayfası SDK'sı olan istemciyi kapsar.

Adım 1: çözümü sade bir fonksiyon olarak yazın

in.php'ye gönderin, bir ID alın, ardından yanıt gelene kadar res.php'yi yoklayın. JSON isteyin ki metinleri pipe karakterinden bölmek yerine alanları okuyasınız.

// No install step. Both modules are built into k6.
import http from 'k6/http';
import { sleep } from 'k6';

const SOLVER = 'http://127.0.0.1:8080';
const KEY = 'YOUR_API_KEY';

function solve(sitekey, pageurl) {
  const submitted = http.post(SOLVER + '/in.php', {
    key: KEY,
    method: 'userrecaptcha',
    googlekey: sitekey,
    pageurl: pageurl,
    json: '1',
  });

  return poll(submitted.json('request'));   // the captcha ID
}

Parametre adına dikkat edin. reCAPTCHA googlekey ister, Turnstile ise turnstile metoduyla sitekey ister. Yanlışını göndermek genellikle bir ERROR_GOOGLEKEY yanıtının nedenidir.

function poll(id) {
  const url = SOLVER + '/res.php?key=' + KEY +
              '&action=get&json=1&id=' + id;

  // Roughly three minutes of headroom at five seconds a try.
  for (let i = 0; i < 36; i++) {
    sleep(5);
    const res = http.get(url);
    if (res.json('status') === 1) {
      return res.json('request');   // the token
    }
  }
  throw new Error('solve did not finish in time');
}

Bekleyen bir yanıt, sıfır durumuyla CAPCHA_NOT_READY olarak döner; bu yüzden döngü, herhangi bir yanıtı tamamlanmış saymak yerine status alanını kontrol eder. Sonuçlar yalnızca bir kez okunabilir; dolayısıyla token'ı aldığınızda saklayın.

Adım 2: setup aşamasında çözün

k6, setup'ı herhangi bir sanal kullanıcı başlamadan önce bir kez çalıştırır ve döndürdüğü her şeyi default fonksiyonuna geçirir. Bunun tam olarak ihtiyaç duyduğu şekil budur. Orada çözün, token'ları dağıtın ve hiçbir VU kendi iterasyonu içinde bir çözüm için bedel ödemesin.

const PAGE = 'https://example.com/page-with-recaptcha';
const SITEKEY = 'YOUR_SITEKEY';

export const options = {
  vus: 10,
  duration: '90s',
  setupTimeout: '5m',   // the 60s default expires mid solve
};

export function setup() {
  // One token per VU. They are single use.
  const tokens = [];
  for (let i = 0; i < 10; i++) {
    tokens.push(solve(SITEKEY, PAGE));
  }
  return { tokens };
}

setupTimeout satırı göründüğünden daha önemlidir. k6, setup'a varsayılan olarak 60 saniye verir ve tek bir reCAPTCHA çözümü bunun büyük kısmını tek başına kullanabilir. Bunlardan on tanesi sığmaz, aşama öldürülür ve hata, bakacağınızı düşüneceğiniz herhangi bir şey yerine setup'ı suçlar.

Bunun üzerine inşa etmeden önce bilmeye değer sınır

Token'lar tek kullanımlıktır ve yaklaşık iki dakika geçerli kalır. Her iki yarısı da burada ısırır. Tek kullanımlık olması, korunan istekler kadar çok token'a ihtiyacınız olduğu anlamına gelir; dolayısıyla korumalı uç noktayı bin kez vuran bir test bin çözüm gerektirir ve artık bir yük testine benzemez. İki dakika ise, setup'ta çözdüğünüz token'ların ilk VU başladığında zaten yaşlanmakta olduğu anlamına gelir; dolayısıyla uzun bir soak testi, çalışmasının çoğunu süresi dolmuş olanları göndererek geçirir.

Yani bu desen, korumalı bir uç noktaya karşı kısa süreli bir yük patlamasına uyar, otuz dakikalık sürdürülebilir bir yüke değil. Bir reCAPTCHA token'ının ne kadar süre geçerli kaldığına dair yazı zamanlamaları içerir. Widget üzerinden sürdürülebilir yük gerekiyorsa, daha önceki allowlist yöntemi bunu elde etmenin tek dürüst yoludur.

Adım 3: çözücüyü metriklerinizin dışında tutun

k6’nın http modülüyle gönderdiğiniz her şey, çözücü çağrıları dahil, http_req_duration'a düşer. Sessizce on beş saniyelik bir yoklamayı içeren bir p95, üzerine hareket edebileceğiniz bir sayı değildir. Önemsediğiniz istekleri etiketleyin ve eşikleri o etikete yöneltin.

export const options = {
  vus: 10,
  duration: '90s',
  setupTimeout: '5m',
  thresholds: {
    // Measure the app, not the solve.
    'http_req_duration{target:app}': ['p(95)<500'],
  },
};

export default function (data) {
  const token = data.tokens[__VU - 1];

  http.post(PAGE, { 'g-recaptcha-response': token }, {
    tags: { target: 'app' },
  });
}

__VU değişkeni sanal kullanıcıları birden başlayarak numaralandırır; dolayısıyla token dizisini onunla indekslemek her VU'ya kendi token'ını verir. Etiketleme, çözümü k6'nın göremeyeceği bir yere taşımaktan daha temiz bir çözümdür; çünkü ne kadar sürdüklerini bilmek istediğinizde çözüm istekleri hâlâ çıktıda görünür.

Çözücü nerede durmalı

Yük üreticileri nadiren masaüstünüzdür. k6, CI'da, özel bir makinede veya yönetilen bir serviste çalışır; bunların hiçbirinde loopback adresi çözücünüzün bulunduğu makine değildir.

ModDinlediği adresNe zaman kullanılır
Yerel127.0.0.1, yalnızca o cihazk6 ve çözücü tek bir makinede
SunucuAğ adresiniz veya genel IP'nizCI, bir yük üretici filosu, yönetilen bir runner

Server modu, ikinci satırdaki her şeyin cevabıdır: uygulamadaki dinleme adresini değiştirin, betiği o host'a yönlendirin ve her üretici tek bir çözücüyü paylaşsın. Çağıranlar ağınızın dışındaysa sabit bir genel IP önerilir. Hâlâ sizin donanımınızdır ve hâlâ ölçüm bazlı ücretlendirilmez; dolayısıyla bu yalnızca çözücünün çalıştığı yeri değiştirir, başka bir şeyi değil. CapSkip bir Windows uygulamasıdır; yani bu, üreticilerin çağırdığı tek bir Windows makinesidir. Pratik bir not: onu test ettiğiniz aynı yük dengeleyicinin arkasına koymayın, yoksa kendi darboğazınızı iki kez ölçmüş olursunuz.

Yaygın hatalar

GördüğünüzNedenDüzeltme
‘capskip’ modülü bulunamıyork6 npm paketlerini çözümlemezBunun yerine API'yi k6’nın http modülüyle çağırın
setup() çalıştırması zaman aşımına uğradıÇözümler 60 saniyelik varsayılandan daha uzun sürdüHer çözümü kapsayacak şekilde setupTimeout'u yükseltin
p95 devasa ama hiçbir şey yavaş değilÇözücü çağrıları http_req_duration'a dahil edildiUygulama isteklerini etiketleyin ve eşiği filtreleyin
Sonraki iterasyonlar reddediliyor, ilkler sorunsuzToken'lar ömürlerinin ötesinde yaşlandıÇalıştırmayı kısaltın ya da daha az, daha geç çözün
Her VU aynı reddi alıyorVU'lar arasında yeniden kullanılan tek bir tokenVU başına bir tane çözün ve __VU ile indeksleyin

Kodların tam listesi ve her metodun aldığı parametreler şurada yer alır: CapSkip API dokümantasyonu.

FAQ

CapSkip SDK'sını k6'ya kurabilir miyim?

Hayır. k6, yerleşik modülleri, yerel dosyaları ve uzak betikleri işleyen kendi modül yükleyicisini uygular ve kasıtlı olarak Node’un çözümleme algoritmasını izlemez; dolayısıyla npm paketleri devre dışıdır. API 2captcha uyumludur; bu yüzden iki uç nokta, SDK'nın sizin için yapacağı her şeyi k6’nın kendi http modülünün yaklaşık on beş satırında karşılar.

Bunun yerine default fonksiyonunun içinde mi çözmeliyim?

Yalnızca test ettiğiniz şey çözümün kendisiyse. default fonksiyonu VU başına iterasyon başına bir kez çalışır; dolayısıyla iki dakika boyunca yirmi VU, yüzlerce çözüm demektir ve gecikme sayılarınız bir yoklama ölçümüne dönüşür. setup'ta çözün, token'ları dağıtın ve iterasyonu gerçekten önemsediğiniz isteğe ayırın.

k6'm yönetilen bir serviste çalışıyor. Çözücüye ulaşabilir mi?

Evet, Server modunda. Çözücü, loopback adresi yerine bir ağ adresinde dinler ve üreticiler onu diğer herhangi bir dahili servis gibi API üzerinden çağırır. Runner'lar ağınızın dışındaysa sabit bir genel IP bunu istikrarlı hale getirir. Anahtar doğrulamasını açın ve her ortama kendi anahtarını verin; böylece biri diğerlerine dokunmadan iptal edilebilir.

Bir widget üzerinden bir saat boyunca nasıl yük testi yaparım?

Yapmazsınız, en azından gerçek token'lar üzerinden değil. Tek kullanımlık olma artı iki dakikalık ömür, bir saatlik sürdürülebilir yükün kesintisiz bir çözüm akışına ihtiyaç duyduğu anlamına gelir; bu noktada test edilen sistem çözücünün kendisi olur. Kendi uygulamanız üzerinde uzun bir çalıştırma için, yük üreticisini doğrulamadan muaf tutun ve arkasındaki yolu test edin.

Kısa özet

k6’nın http modülünü in.php ve res.php'ye karşı kullanın, setupTimeout'u yükselterek setup aşamasında çözün, eşiklerin anlamlı kalması için uygulama isteklerinizi etiketleyin ve token'ların hâlâ canlı olacağı kadar kısa bir çalıştırma süresi tutun. Bunun crawl tarafı için bkz: web scraping için CAPTCHA çözücü sayfası. Yük testi, çözüm başına fiyatlandırmanın en hızlı saçmalaştığı yerdir, çünkü tek bir patlama, hiçbir iş değeri üretmeyen yüzlerce token gerektirebilir. Fiyatlandırma modeli işte tam farkı yaratan şeydir: captcha atlatma çalışması, zaten sahip olduğunuz donanımda, bir testi de kırk testi de çalıştırsanız aynı maliyete sahiptir.