بازگشت به وبلاگ

SSH با Permission denied (publickey): رفع واقعی

۲۷ شهریور ۱۴۰۵

ساعت 02:10 یک deploy روی خطی مُرد که هزار بار تایپ کرده‌ام: ssh deploy@stagingPermission denied (publickey). کلید سالم بود. پیشنهاد سالم نبود.

TL;DR: Permission denied (publickey) یعنی هر کلیدی که کلاینت پیشنهاد داد از طرف سرور رد شده — حکم مذاکره، نه تایپ غلط پسورد. تشخیص با ssh -vvv (کدام کلیدها پیشنهاد شدند) و لاگ سرور journalctl -u ssh (کدام‌ها رد شدند و چرا). بعد یکی از چهار علت را رفع کنید: کاربر غلط، کلید غایب در authorized_keys، مجوزهای بازتر از حد، یا کلید ssh-rsa ای که OpenSSH 8.8+ رد می‌کند. ssh-copy-id بیشتر عودها را پیشگیری می‌کند.

$ ssh -T [email protected]
[email protected]: Permission denied (publickey).

خطا حکم است، نه سرنخ: همه محتوای پیشنهاد رد شده.

چرا SSH می‌گوید «Permission denied (publickey)»؟

احراز هویت کلید عمومی، مذاکره‌ی پیشنهاد-و-رد است. کلاینت هر کلیدی را که می‌یابد پیشنهاد می‌دهد — identity های agent، ~/.ssh/config، نام‌فایل‌های پیش‌فرض (id_ed25519، id_rsa) و هر چه با -i رد شده. سرور هر پیشنهاد را با ~/.ssh/authorized_keys حساب مقصد می‌سنجد. وقتی هیچ‌کدام match نمی‌شود و احراز پسورد بسته یا تمام‌شده است، کلاینت همان یک خطی را چاپ می‌کند که هر مهندس devops از بر است.

دو واقعیت برای دیباگ مهم است. اول، پیام نمی‌گوید به کدام کاربر خورده‌اید — نیمی از موارد کلید کاملاً سالمی است که در authorized_keys حساب اشتباه نشسته. دوم، سرور از قبل گفته چرا: sshd هر پیشنهاد ردشده را لاگ می‌کند. stack trace سمت کلاینت که هیچ‌کس نخواسته و همه لازم دارند -vvv است.

چطور بفهمم SSH واقعاً کدام کلید را پیشنهاد می‌دهد؟

ssh -vvv deploy@staging 2>&1 | grep -iE "offering|identity|denied|authentications"
# debug1: Offering public key: /home/you/.ssh/id_ed25519 RSA-SHA256 (explicit)
# debug1: Authentications that can continue: publickey
# deploy@staging: Permission denied (publickey).

سه خط را بخوانید: Offering public key (کلاینت چه پیشنهاد داد)، Authentications that can continue (سرور هنوز چه می‌پذیرد — اگر password غایب است، هیچ prompt پسوردی نخواهد آمد)، و حکم نهایی. اگر کلید موردنظرتان اصلاً در فهرست پیشنهادها نیست، مشکل سمت کلاینت است: مسیر -i غلط، یک IdentityFile فراموش‌شده در ~/.ssh/config، یا agent ای (ssh-add -l) با identity کهنه که زودتر جواب می‌دهد.

چهار علت واقعی کدام‌اند؟

