Dogfooding наш власний API з обмеженою швидкістю


117

Огляд:

Моя компанія розробила API з обмеженою швидкістю. Наша мета подвійна:

  • A: Створіть міцну екосистему розробника навколо нашого продукту.
  • B: Продемонструйте потужність нашого API, використовуючи його для керування власним додатком.

Пояснення: навіщо взагалі обмеження ставки?

Ми обмежуємо свій API, оскільки продаємо його як додаток до нашого продукту. Анонімний доступ до нашого API має дуже низький поріг для дзвінків API на годину, тоді як нашим платним клієнтам дозволено більше 1000 дзвінків на годину або більше.

Проблема:

Наш API з обмеженою швидкістю відмінно підходить для екосистеми розробників, але для того, щоб ми могли їсти собачі корми, ми не можемо дозволити його обмежувати тим же обмеженням швидкості. Передній кінець нашого API - це всі JavaScript, які здійснюють прямі дзвінки Ajax до API.

Тож питання:

Як убезпечити api, щоб обмеження швидкості можна було зняти, коли в процесі видалення такого обмеження швидкості не можна легко підробити?

Досліджені рішення (і чому вони не працювали)

  1. Перевірте реферала проти заголовка хоста. - Помилка, оскільки референт легко підробляється.

  2. Використовуйте HMAC для створення підпису на основі запиту та загальної таємниці, а потім перевірити запит на сервері. - Помилково, оскільки секрет та алгоритм легко визначити, заглянувши в JavaScript на передньому кінці.

  3. Проксі-сервер і підпишіть запит у проксі-сервері - все-таки помилково, оскільки сам проксі виставляє API.

Питання:

Я дивлюся на блискучі уми на Stack Overflow, щоб представити альтернативні рішення. Як би ви вирішили цю проблему?


13
Ви не можете. Якщо власне використання API, яке ви не хочете обмежувати обмеженням тарифів, відбувається лише з загальнодоступних веб-сторінок, то ви не можете зробити нічого захищеного від цих загальнодоступних веб-сторінок, оскільки, як вам здається, ви вже знаєте, ніяких секретів на публічних веб-сторінках. Отже, що ви можете робити на своїх веб-сторінках, так може зробити і будь-хто інший.
jfriend00

28
Ви впевнені, що у вас є проблема з обмеженням ставок, яку потрібно вирішити у вживанні собачих продуктів? Кожен користувач, який використовує ваш веб-сайт та ваші веб-сторінки, повинен виглядати зовсім іншим користувачем, який обмежує ваш тарифний код. Таким чином, просто переконайтеся, що кожна веб-сторінка живе за нормальними правилами обмеження тарифів самі по собі, і вам слід добре. Якщо припустити, що обмеження вашої ставки призначено для кожного клієнта, один користувач не матиме нічого спільного з будь-яким іншим користувачем.
jfriend00

6
Чому б вам не розглянути рішення щодо управління API, яке забезпечує обмеження швидкості та зменшення швидкості для кожного користувача, ролі / дозволу чи області застосування. Напр. Wso2 api manger
MiddlewareManiac


28
У вашому дог-фуді виявлено значну проблему з вашим загальнодоступним API (який полягає в тому, що обмеження швидкості занадто низьке), і замість того, щоб виправити це, ви намагаєтесь його обійти. Навіщо їжа, якщо ви збираєтесь ігнорувати проблеми, які ви знайдете?
користувач253751

Відповіді:


93

Оскільки ваш власний клієнт JavaScript здійснює прямий доступ до API, будь-хто зможе подивитися, що він робить, і імітувати його, в тому числі використовувати той самий ключ API. Ви можете спробувати зробити це складніше, наприклад, забруднюючи свій код або вкладаючи різні перешкоди, але ви і людина, яку ви намагаєтесь стримати, мають принципово однаковий доступ. Замість того, щоб намагатися створити різницю у привілеях, вам потрібно буде побудувати систему там, де цілком нормально, що неофіційний клієнт використовує весь доступ у своєму обсязі, але система влаштована таким чином, що офіційне використання для всіх клієнтів більший.

Це часто робиться за допомогою жетонів доступу для кожного користувача, на відміну від одного маркера для всієї програми. Обмеження кожного маркера має бути достатньо для типового використання вашого API, але обмежувальним для тих, хто намагається ним зловживати. Наприклад, 100 дзвінків в хвилину може бути і більш ніж достатньо для підтримки типового перегляду, але якщо я хочу скребти вас, я не можу це зробити ефективно за цим бюджетом.

Завжди буде гонка озброєнь - я можу обійти межу, створивши безліч облікових записів користувачів ботів. Це, однак, є досить вирішеною проблемою, якщо ви просто додасте капчу до свого реєстраційного потоку з невеликими витратами на реальну людину. Коли ви потрапляєте у ці сценарії, все є лише компромісом між зручністю та обмеженням. Ви ніколи не знайдете щось абсолютно безшовне, тому зосередьтеся на тому, щоб зробити його досить хорошим, і зачекайте, коли хтось використає вас, щоб дізнатися, де були отвори.


