Gateway
محدودسازی نرخ
Gateway چندین محدودیت نرخ مستقل را اعمال میکند. این محدودیتها از مرزهای متفاوتی محافظت میکنند، بر اساس هویتهای متفاوتی کلیدگذاری میشوند و با قالبهای خطای متفاوتی شکست میخورند. این صفحه مرجع همه آنها است.
در یک نگاه:
| سطح | محدودیت (پیشفرض) | کلیدگذاری بر اساس | قابل پیکربندی |
|---|---|---|---|
| احراز هویت ناموفق (توکن/رمز عبور/دستگاه) | 10 شکست / 60s، قفلشدن 5 min | IP + دامنه اعتبارنامه | gateway.auth.rateLimit |
| شکست احراز هویت WS با مبدأ مرورگر | همان، loopback مستثنا نیست | IP، یا مبدأ صفحه از loopback | gateway.auth.rateLimit |
شکست احراز هویت Webhook (/hooks) |
20 شکست / 60s، قفلشدن 60s | IP | خیر |
| RPCهای نوشتن صفحه کنترل | 30 درخواست / 60s برای هر متد | متد + دستگاه + IP | خیر |
| ایجاد نشست ACP | 120 نشست / 10s | نمونه مترجم | داخلی |
| چرخههای راهاندازی مجدد Gateway | فاصله 30s میان راهاندازیهای مجدد | فرایند | خیر |
تلاشهای احراز هویت (پیش از احراز هویت)
تلاشهای ناموفق احراز هویت، پیش از هرگونه پردازش درخواست و بهازای IP هر کلاینت محدود میشوند. این سازوکار محافظ جستوجوی فراگیر برای Gatewayهای در معرض دسترسی است.
- فقط اعتبارنامههای نادرست محاسبه میشوند. اعتبارنامههای مفقود (کلاینتی که هرگز توکنی ارسال نکرده است) و احراز هویتهای موفق بودجه را مصرف نمیکنند؛ یک احراز هویت موفق شمارنده آن IP را بازنشانی میکند.
- پیشفرضها: 10 شکست در هر 60 ثانیه، سپس قفلشدن 5 دقیقهای برای آن IP.
- Loopback (
127.0.0.1/::1) بهطور پیشفرض مستثنا است تا نشستهای محلی CLI قفل نشوند. - شمارندهها بهازای هر رده اعتبارنامه دامنهبندی میشوند، بنابراین هجوم علیه یک سطح سطح دیگری را کنار نمیزند. دامنهها شامل توکن/رمز عبور مشترک Gateway، توکنهای دستگاه، جفتسازی Node، تأیید مجدد Node جفتشده، توکنهای راهاندازی اولیه دستگاه و صدور چالش watchOS هستند.
در مدت قفلشدن، تلاشهای اتصال با خطای زیر شکست میخورند:
{ "code": "INVALID_REQUEST", "message": "unauthorized: too many failed authentication attempts (retry later)", "retryable": true, "retryAfterMs": 297000, "details": { "code": "AUTH_RATE_LIMITED", "authReason": "rate_limited", "recommendedNextStep": "wait_then_retry" }}تلاشها از IPهای دیگر (از جمله loopback) در مدت قفلشدن تحت تأثیر قرار نمیگیرند.
آن را در gateway.auth.rateLimit درون openclaw.json تنظیم کنید:
{ "gateway": { "auth": { "rateLimit": { "maxAttempts": 10, "windowMs": 60000, "lockoutMs": 300000, "exemptLoopback": true } } }}ورودیهای تکرارشونده AUTH_RATE_LIMITED در گزارش Gateway به این معنا است که کسی در حال
حدسزدن اعتبارنامهها است؛ راهنمای عملیاتی مواجهه را ببینید.
اتصالهای با مبدأ مرورگر
اتصالهای WebSocket که سرآیند مرورگر Origin را حمل میکنند، از همان
محدودیتها استفاده میکنند، اما استثنای loopback در آنها همیشه غیرفعال است — یک صفحه مخرب در
مرورگر محلی همچنان کلاینتی غیرقابلاعتماد است، بنابراین localhost در
این مسیر معافیت ندارد. وقتی چنین اتصالی از یک نشانی loopback برسد،
شکستهای آن بهجای IP مشترک loopback، بر اساس مبدأ نرمالسازیشده صفحه
(برای مثال browser-origin:https://evil.example) کلیدگذاری میشوند،
بنابراین هر مبدأ سبد مخصوص خود را دارد؛ برای نشانیهای غیرـloopback، کلید
همان IP کلاینت باقی میماند. این رفتار قابل پیکربندی نیست.
Webhookها
ورودی HTTP /hooks محدودکننده شکست مخصوص خود را دارد: 20 احراز هویت
ناموفق در هر 60 ثانیه بهازای هر IP کلاینت، سپس قفلشدن 60 ثانیهای.
Loopback مستثنا نیست. احراز هویت موفق hook شمارنده را بازنشانی میکند. درخواستهای
محدودشده، HTTP ساده 429 Too Many Requests را همراه با سرآیند Retry-After
(بر حسب ثانیه) دریافت میکنند. محدودیتها ثابتاند؛ اگر یک یکپارچهسازی معتبر به این حد رسید،
بهجای تلاش مجدد شدیدتر، اعتبارنامههای آن را اصلاح کنید.
نوشتنهای صفحه کنترل (پشتوانه پس از احراز هویت)
RPCهای مدیریتی سمت نوشتن (config.apply، config.patch، plugins.install،
plugins.setEnabled، plugins.uninstall، update.run، worktrees.*،
gateway.restart.request، ...) علاوهبراین، پس از
مجوزدهی محدود میشوند: 30 درخواست در هر 60 ثانیه، بهازای هر متد و هر
deviceId+clientIp.
این یک مرز امنیتی نیست — فراخوانندهها از قبل operator.admin را در اختیار دارند — بلکه
پشتوانهای است که حلقههای مهارنشده کلاینت یا عامل را که عملیات پرهزینه را
مکرراً فراخوانی میکنند، محدود میسازد. استفاده تعاملی هرگز به این حد نمیرسد؛ هر متد سبد مخصوص خود را دارد، بنابراین
تغییر وضعیت یک Plugin بودجه نوشتنهای پیکربندی را مصرف نمیکند.
پس از عبور از حد، درخواست با خطایی قابل تلاش مجدد شکست میخورد:
{ "code": "UNAVAILABLE", "message": "rate limit exceeded for config.patch; retry after 35s", "retryable": true, "retryAfterMs": 34539, "details": { "method": "config.patch", "limit": "30 per 60s" }}کلاینتها باید retryAfterMs را رعایت کنند. محدودیت ثابت است (قابل پیکربندی نیست)؛
سبدها خودبهخود منقضی میشوند و نگهداشت Gateway آنها را هرس میکند.
ایجاد نشست ACP
مترجم ACP ایجاد نشست را در هر بازه 10 ثانیهای و بهازای هر نمونه مترجم، به 120 نشست جدید
محدود میکند. عبور از این حد، درخواست را با خطایی شکست میدهد
که پیام آن زمان انتظار را در بر دارد (در این مسیر فیلد ساختاریافته retryAfterMs
وجود ندارد):
از محدودیت نرخ ایجاد نشست ACP برای <method> عبور شد؛ پس از <n>s دوباره تلاش کنید.این محدودیت کلاینتهای مهارنشدهای را که در یک حلقه نشست ایجاد میکنند مهار میکند؛ استفاده عادی IDE و عامل بسیار پایینتر از این حد باقی میماند.
فاصله راهاندازی مجدد
درخواستهای راهاندازی مجدد Gateway با یکدیگر ادغام میشوند و سپس فاصله 30 ثانیهای میان
چرخههای راهاندازی مجدد اعمال میشود. راهاندازی مجددی که در مدت این فاصله درخواست شود، بهجای ردشدن،
برای پس از پایان آن زمانبندی میشود. این مورد از محدودکننده صفحه کنترل
بالا جدا است: gateway.restart.request یک جایگاه از بودجه صفحه کنترل را مصرف میکند و
راهاندازی مجدد حاصل نیز از این فاصله پیروی میکند.
نکات عملیاتی
- همه محدودکنندهها درون حافظه و بهازای هر فرایند هستند و چند Gateway وضعیت را با یکدیگر به اشتراک نمیگذارند. جایگزینی فرایند Gateway شمارندههای متعلق به Gateway (قفلهای احراز هویت، محدودسازی Webhook، سبدهای صفحه کنترل) را پاک میکند. فاصله راهاندازی مجدد عمداً در چرخههای راهاندازی مجدد درونفرایندی باقی میماند — زیرا دقیقاً همانها را محدود میکند — و فقط همراه با فرایند بازنشانی میشود. سقف نشست ACP متعلق به نمونه مترجم آن است و هنگام ایجاد مجدد آن نمونه بازنشانی میشود، نه هنگام راهاندازی مجدد Gateway.
- نقشههای سبد محدود هستند (سقف قطعی تعداد ورودی بهعلاوه هرس دورهای)، بنابراین هجوم کلیدهای یکتا نمیتواند حافظه را بدون حد افزایش دهد.
- وقتی کلاینت پشت یک پراکسی معکوس قرار دارد، IP مؤثر همان IP تفکیکشده کلاینت است؛ برای چگونگی اعتبارسنجی سرآیندهای پراکسی پیش از آنکه بتوانند بر آن اثر بگذارند، احراز هویت پراکسی مورد اعتماد را ببینید.
- شیوه اعلام تلاش مجدد بسته به سطح متفاوت است: محدودکنندههای RPC در Gateway،
retryable: trueرا بههمراهretryAfterMsبرمیگردانند، ورودی Webhook از HTTP 429 با سرآیندRetry-Afterاستفاده میکند و ACP زمان انتظار را در پیام خطا میگنجاند. در همه موارد، بهجای تلاش مجدد فوری، بهاندازه مدت اعلامشده عقبنشینی کنید.