رفع خطای Too many authentication failures در SSH
خطای Too many authentication failures زمانی رخ میدهد که SSH agent کلیدهای زیادی ارسال میکند. با دستور ssh -v مشکل را عیبیابی و با تنظیم IdentitiesOnly در فایل config آن را حل کنید.
معنای خطای "Too many authentication failures"
خطای "Too many authentication failures" بدین معناست که کلاینت SSH شما کلیدهای بیشتری نسبت به آنچه سرور مایل به بررسی آنهاست ارائه کرده و سرور پیش از آنکه کلید صحیح شما امتحان شود، اتصال را قطع کرده است. این مشکل تقریباً همیشه مربوط به کلاینت است. کلید روی دیسک شما موجود است، سرور آن را در authorized_keys دارد، اما هیچکدام از این موارد کمکی نمیکند زیرا اتصال خیلی زود پایان یافته است.
زنجیرهٔ اتفاقات به این صورت است: ssh-agent تمام کلیدهای خصوصی که در آن بارگذاری کردهاید را نگه میدارد. کلاینت شما این کلیدها را یکییکی به سرور ارائه میدهد، زیرا راهی برای تشخیص اینکه اکانت کدامیک را میپذیرد ندارد. سرور هر کلیدی که در authorized_keys نباشد را رد میکند و هر مورد رد شده را به عنوان یک تلاش ناموفق برای احراز هویت میشمارد. پارامتر MaxAuthTries در sshd_config تعداد دفعات مجاز شکست در یک اتصال را محدود میکند. مقدار پیشفرض این محدودیت 6 است. اگر ایجنت شما ده کلید داشته باشد و کلید صحیح در جایگاه هشتم باشد، سرور پیش از رسیدن به آن، اتصال را قطع میکند.
بنابراین راه حل این است که کلاینت را مجبور کنید فقط یک کلید ارائه دهد: کلید صحیح.
شمارشهای سرور و نقش MaxAuthTries
احراز هویت با کلید عمومی (Public key authentication) در ابتدا مانند یک بازی حدسزدن است. کلاینت یک کلید عمومی میفرستد و میپرسد که آیا سرور امضای ساختهشده با آن را میپذیرد یا خیر. سرور پاسخ «بله» یا «خیر» میدهد. یک پاسخ «خیر» به معنای یک تلاش ناموفق است، دقیقاً مشابه یک رمز عبور اشتباه.
صفحه راهنمای sshd_config(5) این محدودیت را اینگونه توصیف میکند: «حداکثر تعداد تلاشهای احراز هویت مجاز در هر اتصال را مشخص میکند. هنگامی که تعداد شکستها به نصف این مقدار برسد، شکستهای بعدی ثبت (log) میشوند. مقدار پیشفرض 6 است.»
شش تلاش برای شخصی که رمز عبور تایپ میکند کافی است. اما برای عاملی (agent) که ده کلید در اختیار دارد، مقدار زیادی نیست. هنگامی که تعداد شکستها از این حد فراتر رود، sshd اتصال را قطع کرده و خطی مشابه این را در لاگ سیستم مینویسد:
error: maximum authentication attempts exceeded for deploy from 203.0.113.10 port 51292 ssh2کلاینت شما نیمه دیگر همین رویداد را چاپ میکند:
Received disconnect from 203.0.113.10 port 22:2: Too many authentication failures
Disconnected from 203.0.113.10 port 22این یک شکست متفاوت از خطای SSH permission denied (publickey) است. در آنجا، سرور تمام مواردی که ارائه کردید را بررسی کرد و هیچکدام را نپذیرفت. در اینجا، سرور از بررسی دست کشیده است. اشتباه گرفتن این دو مورد با یکدیگر، دلیلی است که باعث میشود افراد یک بعدازظهر کامل را صرف کپی مجدد کلیدی کنند که از قبل صحیح بوده است.
چرا همان کلید از لپتاپ همکارتان کار میکند
هیچ تفاوتی در کلید یا سرور وجود ندارد. عامل (agent) آنها دو کلید را نگه میدارد و عامل شما دوازده کلید. پیشنهادی که برای آنها در جایگاه اول ارسال میشود، برای شما در جایگاه نهم قرار دارد و تا آن زمان، اتصال پایان یافته است.
این تعداد بهآرامی افزایش مییابد. AddKeysToAgent yes در ~/.ssh/config هر کلیدی را که استفاده میکنید به عامل اضافه کرده و آن را همانجا باقی میگذارد. عوامل دستهکلید دسکتاپ، مانند GNOME Keyring در Linux یا login keychain در macOS، کلیدها را هنگام ورود به سیستم بدون پرسش بارگذاری میکنند. در طول یک سال، یک کلید کلاینت، یک کلید میزبان git و یک کلید برای سرور آزمایشگاه اضافه میکنید و یک روز، سروری که همیشه کار میکرد، دسترسی شما را رد میکند. هیچچیز در سرور تغییر نکرده است. عامل شما فقط شلوغتر شده است.
نحوه مشاهده پیشنهادها با استفاده از ssh -v
اتصال ناموفق را با دستور -v اجرا کنید و خروجی trace را بخوانید.
ssh -v deploy@203.0.113.10دو نوع خط در اینجا اهمیت دارند. Will attempt key: هویتهایی را که کلاینت جمعآوری کرده است، به ترتیبی که از آنها استفاده خواهد کرد، فهرست میکند. Offering public key: برای هر کلیدی که واقعاً به سرور ارسال میشود، یک بار ظاهر میگردد.
debug1: Will attempt key: /home/you/.ssh/id_ed25519 ED25519 SHA256:AAAA... agent
debug1: Will attempt key: /home/you/.ssh/id_rsa RSA SHA256:BBBB... agent
debug1: Offering public key: /home/you/.ssh/id_ed25519 ED25519 SHA256:AAAA... agent
debug1: Authentications that can continue: publickey,password
debug1: Offering public key: /home/you/.ssh/id_rsa RSA SHA256:BBBB... agentمسیرها، نوع کلیدها و اثرانگشتهای شما متفاوت خواهند بود. آنچه باید بشمارید، تعداد خطوط Offering public key: پیش از قطع اتصال است. اگر پیشنهادها یکی پس از دیگری ظاهر شوند و نشست بدون ارسال کلید مورد نظر شما پایان یابد، تشخیص قطعی است. عبارت agent در انتهای یک خط به این معنی است که آن هویت از ssh-agent آمده است. عبارت explicit به این معنی است که هویت از یک خط IdentityFile یا از -i در خط فرمان دریافت شده است.
سپس از agent بپرسید چه کلیدهایی را در اختیار دارد:
ssh-add -lهر خط از خروجی نشاندهنده یک کلید بارگذاریشده است. اگر خروجی The agent has no identities. را چاپ کند، مشکل از agent نیست و باید خطوط IdentityFile را در ~/.ssh/config بررسی کنید. اگر خروجی Could not open a connection to your authentication agent. را چاپ کند، یعنی هیچ agent در حال اجرا نیست و پیشنهادها از فایلهای کلید پیشفرض شما میآیند.
رفع 1: استفاده از IdentitiesOnly با یک کلید برای هر میزبان
IdentitiesOnly yes به ssh دستور میدهد که فقط هویتهای پیکربندیشده توسط شما را ارائه دهد و از هویتهای اضافی که agent پیشنهاد میدهد صرفنظر کند. این گزینه را با یک خط IdentityFile ترکیب کنید تا کلاینت فقط یک پیشنهاد ارسال کند.
Host vps
HostName 203.0.113.10
User deploy
IdentityFile ~/.ssh/id_ed25519_vps
IdentitiesOnly yesآن را در ~/.ssh/config ذخیره کنید و سپس chmod 600 ~/.ssh/config را اجرا نمایید. اگر فایل دارای مجوز نوشتن برای گروه یا همه باشد، ssh از اجرای آن خودداری کرده و خطای Bad owner or permissions on /home/you/.ssh/config را نمایش میدهد. اکنون ssh vps فقط یک کلید ارائه میدهد و ssh -v vps باید دقیقاً یک خط Offering public key: را نشان دهد.
دو نکته در اینجا برای کاربران تعجبآور است.
- گزینه
IdentitiesOnly yesبهتنهایی به معنای «یک کلید» نیست. فایلهای هویت پیشفرض نیز جزو هویتهای پیکربندیشده محسوب میشوند، بنابراین ssh همچنان سعی میکند~/.ssh/id_ed25519،~/.ssh/id_rsaو سایر موارد پیشفرض را امتحان کند. شما به خطIdentityFileنیز نیاز دارید. - عملیات امضا همچنان توسط agent انجام میشود.
IdentitiesOnlyکنترل میکند که کدام کلیدها پیشنهاد شوند، نه اینکه چه کسی آنها را امضا کند. اگر کلید خصوصی مشخصشده توسطIdentityFileدر agent بارگذاری شده باشد، agent امضا را تولید میکند و هرگز از شما passphrase خواسته نمیشود. شما حتی میتوانیدIdentityFileرا به فایل.pubمتناظر اشاره دهید؛ این کاری است که وقتی کلید خصوصی فقط در agent یا روی یک توکن سختافزاری قرار دارد، انجام میدهید.
یک تله در ~/.ssh/config میتواند این اصلاح را بیاثر کند. اکثر کلمات کلیدی اولین مقدار یافتشده را میپذیرند، به همین دلیل است که بلوکهای خاص Host باید بالاتر از Host * قرار گیرند. اما IdentityFile از این قاعده پیروی نمیکند. در راهنما آمده است: «امکان مشخص کردن چندین فایل هویت در فایلهای پیکربندی وجود دارد؛ تمام این هویتها به ترتیب امتحان خواهند شد.» یک IdentityFile در زیر Host * به هویت میزبان-محور شما اضافه میشود و جایگزین آن نمیشود، بنابراین یک خط سراسری فراموششده باعث میشود یک پیشنهاد اضافی به هر اتصال بازگردد.
اگر به یک شبکه ایمنی سراسری نیاز دارید، فقط این پرچم را در انتهای فایل تنظیم کنید:
Host *
IdentitiesOnly yesسپس هر میزبان به IdentityFile مخصوص خود نیاز دارد که در نهایت همان نتیجه مطلوب است. تعیین یک کلید برای هر سرور همان چیزی است که امکان لغو دسترسی یک ماشین خاص را در آینده بدون صدور مجدد همه کلیدها فراهم میکند؛ این عادت ارزش دارد که از همان ابتدا ایجاد شود: مشاهده نحوه مدیریت کلیدهای SSH برای هر ماشین.
راهکار 2: پاکسازی یا راهاندازی مجدد agent
اگر هنوز امکان ویرایش فایل پیکربندی را ندارید، محتویات agent را خالی کرده و فقط موارد مورد نیاز را بارگذاری کنید.
ssh-add -l # list what is loaded
ssh-add -d ~/.ssh/id_rsa # remove one key
ssh-add -D # remove every key
ssh-add ~/.ssh/id_ed25519_vps # load the one you needاگر اتصال بلافاصله پس از ssh-add -D برقرار شد، عامل مشکل همان agent بوده است. این کار را به عنوان یک تست در نظر بگیرید، نه یک تعمیر دائمی. یک desktop keyring agent کلیدهای خود را در ورود بعدی شما دوباره بارگذاری میکند، بنابراین مشکل فردا دوباره بازخواهد گشت. یک خط IdentitiesOnly در ~/.ssh/config پس از reboot باقی میماند، اما یک agent خالی خیر.
همچنین میتوانید برای یک کلید طول عمر (lifetime) تعیین کنید تا agent آن را بهطور خودکار برای شما پاک کند:
ssh-add -t 1800 ~/.ssh/id_ed25519_vpsاین کلید 1800 ثانیه پس از اضافه شدن حذف میشود. راهاندازی مجدد agent نیز موثر است و نحوه انجام آن به روش اجرای اولیه بستگی دارد. یک ssh-agent که خودتان اجرا کردهاید با ssh-agent -k متوقف میشود. اگر آن را از طریق یک systemd user unit که نوشتهاید اجرا میکنید، آن unit را با systemctl --user restart <unit> راهاندازی مجدد کنید. یک keyring agent همراه با نشست دسکتاپ شما دوباره راهاندازی میشود.
راهکار 3: دستور یکباره برای سروری که فقط یکبار به آن متصل میشوید
برای میزبانی که قصد ندارید به فایل پیکربندی خود اضافه کنید، همان تنظیمات را در خط فرمان وارد کنید:
ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10استفاده از -i بهتنهایی، رایجترین اشتباه در رفع این مشکل است. دستور -i فقط یک کلید به فهرست هویتها اضافه میکند. این دستور کلیدهای موجود در agent را از آن فهرست حذف نمیکند، بنابراین سایر کلیدها همچنان پیش از کلید شما ارسال میشوند و اتصال بهدلیل رسیدن به حد مجاز، قطع میگردد. اگر ssh -v -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10 را بدون IdentitiesOnly اجرا کنید، خواهید دید که کلیدهای agent همچنان در اولویت ارسال قرار میگیرند. دستور -i برای عملکرد صحیح به -o IdentitiesOnly=yes در کنار خود نیاز دارد.
برای حذف کامل نقش agent در یک اتصال خاص:
ssh -o IdentityAgent=none -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10در این حالت، ssh کلید خصوصی را از روی دیسک میخواند و در صورت داشتن passphrase، آن را از شما میپرسد.
ابزارهای مبتنی بر ssh نیز همین گزینه را میپذیرند:
scp -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps report.tar.gz deploy@203.0.113.10:/tmp/
rsync -av -e "ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps" ./site/ deploy@203.0.113.10:/srv/site/
GIT_SSH_COMMAND="ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps" git clone git@example.com:team/repo.gitچرا خطا در گام دوم (hop) ظاهر میشود
با استفاده از ForwardAgent yes، سوکت agent روی سروری که به آن متصل میشوید در دسترس قرار میگیرد. دستوری که با ssh روی آن سرور اجرا میشود، از agent محلی شما و تمام کلیدهایتان از طریق سوکت فوروارد شده استفاده میکند. به همین دلیل است که خطا میتواند در مسیر بین jump host و سرور نهایی ظاهر شود، در حالی که گام اول بهدرستی کار کرده است. دستور echo $SSH_AUTH_SOCK را روی ماشین میانی اجرا کنید: وجود مسیر سوکت به این معنی است که یک agent فوروارد شده در دسترس است و خروجی خالی به این معنی است که هیچ agentای وجود ندارد.
فوروارد کردن agent هزینهٔ دومی هم دارد. هر کسی که دسترسی root روی آن ماشین میانی داشته باشد، میتواند تا زمانی که نشست (session) شما باز است، از agent شما برای احراز هویت به جای شما استفاده کند. ProxyJump از هر دو مشکل جلوگیری میکند:
ssh -J deploy@jump.example.com deploy@10.0.0.5ProxyJump یک اتصال از طریق jump host برقرار میکند و از ماشین خودتان به سرور نهایی احراز هویت انجام میدهد، بنابراین ~/.ssh/config محلی شما در هر گام، از جمله IdentitiesOnly، اعمال میشود. غیرفعال کردن ForwardAgent یک گام استاندارد هنگام ایمنسازی SSH روی یک VPS است.
آیا باید مقدار MaxAuthTries را در سرور افزایش داد؟
معمولاً خیر. ابتدا مقدار فعلی را بررسی کنید:
sudo sshd -T | grep -i maxauthtriesgrep MaxAuthTries /etc/ssh/sshd_config
sshd -T پیکربندی مؤثر، شامل مقادیر پیشفرض را چاپ میکند، بنابراین حتی زمانی که sshd_config چیزی درباره آن نمیگوید، مقدار واقعی را گزارش میدهد. اگر از بلوکهای Match استفاده میکنید، -C user=deploy,host=example.com,addr=203.0.113.10 را اضافه کنید، زیرا این بلوکها برای هر اتصال ارزیابی میشوند و در غیر این صورت نادیده گرفته میشوند.
افزایش این محدودیت در معنای محدود آن کار میکند، به این صورت که عدد بزرگتر به کلاینتی که رفتار نادرستی دارد، فضای بیشتری میدهد:
MaxAuthTries 20Match User admin
MaxAuthTries 20
فایل را اعتبارسنجی کرده و سرویس را reload کنید؛ در حین انجام این کار، یک نشست دوم را باز نگه دارید:
sudo sshd -t
sudo systemctl reload ssh # Debian and Ubuntu
sudo systemctl reload sshd # RHEL familysshd -t && systemctl reload ssh
اگر systemctl is-enabled ssh.socket در Ubuntu 24.04 مقدار enabled را گزارش میدهد، sshd به صورت socket activated است: یک پردازش جدید برای هر اتصال شروع میشود و دوباره sshd_config را میخواند، بنابراین اتصالات جدید تغییرات را خودبهخود اعمال میکنند.
اکنون ببینید این تغییر چه کاری انجام داد. کلاینت کلیدهایی را ارائه میدهد که این سرور هرگز نمیپذیرد. افزایش سقف به سرور میگوید که به جای 6 مورد، بیست پیشنهاد رد شده را برای هر اتصال و برای هر حدسزننده رمز عبور در اینترنت پردازش کند. هر پیشنهاد، هزینه یک جستجو در authorized_keys را برای سرور دارد. ورود خود شما همچنان کند باقی میماند، زیرا کلید درست همچنان در انتهای صف است. کلید سیزدهم را به agent خود اضافه کنید تا دوباره به نقطه اول برگردید و باز هم درخواست عدد بزرگتری کنید.
فقط زمانی آن را افزایش دهید که یک کلاینت قانونی واقعاً نیاز به ارائه چندین هویت داشته باشد. در تمام موارد دیگر، کلاینت را اصلاح کنید. کاهش آن پس از اینکه هر کاربر با یک کلید پیکربندیشده وارد سیستم شد، یک hardening منطقی است، زیرا عدد کوچکتر به حدسزننده فرصتهای کمتری در هر اتصال میدهد.
چرا fail2ban ممکن است شما را به این دلیل مسدود کند
در سطح لاگ پیشفرض، sshd هر کلید عمومی (public key) رد شده را ثبت میکند:
Failed publickey for deploy from 203.0.113.10 port 51292 ssh2: ED25519 SHA256:AAAA...یک اتصال از یک agent کامل، چندین خط از این دست را در عرض یک یا دو ثانیه از یک آدرس تولید میکند. jail مربوط به sshd در fail2ban، خطاهای sshd را میشمارد و به محض رسیدن به maxretry در بازه زمانی findtime، آدرس مبدأ را مسدود میکند. این بازههای زمانی بهطور پیشفرض کوچک هستند، بنابراین دو بار تلاش مجدد برای یک اتصال ناقص میتواند برای مسدود شدن آدرس خودتان کافی باشد.
سپس نشانه تغییر میکند و این بخشی است که باعث سردرگمی کاربران میشود. شما دیگر پیام "Too many authentication failures" را نمیبینید و اصلاً چیزی دریافت نمیکنید: اتصال معلق میماند و در نهایت با timeout مواجه میشود، زیرا فایروال اکنون به جای پاسخ دادن به بستههای شما، آنها را drop میکند. timeout در جایی که قبلاً پیام خطا دریافت میکردید، یک نشانه است و این تفاوت در تفاوت بین رد شدن اتصال SSH و timeout شدن آن پوشش داده شده است.
از طریق کنسول ارائهدهنده سرویس خود یا از یک آدرس دیگر، jail را بررسی کرده و مسدودیت را رفع کنید:
sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 203.0.113.10آدرس خود را در ignoreip در فایل jail.local قرار دهید تا مشکل کلاینت را برطرف کنید، سپس پس از اتمام کار، آن را حذف کنید. خودِ jail در راهنمای fail2ban برای Ubuntu 24.04 تنظیم شده است.
چه کاری انجام دهیم تا این مشکل دیگر تکرار نشود
برای هر سرور یک بلوک Host اختصاصی در فایل ~/.ssh/config ایجاد کنید و در آن از HostName، User، IdentityFile و IdentitiesOnly yes استفاده نمایید. پس از این کار، تایپ دستور ssh vps کوتاه میشود، دقیقاً یک کلید ارائه میدهد و فارغ از اینکه MaxAuthTries چقدر شلوغ شود، باعث بروز خطا نمیگردد. همچنین این کار باعث میشود خروجی ssh -v به اندازهای کوتاه بماند که در روزی که مشکل دیگری رخ میدهد، بهراحتی قابل خواندن باشد.
FAQ
چگونه خطای "Too many authentication failures" را فوراً برطرف کنم؟
بهجای ارائه همه کلیدها، فقط یک کلید را ارائه دهید. برای اتصال فوری، دستور ssh -o IdentitiesOnly=yes -i ~/.ssh/your_key user@host را اجرا کنید. برای رفع دائمی، یک بلوک در ~/.ssh/config با استفاده از HostName، User، IdentityFile که به آن کلید اشاره دارد، و همچنین IdentitiesOnly yes و سپس chmod 600 ~/.ssh/config اضافه کنید. با استفاده از ssh -v آن را تأیید کنید: باید یک خط Offering public key: برای آن میزبان مشاهده کنید.
چرا با وجود استفاده از ssh -i، سایر کلیدهای من همچنان ارائه میشوند؟
زیرا -i یک هویت به لیست اضافه میکند، نه اینکه لیست را محدود کند. کلیدهای بارگذاریشده در ssh-agent در لیست باقی میمانند و همچنان ارائه میشوند، که اغلب پیش از کلید شماست؛ بنابراین سرور ممکن است پیش از رسیدن به کلید شما، به حد مجاز MaxAuthTries برسد. -o IdentitiesOnly=yes گزینهای است که ssh را به هویتهای نامبرده محدود میکند. از -i و -o IdentitiesOnly=yes با هم استفاده کنید، یا برای نادیده گرفتن کامل agent در آن اتصال خاص، از -o IdentityAgent=none بهره ببرید.
آیا برای رفع این مشکل باید MaxAuthTries را در سرور افزایش دهم؟
خیر، تقریباً در هیچ موردی این کار توصیه نمیشود. کلاینت کلیدهایی را ارسال میکند که سرور هرگز آنها را نمیپذیرد و افزایش حد مجاز فقط باعث میشود سرور در هر اتصال، پیشنهادهای ردشده بیشتری را برای هر کلاینت و هر تلاش brute force بررسی کند. همچنین بهمحض اضافه شدن یک کلید دیگر به agent شما، مشکل دوباره بروز میکند. اگر کنجکاو هستید، مقدار فعلی را با sudo sshd -T | grep -i maxauthtries بررسی کنید و سپس کلاینت را با IdentitiesOnly اصلاح کنید.
چرا این مشکل در سروری که ماه گذشته بهخوبی کار میکرد، شروع شده است؟
agent شما بزرگتر شده است. AddKeysToAgent yes در ~/.ssh/config هر کلیدی را که استفاده میکنید بارگذاری نگه میدارد و agentهای keyring دسکتاپ نیز کلیدها را هنگام ورود به سیستم بهطور خودکار بارگذاری میکنند. هنگامی که تعداد کلیدهای بارگذاریشده از حد مجاز MaxAuthTries سرور فراتر رود، هر سروری که کلید آن در انتهای ترتیب ارائه قرار دارد، با شکست مواجه میشود. دستور ssh-add -l را اجرا کنید و تعداد را با حد مجاز سرور مقایسه کنید.
آیا این مشکل میتواند باعث مسدود شدن IP من توسط fail2ban شود؟
بله. هر کلید ردشده یک خط Failed publickey for ... در لاگ سرور ایجاد میکند، بنابراین یک اتصال میتواند در عرض چند ثانیه چندین خطا از آدرس شما تولید کند و jail مربوط به sshd در fail2ban، آدرس را پس از رسیدن به maxretry در بازه زمانی findtime مسدود میکند. نشانه این اتفاق این است که خطا به حالت hang و سپس timeout تغییر میکند، زیرا بستهها بهجای پاسخدهی، دور ریخته میشوند. با استفاده از sudo fail2ban-client set sshd unbanip <your address> آن را از طریق کنسول پاک کنید و پیش از اتصال مجدد، کلاینت را اصلاح کنید.