Gambaran:
Perusahaan saya telah mengembangkan API dengan tarif terbatas. Tujuan kami ada dua:
- J: Ciptakan ekosistem pengembang yang kuat di sekitar produk kami.
- B: Mendemonstrasikan kekuatan API kami dengan menggunakannya untuk menjalankan aplikasi kami sendiri.
Klarifikasi: Mengapa rate-limit sama sekali?
Kami menilai batas API kami, karena kami menjualnya sebagai tambahan untuk produk kami. Akses anonim ke API kami memiliki ambang yang sangat rendah untuk panggilan API per jam, sedangkan pelanggan berbayar kami diizinkan lebih dari 1000 panggilan per jam atau lebih.
Masalah:
API terbatas tarif kami sangat bagus untuk ekosistem pengembang, tetapi agar kami dapat melakukan dogfood, kami tidak dapat mengizinkannya dibatasi ke pembatasan tarif yang sama. Bagian depan API kami adalah semua JavaScript, membuat panggilan Ajax langsung ke API.
Jadi pertanyaannya adalah:
Bagaimana Anda mengamankan api sehingga pembatasan kecepatan dapat dihapus di mana dalam proses menghapus pembatasan kecepatan tidak dapat dengan mudah dipalsukan?
Solusi yang Dijelajahi (dan mengapa tidak berhasil)
Verifikasi perujuk terhadap header host. - Cacat karena perujuk mudah dipalsukan.
Gunakan HMAC untuk membuat tanda tangan berdasarkan permintaan dan rahasia bersama, lalu verifikasi permintaan di server. - Cacat karena rahasia dan algoritme akan mudah ditentukan dengan melihat ke JavaScript front end.
Proksi permintaan dan tanda tangani permintaan di proxy - Masih cacat, karena proxy itu sendiri mengekspos API.
Pertanyaan:
Saya mencari pemikiran brilian di Stack Overflow untuk menyajikan solusi alternatif. Bagaimana Anda mengatasi masalah ini?
sumber
Jawaban:
Karena klien JavaScript Anda mengakses API secara langsung, siapa pun akan dapat melihat apa yang dilakukannya dan menirunya, termasuk menggunakan kunci API yang sama. Anda dapat mencoba membuatnya lebih sulit, seperti dengan mengaburkan kode Anda atau meletakkan berbagai rintangan di jalan, tetapi Anda dan orang yang Anda coba tahan pada dasarnya memiliki akses yang sama. Alih-alih mencoba membuat perbedaan dalam hak istimewa, Anda harus membangun sistem di mana tidak apa-apa bahwa klien tidak resmi menggunakan semua akses dalam cakupannya, tetapi sistem diatur sedemikian rupa sehingga penggunaan resmi di semua klien diatur. lebih besar.
Ini sering dilakukan dengan token akses per pengguna, bukan satu token untuk seluruh aplikasi. Setiap batas token seharusnya cukup untuk penggunaan umum API Anda, tetapi membatasi bagi seseorang yang mencoba menyalahgunakannya. Misalnya, 100 panggilan per menit mungkin lebih dari cukup untuk mendukung penjelajahan biasa, tetapi jika saya ingin membatalkannya, saya tidak dapat melakukannya secara efektif dengan anggaran itu.
Akan selalu ada perlombaan senjata - saya bisa menyiasati batas dengan membuat banyak akun pengguna bot. Itu, bagaimanapun, adalah masalah yang cukup terpecahkan jika Anda hanya menambahkan captcha ke aliran pendaftaran Anda, dengan sedikit biaya bagi manusia yang sebenarnya. Ketika Anda masuk ke dalam skenario ini, semuanya hanyalah pertukaran antara kenyamanan dan pembatasan. Anda tidak akan pernah menemukan sesuatu yang benar-benar antipeluru, jadi fokuslah untuk membuatnya cukup baik dan tunggu sampai seseorang mengeksploitasi Anda untuk mengetahui di mana lubangnya.
sumber
Jika hal ini menyebabkan masalah bagi Anda, hal ini akan menyebabkan masalah pada ekosistem diduga pengembang Anda (misalnya, saat mereka mencoba mengembangkan UI alternatif). Jika Anda benar-benar memakan makanan anjing Anda sendiri, buat API (dan pembatasan kecepatan) berfungsi untuk aplikasi Anda. Berikut adalah beberapa saran:
Jangan menilai batas berdasarkan alamat IP. Melainkan, batas tarif oleh sesuatu yang terkait dengan pengguna, misalnya ID pengguna mereka. Terapkan batas tarif pada tahap otentikasi.
Rancang API Anda sehingga pengguna tidak perlu memanggilnya terus menerus (mis. Memberikan panggilan daftar yang mengembalikan banyak hasil, daripada panggilan berulang yang mengembalikan satu item setiap kali)
Rancang aplikasi web Anda dengan batasan yang sama dengan yang Anda harapkan dari ekosistem pengembang Anda, yaitu memastikan Anda dapat merancangnya dalam tingkat pembatasan yang wajar.
Pastikan back end Anda dapat diskalakan (lebih disukai secara horizontal) sehingga Anda tidak perlu memaksakan pembatasan pada level yang sangat rendah sehingga menyebabkan masalah pada UI.
Pastikan pelambatan Anda memiliki kemampuan untuk mengatasi semburan, serta membatasi penyalahgunaan jangka panjang.
Pastikan pembatasan Anda melakukan tindakan yang masuk akal yang disesuaikan dengan penyalahgunaan yang ingin Anda hapus. Misalnya, pertimbangkan untuk mengantri atau menunda pelaku kekerasan ringan daripada menolak koneksi. Sebagian besar ujung depan web hanya akan membuka empat koneksi simultan sekaligus. Jika Anda menunda upaya untuk membuka yang kelima, Anda hanya akan menemukan kasus di mana mereka menggunakan CLI pada saat yang sama dengan klien web (atau dua klien web). Jika Anda menunda panggilan API ke-n tanpa jeda daripada gagal, pengguna akhir akan melihat segalanya melambat daripada rusak. Jika Anda menggabungkan ini dengan hanya mengantri panggilan N API sekaligus, Anda hanya akan menyerang orang yang memparalelkan sejumlah besar panggilan API, yang mungkin bukan perilaku yang Anda inginkan - misalnya 100 panggilan API simultan maka jarak selama satu jam biasanya jauh lebih buruk dari 100 panggilan API berurutan selama satu jam.
Apakah ini tidak menjawab pertanyaan Anda? Nah, jika Anda benar - benar perlu melakukan apa yang Anda minta, rate-limit pada tahap otentikasi dan terapkan batas rate yang berbeda berdasarkan grup yang cocok dengan pengguna Anda. Jika Anda menggunakan satu set kredensial (digunakan oleh tim pengembang dan QA Anda), Anda mendapatkan batas tarif yang lebih tinggi. Tetapi Anda dapat segera melihat mengapa ini pasti akan membawa Anda ke ekosistem Anda melihat masalah yang tidak dilihat oleh tim pengembang dan QA Anda.
sumber
Beli produk Anda. Jadilah pelanggan berbayar Anda sendiri.
"Akses anonim ke API kami memiliki ambang yang sangat rendah untuk panggilan API per jam, sedangkan pelanggan berbayar kami diizinkan lebih dari 1000 panggilan per jam atau lebih."
Ini juga membantu menguji sistem dari perspektif pelanggan.
sumber
Sayangnya, tidak ada solusi yang tepat untuk ini.
Pendekatan umum biasanya memberikan spoofablecara bagi klien untuk mengidentifikasi diri mereka sendiri (mis. pengenal, versi, dan kunci API - misalnya), bagi klien untuk mendaftarkan informasi tentang diri mereka sendiri yang dapat digunakan untuk membatasi akses (mis. klien adalah server dalam kisaran alamat IP tertentu, jadi hanya izinkan penelepon dalam rentang itu; misalnya klien adalah JavaScript, tetapi dikirim hanya ke kategori browser tertentu, jadi hanya izinkan akses ke permintaan HTTP yang menentukan string agen pengguna tertentu; dll.), lalu menggunakan pembelajaran / pola mesin pengakuan untuk mendeteksi penggunaan yang tidak wajar yang kemungkinan merupakan klien palsu dan kemudian menolak lalu lintas dari klien palsu ini (atau mengonfirmasi dengan klien bahwa penggunaan ini memang tidak berasal dari klien yang sah, ganti kredensial palsu mereka, dan kemudian larang lalu lintas lebih lanjut menggunakan yang lebih lama kredensial palsu).
Anda dapat membuatnya sedikit lebih sulit untuk melakukan spoof dengan menggunakan banyak lapisan kunci. Misalnya, Anda memberikan kredensial yang berumur lebih lama yang berada di server (dan itu hanya dapat digunakan dalam rangkaian terbatas rentang alamat IP) untuk membuat panggilan API yang mencatat informasi tentang klien (misalnya agen pengguna) dan mengembalikan kunci sisi klien yang berumur lebih pendek yang disindikasikan dalam JavaScript untuk digunakan pada klien untuk permintaan API sisi klien. Ini juga tidak sempurna (spoofer dapat mengeluarkan panggilan server yang sama untuk mendapatkan kredensial), tetapi akan lebih sulit jika kunci API yang dikembalikan disertakan dalam JavaScript atau HTML yang dikaburkan (dan sering berubah) (yang akan menyulitkan untuk mengekstrak dengan andal dari respons). Itu juga menyediakan cara untuk mendeteksi spoofing dengan lebih mudah; kunci sisi klien sekarang terikat ke klien tertentu (mis
sumber
Dengan asumsi aplikasi yang dipermasalahkan harus terbuka untuk umum, Anda tidak punya banyak pilihan:
Pilih cara lain untuk mendemonstrasikan kekuatan API Anda. Misalnya, tulis aplikasi semacam itu dan bagikan sumbernya, tetapi jangan benar-benar menjalankan kode itu. Pastikan itu didokumentasikan dengan baik, sehingga siapa pun dapat menerapkannya dan melihatnya berfungsi (tunduk pada pembatasan).
Aplikasi yang Anda jalankan perlu difaktorkan ulang untuk menghindari permintaan API sisi klien dan lebih banyak dirender server. Anda masih dapat melakukan dogfood pada API Anda, tetapi tidak dengan cara yang jelas — membuat permintaan yang aman ke API yang bebas hambatan dari sisi server.
Sesuaikan batasan tarif agar aplikasi Anda dapat bekerja dan berinvestasi pada pengoptimalan kinerja untuk menangani beban.
Dan ya, pertama-tama miliki API inti yang bebas throttle, dan simpan di dalam jaringan pribadi. Batasi dalam lapisan terpisah yang dapat diakses publik.
sumber
Dapatkah Anda membuat instance terpisah dari UI dan API bebas hambatan, lalu membatasi akses ke alamat IP yang berasal dari organisasi Anda?
Misalnya, terapkan semuanya di belakang firewall perusahaan Anda, dan lampirkan aplikasi ke database yang sama dengan instance publik jika Anda perlu berbagi data antar instance.
sumber
Anda dapat mencoba membuat ID sesi unik, terikat ke alamat IP / pengguna tertentu dan waktu terbatas untuk aktif. Saat pengguna mendownload kode JavaScript frontend aplikasi Anda, masukkan ID sesi yang dihasilkan ke dalam kode sumber JavaScript. ID sesi akan dilampirkan ke setiap permintaan ke API Anda dan batas tarif dicabut.
ID tidak dapat disalin begitu saja untuk spoofing, karena hanya berlaku untuk satu alamat IP, pengguna, dan waktu yang terbatas. Jadi musuh harus memanggil halaman Anda dan memfilter kunci dari sumber JavaScript Anda atau dari mencegat permintaan Ajax setiap kali pengguna baru ingin menggunakannya.
Pilihan lain:
Siapkan proxy untuk aplikasi Anda sendiri dan gunakan obfuscation. Permintaan Ajax ke proxy menggunakan nama yang berbeda dari panggilan API yang sebenarnya dan proxy menerjemahkannya kembali. Jadi aplikasi Anda tidak akan memanggil
getDocument
API asli Anda, tetapi akan memanggilgetFELSUFDSKJE
proxy Anda. Proksi akan menerjemahkan panggilan ini kembali ke getDocument dan meneruskannya ke API terbatas tarif yang sebenarnya.API Anda yang sebenarnya tidak akan membatasi permintaan oleh proxy.
Dan agar orang lain tidak menggunakan proxy Anda untuk aplikasi mereka sendiri, Anda mengubah skema obfuscation setiap hari. Nama panggilan yang dikaburkan dapat dibuat secara otomatis di kode sumber JavaScript Anda dan dikonfigurasi di proxy.
Klien yang ingin menggunakan ini, juga perlu mengikuti perubahan kebingungan Anda untuk menggunakan proxy Anda. Dan Anda masih bisa menggunakan referrer-headers dan sejenisnya untuk logging, jadi Anda bisa menemukan orang yang menggunakan proxy Anda. Atau tangkap mereka saat mengubah skema obfuscation.
sumber
sumber
Siapkan beberapa akun, dan pilih salah satunya secara acak di setiap permintaan, atau ubah akun mana yang Anda gunakan setiap jam atau lebih. Dengan cara ini Anda dapat mendistribusikan beban ke
n
akun, memberi Andan
batas kali lebih tinggi.Berhati-hatilah agar tidak menonaktifkan diri Anda secara tidak sengaja jika Anda mencoba menemukan pengguna lain melakukan ini, jika tidak diizinkan untuk pelanggan.
sumber