Cara Memecahkan CAPTCHA dalam Load Test k6 dengan Raw API

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

Langkah CAPTCHA di k6 harus melalui raw HTTP API, karena k6 bukan Node dan SDK tidak bisa dipasang ke dalamnya. Itu bagian yang mudah: dua panggilan, submit dan poll. Bagian yang menentukan apakah pengujian Anda benar-benar berarti adalah di mana proses pemecahan berjalan. Letakkan di default function dan setiap virtual user memecahkan CAPTCHA di setiap iterasi, yang justru mengukur solver, bukan aplikasi Anda, dan membanjiri mesin yang tidak pernah dirancang untuk menanggung itu. Letakkan di tahap setup dan Anda mendapat angka yang bersih, dengan satu batasan jujur yang perlu Anda ketahui.

Apa yang Anda butuhkan

  • k6, versi terbaru mana pun. Tidak ada paket yang perlu dipasang, karena tidak ada tempat untuk memasangnya.
  • Sitekey dan URL halaman dari endpoint terproteksi yang sedang Anda uji.
  • CapSkip yang berjalan dalam Local mode jika k6 berjalan di komputer yang sama dengan solver, atau dalam Server mode jika berjalan di load generator atau di CI. Keduanya dijelaskan di pengaturan koneksi.

Kapan memecahkan CAPTCHA adalah pilihan yang tepat

Katakan ini dengan jelas sebelum menulis kode apa pun. Jika situs yang diuji adalah milik Anda sendiri, langkah yang lebih baik biasanya adalah membiarkan load generator melewati challenge-nya: masukkan alamatnya ke allowlist, atau kirim header yang dikenali oleh environment staging Anda, lalu lewati widget-nya sepenuhnya. Anda sedang berusaha mengukur aplikasi Anda sendiri, dan setiap challenge yang dipecahkan menambahkan latensi yang bukan milik Anda.

Memecahkan CAPTCHA adalah pilihan yang tepat dalam dua kasus. Endpoint yang perlu Anda tuju terproteksi dan Anda tidak mengendalikan proteksi itu, atau jalur yang terproteksi itu sendiri adalah yang sedang diuji, sehingga melewatinya berarti menguji rute yang tidak pernah dilalui trafik sungguhan. Keduanya nyata, dan keduanya adalah alasan sisa artikel ini ditulis.

Mengapa SDK tidak berfungsi di sini

Skrip k6 terlihat seperti JavaScript, tetapi tidak berjalan di atas Node. Implementasi require adalah milik k6 sendiri, dan dokumentasinya blak-blakan soal batasannya: ia memuat modul bawaan k6, file lokal, dan skrip jarak jauh, tetapi tidak mendukung algoritma resolusi modul Node. Tidak ada npm, tidak ada node_modules, tidak ada fs, dan tidak ada crypto. Jadi paket CapSkip tidak dapat diimpor, begitu juga apa pun yang lain yang mungkin Anda coba gunakan.

Ini lebih murah daripada kedengarannya. API-nya kompatibel dengan 2captcha dan punya dua endpoint, jadi modul http milik k6 sendiri sudah cukup untuk menanganinya dalam sekitar lima belas baris. Jika load generator Anda ternyata adalah proses Node biasa, halaman pemecah CAPTCHA Node.js mencakup klien yang memang memiliki SDK.

Langkah 1: tulis proses pemecahan sebagai fungsi biasa

Submit ke in.php, dapatkan ID-nya, lalu poll res.php sampai jawabannya datang. Minta format JSON supaya Anda membaca field, bukan memecah string pada karakter pipe.

// 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
}

Perhatikan nama parameternya. reCAPTCHA menginginkan googlekey, sementara Turnstile menginginkan sitekey dengan metode turnstile. Mengirim yang salah adalah penyebab umum respons ERROR_GOOGLEKEY.

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');
}

Jawaban yang masih tertunda akan kembali sebagai CAPCHA_NOT_READY dengan status nol, itulah sebabnya loop-nya memeriksa field status, bukan menganggap respons apa pun sebagai selesai. Hasilnya hanya bisa dibaca sekali, jadi simpan token-nya begitu Anda mendapatkannya.