علتنشانهرفع
کاربر غلطکلید برای root@host کار می‌کند، برای deploy@host نهکلید باید در ~/.ssh/authorized_keys همان کاربر باشد
کلید نصب نشدهلاگ سرور برای هر پیشنهاد Failed publickey نشان می‌دهدssh-copy-id user@host
مجوزهای بازتر از حدکلاینت: WARNING: UNPROTECTED PRIVATE KEY FILE — کلید رد می‌شود، اصلاً پیشنهاد نمی‌شودchmod 700 ~/.ssh; chmod 600 ~/.ssh/*
کلید قدیمی ssh-rsaسرور OpenSSH 8.8+ دارد؛ کلید RSA قدیمی هرگز پذیرفته نمی‌شودبه‌صورت ed25519 دوباره بسازید، یا کلید را ارتقا دهید

علت مجوزها یادداشت خودش را می‌طلبد، چون OpenSSH سخت پایش است: کلید خصوصی‌ای که گروه یا بقیه بتوانند بخوانند را خود کلاینت رد می‌کند و بی‌سروصدا از پیشنهاد می‌افتد. رفعش دو دستور است:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519 ~/.ssh/authorized_keys

علت ssh-rsa ایمیج‌های قدیمی CI و Raspberry Pi ها را می‌اندازد: OpenSSH 8.8 (منتشرشده 2021-10-01، openssh.com/txt/release-8.8) امضاهای ssh-rsa — همان نوع مبتنی بر SHA-1 — را به‌صورت پیش‌فرض بست. طبق یادداشت انتشار، «طرح امضای ssh-rsa … به‌صورت پیش‌فرض غیرفعال است». کلید RSA ساخته 2018 خراب نیست؛ قالب امضایش است که دیگر زبان مشترک نیست. ساختن کلید ed25519 (ssh-keygen -t ed25519) جواب ماندگار است، و کنسول‌های ابری وقتی وسط رفع خودتان را قفل کنید، کنسول سریال می‌دهند.

چطور ببینم سرور چرا کلید را رد کرده؟

لاگ سمت سرور شاهد صادق است. روی Ubuntu (systemd)، sshd به ازای هر پیشنهاد حکم لاگ می‌کند:

journalctl -u ssh -n 50 --no-pager | grep -iE "publickey|denied|accepted"
# sshd[4421]: Failed publickey for deploy from 203.0.113.7 port 51422 ssh2: RSA SHA256:...
# sshd[4421]: Accepted publickey for deploy from 203.0.113.7 port 51422 ssh2: ED25519 SHA256:...

Failed publickey با اثری که انتظارش را نداشتید یعنی کلاینت کلید دیگری پیشنهاد داده که فکر می‌کردید — برگردید سراغ -vvv. Failed publickey با اثر خودتان یعنی کلید درست است ولی برای آن حساب نصب نیست، یا مجوزهای home directory سمت سرور غلط است (همان قاعده 700/600 برای ~/.ssh و ~/.ssh/authorized_keys سرور). اگر sshd وسط ویرایش کانفیگ‌ها حاضر به بالا آمدن نیست، آن شکار دیگری است — ببینید سرویس systemd استارت نمی‌شود؟ چطور رفعش کنید.

چطور کلیدم را درست نصب کنم؟

ssh-copy-id deploy@staging
# Number of key(s) added: 1
ssh -o BatchMode=yes deploy@staging 'echo ok'   # non-interactive proof

ssh-copy-id کلید عمومی‌تان را به authorized_keys حساب مقصد می‌افزاید و مجوزهای منطقی می‌گذارد — هست چون چسباندن دستی در authorized_keys دقیقاً به‌اندازه کافی، روی newline انتهایی یا دایرکتوری غایب می‌شکند. چک BatchMode آزمون واقعی است: همه prompt ها را می‌بندد، پس موفقیت یعنی تنها کلید، ورود را حمل کرد. وقتی کلید کار کرد، scp و rsync همان احراز را مجانی به ارث می‌برند — انتخاب بینشان پهنای باند است نه اعتبارنامه (rsync در مقابل scp).

تریاژ 30 ثانیه‌ای

ssh -vvv user@host 2>&1 | grep -i offering      # 1. which keys were offered?
journalctl -u ssh -n 50 | grep -i publickey     # 2. why were they refused?
ls -ld ~/.ssh ~/.ssh/authorized_keys            # 3. 700 / 600?
ssh-copy-id user@host                           # 4. install, then verify with BatchMode

Permission denied (publickey) نتیجه مذاکره است، نه prompt پسورد — سرور هر کلید پیشنهادشده را رد کرده، و لاگش از قبل می‌داند چرا.

چهار دستور را به ترتیب بزنید و شکست رمزآلود نمی‌ماند: یکی از آن‌ها هر بار مقصر را نام می‌برد. مال من identity کهنه agent بود که زودتر از کلید درست جواب می‌داد — ssh-add -d، و deploy ساعت 02:31 سبز شد.

FAQ

چرا SSH می‌گوید Permission denied (publickey)؟

یعنی هر کلیدی که کلاینت پیشنهاد داد از طرف سرور رد شده، و احراز هویت password یا keyboard-interactive تلاش یا مجاز نشده. حکم مذاکره روی کلیدهای پیشنهادی شماست — نه تایپ غلط پسورد.

چطور SSH permission denied (publickey) را روی Ubuntu رفع کنم؟

سمت سرور با journalctl -u ssh -n 50 چک کنید، تأیید کنید کلید عمومی‌تان در ~/.ssh/authorized_keys کاربر مقصد است، و مطمئن شوید مجوزها 700 روی ~/.ssh و 600 روی authorized_keys و کلید خصوصی است.

چرا ssh -i mykey باز هم شکست می‌خورد؟

سه دلیل همیشگی: مجوز کلید خصوصی بازتر از حد است و OpenSSH بارگذاری‌اش را رد می‌کند، سرور OpenSSH 8.8+ دارد که امضاهای ssh-rsa (SHA-1) را بسته، یا کلید اصلاً در authorized_keys کاربر مقصد نیست.

چطور کلید عمومی‌ام را به سرور اضافه کنم؟

ssh-copy-id user@host را اجرا کنید — کلید عمومی‌تان را با مجوزهای درست به ~/.ssh/authorized_keys می‌افزاید. اگر ورود با پسورد از قبل بسته است، از کنسولی انجامش دهید که هنوز به آن دسترسی دارید.

— mrsaynothing

— mrsaynothing

یادداشت‌های میدانی درباره AI، لینوکس و self-hosting.

این نوشته را در dev.to بحث کنید dev.to ↗

آموزش بعدی با ایمیل

هر نوشته یک ایمیل. درستش کن، برو سراغ بعدی.

self-hosted · بدون واسطه‌های ثالث · لغو اشتراک با یک کلیک

این چیست؟

.gitignore کار نمی‌کند؟ این رفعِ واقعی است

این نوشته‌ها را می‌پسندید؟ این همان کاری است که برای زندگی از آن درمی‌آورم. استخدامم کنید