Saját szolgáltatásainkat korlátoztuk sebességben
A Mythex API egy hálózati címről percenként 300 kérést enged. Ez a korlát azért van, hogy megvédjen minket attól, hogy egyetlen ember vagy szkript elárassza az API-t. Az éles környezetben viszont elkezdte visszautasítani a saját szolgáltatásainkat — az edge-ünk azon részét, amely a publikált appokat szolgálja ki, és az AI-ügynököt futtató szolgáltatást —, mert mindegyik csak néhány címről éri el az API-t. A belső hitelesítő adatunkat hordozó kérések most mentesülnek, mindenki más pontosan úgy korlátozott, mint korábban.
A tünet
Az API elkezdett néhány belső hívásunkra 429 Too Many Requests válasszal felelni. Három típusú hívást érintett, és mindegyik számít valakinek, aki a Mythexet használja:
- Annak kikeresése, melyik app van egyedi domainen. Amikor egy látogató egy publikált appot a saját domainjén nyit meg, az edge megkérdezi az API-tól, hol van az oldal. Egy 429 itt azt jelenti, hogy egy látogató nem éri el az oldalt.
- Egy futó ügynök-kör mentése. Amíg az ügynök dolgozik, a haladása menet közben mentésre kerül, hogy a válasz túlélje a frissítést vagy a megszakadt kapcsolatot. Egy 429 itt azt jelenti, hogy a haladás nem mentődött el.
- Az előnézet hozzáférésének ellenőrzése. Az épülő app előnézete védett, és a védelem az API-tól kérdez. Egy 429 itt azt jelenti, hogy az előnézet nem nyílik meg.
Ezek közül egyik sem volt külső ember, aki az API-t hívta. Mind mi voltunk.
Miért történt
A címenkénti sebességkorlát egy feltételezésre épül: egy cím körülbelül egy hívó. Embereknél ez elég közel áll az igazsághoz. A saját infrastruktúránknál ez nagyon rosszul áll.
- A publikált appokat és előnézeteket kiszolgáló edge-szolgáltatás néhány megosztott kimenő címről éri el az API-t. Minden látogató minden publikált appon, és minden előnézet-ellenőrzés úgy érkezik, mintha ezek közül az egyről jött volna.
- Az orchestrator — az a szolgáltatás, amely az ügynök-köröket futtatja — egyetlen konténercímről éri el az API-t. Minden futó kör, minden felhasználóé, ezt a címet osztja.
Az egy embernek szánt keret így egy egész szolgáltatás összes forgalma között oszlott el. Ezek a szolgáltatások közösen elhasználták, a korlátozó pedig azt tette, amire utasították: visszautasította őket.
A javítás
Szolgáltásaink már bizonyítják, kik ők. Minden belső hívás egy belső tokent hordoz, és az API belső részének minden útvonala ellenőrzi ezt a tokent, mielőtt bármit csinálna.
A sebességkorlátozó most ugyanazt az ellenőrzést használja. Egy olyan kérés, amelynek a tokenje egyezik a belső tokennel, egy engedélyezőlistán van, és nem számít bele a címenkénti keretbe. Minden más pontosan úgy számít, mint korábban: 300 kérés percenként címenként.
Két részlet akadályozta meg, hogy ebből kiskapu legyen:
- Hamis token nem kap kiváltságot. Az engedélyezőlista csak a valódi belső tokennel egyezik. Egy kitalált tokenes kérés beleszámít, és ugyanúgy korlátozódik, mint bármely más, a belső útvonalak pedig
401 Unauthorizedválasszal utasítják el. - A korlát maga nem változott. Nem emeltük a számot, hogy helyet csináljunk. A szám emelése elrejtette volna a problémát egészen addig, amíg a forgalom újra nem nő, és gyengítette volna a védelmet arra az esetre, amelyre a korlát való.
A korlátozó beállításait egy kis függvénybe tettük, és teszteket írtunk rá. Az egyik 20 kérést küld a belső tokennel egy olyan korlátozóhoz, amely 5-öt enged, és mind a 20-nak sikerülnie kell. Egy másik egyszerű kéréseket küld egy címről, és azt várja, hogy az első öt sikerüljön, az utána jövők pedig elutasításra kerüljenek. Egy harmadik hamisított tokennel küld kéréseket, és azt várja, hogy ugyanúgy utasítódjanak el.
Amit ebből tanultunk
- A korlátok feltételezéseket hordoznak. Az „egy cím, egy hívó” feltételezés be van építve a címenkénti korlátba. Megszűnik igaz lenni, amint a saját szolgáltatásaid megosztott címek mögött állnak — és sok ilyen van: terheléselosztók, edge-hálózatok, konténerek, irodai hálózatok.
- A saját forgalmat személyazonosság alapján különítsd el, ne cím alapján. A címek azt mutatják, hogyan érkezik a forgalom, nem azt, hogy ki küldte. Már volt egy hitelesítő adatunk, amely bizonyítja, hogy egy hívás a miénk; a korlátozó egyszerűen nem nézte.
- Ne a szám emelésével javítsd. Egy nagyobb korlát egy ideig megszüntette volna a 429-eseket, kevesebbet védett volna, és később újra elromlik.
- Nézd meg, kit korlátoznak. Egy olyan 429, amely a saját szolgáltatásodra esik, a korlátaidról szóló hibajelentés, nem a korlátozó működésének jele.
Mit jelent ez, ha a Mythexen építkezel
Nincs teendőd. A publikált appok egyedi domaineken, az ügynök-körök és az előnézetek már nem függnek attól, mennyire van tele a Mythex többi része. Az appod saját forgalma az appod dolga: az itt leírt korlát az API-nkon van, nem a publikált appjaidon.
Ha saját backendet futtatsz, ugyanez a csapda vonatkozik minden sebességkorlátra, amelyet hozzáadsz. Az mi az API és az AI-val épített appok biztonsági ellenőrzőlistája jó kiindulópont. Egy másik példáért, amikor a saját infrastruktúránk akadályozza magát, lásd: hogyan jutottunk nulla 502-es hibához a deployoknál.