8
Прийнявши це як найкращу відповідь. Маршрут, який ми вирішили пройти, - це використовувати маркери JWT з меншим терміном дії та збільшити ліміт тарифів для цих дзвінків. Ми будемо кодувати деяку додаткову інформацію в токені, щоб повідомити бекенде про вищу межу швидкості. Оскільки ці лексеми підписані надійно на бекенде, не повинно виникнути проблем із підробкою. Хтось все ще може використовувати маркер, але термін його дії закінчується через кілька днів, і для цього підтримка будь-якого бота буде складніше зробити.
Джейсон Уолдріп

33

Якщо це спричинить у вас проблему, це спричинить проблему вашої передбачуваної екосистеми розробників (наприклад, коли вони намагаються розробити альтернативний інтерфейс користувача). Якщо ви дійсно їсте власний корм для собак, примусьте API (і обмеження ставок) працювати на вашу заявку. Ось кілька пропозицій:

  • Не оцінюйте обмеження за IP-адресою. Скоріше, обмежте ставку чимось пов’язаним із користувачем, наприклад, його ідентифікатором користувача. Застосуйте обмеження швидкості на етапі аутентифікації.

  • Створіть свій API так, щоб користувачам не потрібно було дзвонити йому постійно (наприклад, надіслати список дзвінків, який повертає багато результатів, а не повторний дзвінок, який щоразу повертає один елемент)

  • Створіть свій веб-додаток з тими ж обмеженнями, які ви очікуєте від екосистеми розробника, тобто переконайтеся, що ви можете спроектувати його в розумних швидкостях скорочення.

  • Переконайтесь, що ваш задній кінець є масштабованим (бажано по горизонталі), тому вам не потрібно накладати заглушку на таких низьких рівнях, що насправді спричиняє проблеми з інтерфейсом користувача.

  • Переконайтесь, що ваше дроселювання має можливість справлятися зі сплесками, а також обмежувати триваліші зловживання.

  • Переконайтесь, що ваше дроселювання виконує розумні дії, пристосовані до зловживань, які ви хочете усунути. Наприклад, розглянути питання про чергу чи затримку легких зловживань, а не відмовлятися від з'єднання. Більшість передніх кінців веб відкриють лише чотири одночасних з'єднання одночасно. Якщо ви затримаєте спробу відкрити п'яту, ви потрапляєте лише у випадку, коли вони використовують CLI одночасно з веб-клієнтом (від двох веб-клієнтів). Якщо затримати n-й виклик API без розриву, а не відмовити його, кінцевий користувач побачить, що все сповільнюється, а не переривається. Якщо ви поєднаєте це одночасно лише з викликами N API, ви будете вражати лише людей, які паралелізують велику кількість викликів API, що, мабуть, не така поведінка, яку ви хочете - наприклад, 100 одночасних дзвінків API, тоді розрив на годину зазвичай далеко гірше 100 послідовних дзвінків API протягом години.

Це не відповіло на ваше запитання? Добре, якщо вам дійсно потрібно робити те, що ви просите, обмежте ставку на етапі аутентифікації та застосуйте інший ліміт швидкості на основі групи, в яку підходить ваш користувач. Якщо ви використовуєте один набір облікових даних (які використовуються вашими розробниками та командою з контролю якості), ви отримуєте більш високий ліміт ставок. Але ви можете відразу зрозуміти, чому це неминуче призведе вас до вашої екосистеми, побачивши проблеми, яких не бачать ваш розробник та команда з контролю якості.


11

Купуйте свій товар. Станьте собі платним клієнтом.

"Анонімний доступ до нашого API має дуже низький поріг для дзвінків API за годину, тоді як нашим платним клієнтам дозволено перевищувати 1000 дзвінків на годину або більше".

Це також допомагає перевірити систему з погляду замовника.


1
Очевидна відповідь. Тут немає жодного обману чи підробки!
wizzwizz4

9

На жаль, ідеального рішення для цього немає.

Загальний підхід, як правило, полягає в тому, щоб забезпечити підроблянняспосіб клієнтів ідентифікувати себе (наприклад, ідентифікатор, версія та ключ API - наприклад), щоб клієнти могли зареєструвати інформацію про себе, яку можна використовувати для обмеження доступу (наприклад, клієнт - це сервер у заданому діапазоні IP-адрес, тому дозволяйте лише тим, хто телефонує в цьому діапазоні; наприклад, клієнт - JavaScript, але доставляється лише до певної категорії браузера, тому дозволяйте доступ лише до запитів HTTP, які визначають певні рядки агента користувача; тощо), а потім використовувати машинне навчання / шаблон розпізнавання для виявлення аномального використання, яке, ймовірно, підроблений клієнт, а потім відхилення трафіку від цих підроблених клієнтів (або підтвердження з клієнтами, що ці звичаї дійсно не надходять від законного клієнта, замініть їх підроблювальні дані, а потім заборонити подальший трафік за допомогою старшого підроблені повноваження).