Langkah 2: pecahkan CAPTCHA di tahap setup

k6 menjalankan setup satu kali, sebelum virtual user mana pun dimulai, dan meneruskan apa pun yang dikembalikannya ke default function. Itu persis bentuk yang dibutuhkan di sini. Pecahkan CAPTCHA di sana, bagikan token-tokennya, dan tidak ada VU yang menanggung biaya pemecahan di dalam iterasinya sendiri.

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 };
}

Baris setupTimeout lebih penting daripada kelihatannya. k6 memberi setup waktu 60 detik secara default, dan satu proses pemecahan reCAPTCHA saja bisa menghabiskan sebagian besar waktu itu. Sepuluh proses pemecahan jelas tidak akan muat, tahap setup akan dimatikan, dan errornya menyalahkan setup, bukan hal lain yang mungkin akan Anda periksa.

Batasan yang perlu Anda ketahui sebelum membangun di atas ini

Token hanya sekali pakai dan tetap valid selama kurang lebih dua menit. Kedua batasan ini sama-sama terasa di sini. Sekali pakai berarti Anda butuh token sebanyak jumlah permintaan yang terproteksi, jadi pengujian yang menghantam endpoint terjaga seribu kali membutuhkan seribu proses pemecahan dan sudah tidak lagi menyerupai load test. Dua menit berarti token yang Anda pecahkan di setup sudah mulai menua saat VU pertama dimulai, jadi soak test yang panjang akan menghabiskan sebagian besar durasinya untuk mengirim token yang sudah kedaluwarsa.

Jadi pola ini cocok untuk lonjakan singkat terhadap endpoint yang dilindungi, bukan soak selama tiga puluh menit. Artikel tentang berapa lama token reCAPTCHA tetap valid memuat rincian waktunya. Jika Anda memerlukan load berkelanjutan melalui widget, rute allowlist dari sebelumnya adalah satu-satunya cara jujur untuk mendapatkannya.

Langkah 3: jauhkan solver dari metrik Anda

Apa pun yang Anda kirim dengan modul http milik k6 akan tercatat di http_req_duration, termasuk panggilan ke solver. p95 yang diam-diam memasukkan poll selama lima belas detik bukan angka yang bisa Anda jadikan acuan. Beri tag pada permintaan yang benar-benar Anda pedulikan dan arahkan threshold ke tag tersebut.

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' },
  });
}

Variabel __VU menomori virtual user mulai dari satu, jadi mengindeks array token dengannya memberi setiap VU token miliknya sendiri. Pemberian tag adalah solusi yang lebih bersih daripada memindahkan proses pemecahan ke tempat yang tidak terlihat oleh k6, karena permintaan pemecahan tetap muncul di output saat Anda ingin tahu berapa lama waktu yang dibutuhkannya.

Di mana solver harus ditempatkan

Load generator jarang sekali berupa komputer desktop Anda sendiri. k6 berjalan di CI, di mesin khusus, atau di layanan terkelola, dan alamat loopback pada semua itu bukan mesin tempat solver Anda berada.

ModeMendengarkan diGunakan saat
Lokal127.0.0.1, hanya perangkat ituk6 dan solver di satu mesin yang sama
ServerAlamat jaringan atau IP publik AndaCI, sekumpulan load generator, runner terkelola

Server mode adalah jawaban untuk semua yang ada di baris kedua: ubah listen address di aplikasi, arahkan skrip ke host tersebut, dan setiap generator akan berbagi satu solver. IP publik statis disarankan kalau pemanggilnya berada di luar jaringan Anda. Tetap perangkat keras milik Anda dan tetap tanpa meteran biaya, jadi ini hanya memindahkan tempat solver berjalan, tidak ada yang lain. CapSkip adalah aplikasi Windows, jadi itu berarti satu mesin Windows yang dipanggil oleh generator-generator itu. Satu catatan praktis: jangan taruh solver di belakang load balancer yang sama dengan yang sedang Anda uji, atau Anda akan mengukur bottleneck Anda sendiri dua kali.