Ви можете зробити його трохи складніше підробляти, використовуючи кілька шарів ключа. Наприклад, ви видаєте довговічний обліковий запис, який живе на сервері (і який може використовуватися лише в обмеженому наборі діапазонів IP-адрес) для здійснення виклику API, який записує інформацію про клієнта (наприклад, агент користувача) та повертає короткочасний клієнтський ключ, який синхронізується в JavaScript для використання на клієнті для запитів API на стороні клієнта. Це теж недосконало (спофір може видати той самий виклик сервера, щоб отримати обліковий запис), але буде складніше, якщо повернутий ключ API буде включений у затуплений (і часто мінливий) JavaScript або HTML (що ускладнить роботу надійно витягнути з відповіді). Це також дає спосіб легше виявити підробку; ключ на стороні клієнта тепер прив’язаний до конкретного клієнта (наприклад,


8

Якщо припустити, що програма має бути відкрито відкритою, у вас немає великого вибору:

Виберіть інший спосіб продемонструвати потужність свого API. Наприклад, написати таку програму та поділитися її джерелом, але насправді не запускати цей код. Переконайтеся, що він добре задокументований, щоб кожен міг розгорнути його та побачити його справний (за умови дроселювання).

Програму, яку ви запускаєте, потрібно буде відновити, щоб уникнути запитів API на стороні клієнта та отримати більше сервера. Ви все ще можете випробовувати свій API, але не очевидним способом - робити безпечні запити на безкоштовний API з боку сервера.

Відрегулюйте обмеження швидкості, щоб ваша програма працювала та інвестувала в оптимізацію продуктивності для управління навантаженням.

І так, майте в першу чергу основну програму API без дроселів і зберігайте її всередині приватної мережі. Дросель в окремому загальнодоступному шарі.


4

Чи можете ви виділити окремий екземпляр інтерфейсу користувача та інтерфейсу без дроселів, а потім обмежити доступ до IP-адрес, що надходять від вашої організації?

Наприклад, розгорніть все за корпоративної брандмауером та додайте додаток до тієї ж бази даних, що й екземпляр, що звертається до публічного, якщо вам потрібно обмінюватися даними між екземплярами.


4

Ви можете спробувати створити унікальний ідентифікатор сеансу, прив’язаний до певної IP-адреси / користувача та обмежений час життя. Коли користувач завантажує вашу програму з фронтального коду JavaScript, введіть створений ідентифікатор сеансу у вихідний код JavaScript. Ідентифікатор сеансу буде доданий до кожного запиту до вашого API і ліміт ставок буде знято.

Ідентифікатор не може бути просто скопійований для підробки, оскільки він дійсний лише для однієї IP-адреси, користувача та обмежений час. Тож противнику доведеться зателефонувати на вашу сторінку та відфільтрувати ключ із вашого джерела JavaScript або перехопити запит Ajax кожного разу, коли новий користувач захоче ним скористатися.

Ще один варіант:

Налаштуйте проксі-сервер для власної програми та використовуйте притуплення. Запити Ajax до проксі використовують різні імена від реальних API-викликів, а проксі переводить їх назад. Таким чином, ваша програма не закликає getDocumentваш справжній API, але зателефонує getFELSUFDSKJEна ваш проксі. Проксі-сервер переведе цей виклик назад в getDocument та переправить його в фактичний API з обмеженою швидкістю.

Ваш фактичний API не буде обмежувати запит на отримання проксі.

І щоб інші люди не використовували ваш проксі для власної програми, ви щодня змінюєте схему обфускування. Забруднені імена викликів можна генерувати автоматично у вихідному коді JavaScript та конфігурувати у проксі.

Клієнт, який бажає скористатися цим, також повинен бути в курсі змін, що змінюються, щоб використовувати ваш проксі. І ви все ще можете використовувати заголовки рефералів та подібні для ведення журналів, щоб ви могли знайти людей, які використовують ваш проксі. Або ловити їх при зміні схеми затухання.


3
  • IP-адреси джерела білого списку
  • Використовуйте VPN , білий список членів VPN
  • Проксі-рішення або додаток до браузера, який додає заголовки HTTP, повинні бути добре, якщо ви можете захистити проксі-сервер і не переймаєтесь тим, що MITM- атаки нюхають трафік
  • Будь-яке рішення, що включає секрети, може пом'якшити вплив витоків, обертаючи секрети щодня

Ці рішення не поширюються на веб-клієнт передньої частини. Ідеально, якщо доступ до API був у бекенді.
Джейсон Уолдріп

@jason вони можуть бути застосовані до інтернету
the8472

2

Налаштуйте кілька облікових записів і виберіть один із них навмання на кожен запит або змініть, яким ви користуєтесь щогодини або близько того. Таким чином ви можете розподілити навантаження на nрахунки, що дає вам в nрази більше лімітів.

Будьте обережні, щоб випадково закрити себе, якщо ви намагаєтеся знайти інших користувачів, які роблять це, якщо це заборонено для клієнтів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.