Kesalahan umum

Apa yang Anda lihatPenyebabPerbaiki
Cannot find module ‘capskip’k6 tidak me-resolve paket npmPanggil API menggunakan modul http milik k6 sebagai gantinya
Eksekusi setup() kehabisan waktuProses pemecahan berlangsung lebih lama dari default 60 detikNaikkan setupTimeout agar mencakup semua proses pemecahan
p95 sangat besar padahal tidak ada yang lambatPanggilan solver ikut terhitung di http_req_durationBeri tag pada permintaan aplikasi dan filter threshold-nya
Iterasi belakangan ditolak, yang awal baik-baik sajaToken sudah melewati masa berlakunyaPersingkat durasi run, atau pecahkan lebih sedikit token, belakangan
Setiap VU mendapat penolakan yang samaSatu token dipakai ulang di semua VUPecahkan satu token per VU dan indeks dengan __VU

Daftar lengkap kode dan parameter yang dibutuhkan setiap metode ada di dokumentasi API CapSkip.

FAQ

Bisakah saya memasang SDK CapSkip ke dalam k6?

Tidak. k6 memiliki module loader sendiri yang menangani modul bawaan, file lokal, dan skrip jarak jauh, dan secara sengaja tidak mengikuti algoritma resolusi milik Node, jadi paket npm tidak bisa dipakai. API-nya kompatibel dengan 2captcha, jadi kedua endpoint itu mencakup semua yang akan dilakukan SDK untuk Anda, dalam sekitar lima belas baris modul http milik k6 sendiri.

Haruskah saya memecahkan CAPTCHA di dalam default function sebagai gantinya?

Hanya jika proses pemecahan itu sendiri yang sedang Anda uji. Default function berjalan sekali per iterasi per VU, jadi dua puluh VU selama dua menit berarti ratusan proses pemecahan, dan angka latensi Anda berubah menjadi ukuran polling semata. Pecahkan di setup, bagikan token-tokennya, dan biarkan iterasi hanya berisi permintaan yang benar-benar Anda pedulikan.

k6 saya berjalan di layanan terkelola. Bisakah ia menjangkau solver?

Ya, dalam Server mode. Solver akan listen di alamat jaringan, bukan alamat loopback, dan generator-generator memanggilnya lewat API seperti layanan internal lainnya. IP publik statis membuat ini stabil ketika runner berada di luar jaringan Anda. Aktifkan validasi key dan beri setiap environment key miliknya sendiri, sehingga satu key bisa dicabut tanpa mengganggu yang lain.

Bagaimana cara melakukan load test melalui widget selama satu jam?

Anda tidak melakukannya, setidaknya tidak lewat token asli. Sekali pakai ditambah masa berlaku dua menit berarti satu jam load berkelanjutan membutuhkan aliran proses pemecahan yang terus-menerus, dan pada titik itu solver-lah yang menjadi sistem yang sedang diuji. Untuk run yang panjang pada aplikasi Anda sendiri, bebaskan load generator dari challenge dan uji jalur di baliknya.

Versi singkatnya

Gunakan modul http milik k6 untuk mengakses in.php dan res.php, pecahkan CAPTCHA di setup dengan setupTimeout yang sudah dinaikkan, beri tag pada permintaan aplikasi Anda supaya threshold tetap bermakna, dan jaga agar run cukup singkat sehingga token-tokennya masih hidup. Untuk sisi crawling dari ini, lihat halaman pemecah CAPTCHA untuk web scraping. Load testing adalah tempat penetapan harga per pemecahan menjadi paling tidak masuk akal, karena satu lonjakan saja bisa membutuhkan ratusan token yang sama sekali tidak menghasilkan nilai bisnis. Perbedaan model harganya ada di sini: bypass captcha yang berjalan di atas perangkat keras yang sudah Anda miliki tetap sama biayanya, baik Anda menjalankan satu pengujian maupun empat puluh.