خطای Permission denied (publickey) یعنی شبکه سالم است و سرور SSH جواب داده، اما هیچ کلیدی را که کامپیوتر شما عرضه کرده نپذیرفته — و ورود با رمز را هم قبول نمیکند. علتش تقریباً همیشه یکی از ۹ مورد مشخص است و با ssh -v در کمتر از یک دقیقه معلوم میشود کدام. این راهنما خروجی ssh -v و لاگ سرور را خطبهخط معنی میکند، راهحل هر علت را با دستور میدهد، تلهی پوشهی sshd_config.d در اوبونتو ۲۲.۰۴ را باز میکند، نسخهی گیتهاب همین خطا را جدا حل میکند و اگر از سرور بیرون ماندهاید، مسیر برگشت از کنسول تحت وب را قدمبهقدم نشان میدهد.
خطای Permission denied (publickey) دقیقاً یعنی چه؟
کلمهی داخل پرانتز فهرست روشهایی است که سرور هنوز برای ورود میپذیرد. (publickey) بهتنهایی یعنی ورود با رمز روی این سرور بسته است و تنها راه، کلیدی است که در فایل authorized_keys همان کاربر ثبت شده باشد. (publickey,password) یعنی هر دو روش باز بوده و هر دو شکست خوردهاند؛ و روی آلمالینوکس و راکی معمولاً (publickey,gssapi-keyex,gssapi-with-mic) میبینید که همان معنی را دارد. خبر خوب این است که این خطا بعد از برقراری اتصال رخ میدهد؛ یعنی آیپی، پورت، فایروال و سرویس SSH همه درستاند و مشکل فقط در احراز هویت است. خطاهای پیش از این مرحله داستان دیگری دارند:
| پیام | در کدام مرحله | معنی |
|---|---|---|
| Connection timed out | پیش از اتصال | بسته به سرور نمیرسد: سرور خاموش است، فایروال پورت را بسته یا آیپی اشتباه است |
| Connection refused | پیش از اتصال | سرور در دسترس است اما روی آن پورت کسی گوش نمیدهد |
| Host key verification failed | تبادل کلید | اثر انگشت سرور با نسخهی ذخیرهشده فرق دارد، معمولاً بعد از نصب مجدد |
| Permission denied (publickey) | احراز هویت | سرور کلید شما را نپذیرفت و ورود با رمز هم بسته است |
درمان سه خطای اول در بخش خطاهای راهنمای کامل اتصال به سرور با SSH آمده است. این مقاله فقط روی ردیف آخر تمرکز دارد؛ خطایی که در تیکتهای پشتیبانی ما بارها تکرار شده است.
تشخیص در یک دقیقه: ssh -v دقیقاً چه کلیدی فرستاده است؟
همان دستور همیشگی را با -v بزنید. خروجی طولانی است، اما فقط خطهایی که با Authentications، Offering، Will attempt، Trying، Server accepts و Load key شروع میشوند مهماند:
ssh -v root@203.0.113.10
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Offering public key: /home/ali/.ssh/id_ed25519 ED25519 SHA256:q3k…
debug1: Authentications that can continue: publickey
debug1: Trying private key: /home/ali/.ssh/id_rsa
debug1: No more authentication methods to try.
root@203.0.113.10: Permission denied (publickey).
این نمونهی رایجترین حالت است: کلاینت کلید id_ed25519 را عرضه کرده و سرور بلافاصله دوباره گفته «روشهای باقیمانده: publickey» — یعنی این کلید را نمیشناسد. خطهای کلیدی و معنی هرکدام:
| خط در خروجی ssh -v | معنی | برو به |
|---|---|---|
| Offering public key: … و بلافاصله دوباره Authentications that can continue | سرور این کلید را برای این کاربر نپذیرفت | علت ۱، ۲، ۸ یا ۹ |
| no such identity: … یا اصلاً هیچ Offeringی نیست | فایل کلید در مسیری که گفتهاید نیست | علت ۳ |
| Load key "…": bad permissions | کلاینت خودش کلید را کنار گذاشته، چون مجوزش بیش از حد باز است | علت ۷ |
| Load key "…": invalid format | فایل کلید در قالبی است که OpenSSH نمیخواند، معمولاً ppk پاتی | علت ۶ |
| Server accepts key و بعد no mutual signature supported | کلید درست است، اما دو طرف روی الگوریتم امضا توافق ندارند | علت ۵ |
| Too many authentication failures | کلاینت پیش از کلید درست، چند کلید دیگر را امتحان کرده و سرور اتصال را بسته | علت ۴ |
اگر هنوز راهی به داخل سرور دارید — یک نشست SSH باز در پنجرهی دیگر یا کنسول تحت وب — سمت دیگر ماجرا را هم ببینید. سرور علت رد کلید را به کاربر نمیگوید، اما در لاگ خودش مینویسد:
# Ubuntu / Debian (the unit is "ssh")
journalctl -u ssh -n 30 --no-pager
# AlmaLinux / Rocky (the unit is "sshd")
journalctl -u sshd -n 30 --no-pager
خطهایی که دنبالشان هستید: Authentication refused: bad ownership or modes for directory /root/.ssh (علت ۲)، User ali from 198.51.100.7 not allowed because not listed in AllowUsers یا ROOT LOGIN REFUSED (علت ۸)، و خطی حاوی not in PubkeyAcceptedAlgorithms (علت ۵). اگر هیچکدام نبود و فقط Connection closed by authenticating user root … [preauth] دیدید، سرور کلید را سادهترین شکل ممکن رد کرده: این کلید در authorized_keys این کاربر نیست (علت ۱).
۹ علت خطای Permission denied (publickey) و راهحل هرکدام
۱. کلید عمومی در authorized_keys همان کاربر نیست
سرور فقط فایل ~/.ssh/authorized_keys همان کاربری را میخواند که با آن وارد میشوید؛ کلیدی که برای ali ثبت شده، برای root کار نمیکند. سه اشتباه رایج: کلید در فایل کاربر دیگری است، بهجای کلید عمومی (.pub) کلید خصوصی چسبانده شده، یا کلید موقع کپی دو تکه شده است. هر کلید باید دقیقاً یک خط باشد:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI…Q9x ali@laptop
برای مقایسه، اثر انگشت کلید محلی و کلیدهای ثبتشده روی سرور را کنار هم بگذارید؛ باید یکی از خطها با همان SHA256 که ssh -v در خط Offering چاپ کرد یکی باشد:
# on your computer
ssh-keygen -lf ~/.ssh/id_ed25519.pub
# on the server
ssh-keygen -lf /root/.ssh/authorized_keys
اگر هنوز با رمز یا کلید دیگری وارد میشوید، سادهترین راه ثبت درست کلید ssh-copy-id است که خودش پوشه و مجوزها را هم درست میسازد؛ نسخهی ویندوزیاش در راهنمای اتصال SSH آمده است.
۲. مجوز یا مالکیت پوشهی .ssh و authorized_keys
sshd بهطور پیشفرض (StrictModes yes) فایلی را که دیگران بتوانند در آن بنویسند نادیده میگیرد، و این فقط شامل خود فایل نیست: پوشهی .ssh و حتی پوشهی خانهی کاربر هم نباید برای گروه یا دیگران قابل نوشتن باشد. یک chmod 777 سهوی روی پوشهی خانه، یا فایلی که با SFTP و کاربر دیگری آپلود شده، دقیقاً همین خطا را میسازد. روی سرور:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R "$(id -un):$(id -gn)" ~/.ssh
chmod go-w ~ # the home directory itself must not be group/world-writable
ls -ld ~ ~/.ssh ~/.ssh/authorized_keys
خروجی درست برای .ssh با drwx------ و برای فایل با -rw------- شروع میشود و مالک هر دو خود کاربر است. این دستورها را با همان کاربری اجرا کنید که قرار است وارد شود؛ اگر بهعنوان root برای کاربر دیگری اصلاح میکنید، بهجای ~ مسیر کامل خانهی او را بنویسید.
۳. کلاینت کلید درست را پیدا نمیکند
SSH بدون راهنمایی فقط نامهای پیشفرض را امتحان میکند: id_ed25519، id_ecdsa، id_rsa و چند نام دیگر زیر ~/.ssh. کلیدی که اسم دیگری دارد یا جای دیگری است، باید صریح معرفی شود:
ssh -i ~/.ssh/srv1_key root@203.0.113.10
یا یک بار برای همیشه در ~/.ssh/config:
Host srv1
HostName 203.0.113.10
User root
IdentityFile ~/.ssh/srv1_key
IdentitiesOnly yes
یک دام رایج دیگر اجرای دستور با sudo است: sudo ssh یا sudo git pull کلیدهای root را میخواند، نه کلیدهای شما را.
۴. Too many authentication failures: کلیدهای زیاد در ssh-agent
اگر ssh-agent یا مدیر کلیدتان ده کلید نگه میدارد، کلاینت آنها را یکییکی عرضه میکند و sshd بعد از شش تلاش ناموفق (MaxAuthTries 6) اتصال را میبندد، پیش از آنکه نوبت کلید درست برسد. خط IdentitiesOnly yes در فایل config بالا دقیقاً همین را حل میکند: فقط کلیدی که نام بردهاید فرستاده میشود. برای یک بار: ssh -o IdentitiesOnly=yes -i ~/.ssh/srv1_key root@203.0.113.10.
۵. کلید RSA قدیمی و OpenSSH جدید (اوبونتو ۲۲.۰۴ به بعد)
از OpenSSH 8.8 امضای RSA با الگوریتم هش SHA-1 (ssh-rsa) بهطور پیشفرض خاموش است، و اوبونتو ۲۲.۰۴ با OpenSSH 8.9 عرضه میشود. خود کلید RSA هنوز معتبر است، به شرط آنکه کلاینت با rsa-sha2-256 یا rsa-sha2-512 امضا کند؛ کلاینتهای قدیمی این کار را بلد نیستند: نسخههای قدیمی PuTTY و WinSCP، و کتابخانههای SSH قدیمی داخل اسکریپتها و برنامهها. نشانهاش سمت سرور خطی حاوی not in PubkeyAcceptedAlgorithms است، و سمت کلاینتِ جدیدی که به سرور خیلی قدیمی وصل میشود، no mutual signature supported.
راه درست، کلید تازهی Ed25519 است که همهی نسخههای امروزی میشناسند:
ssh-keygen -t ed25519 -C "ali@laptop"
و بهروزرسانی کلاینت یا کتابخانهی قدیمی. باز کردن دوبارهی ssh-rsa روی سرور با PubkeyAcceptedAlgorithms +ssh-rsa فقط راه موقت است و الگوریتمی را برمیگرداند که به دلیل ضعف SHA-1 کنار گذاشته شده.
۶. قالب کلید: ppk پاتی در برابر OpenSSH
PuTTY کلید را با قالب خودش (.ppk) ذخیره میکند و OpenSSH — یعنی ssh در PowerShell، لینوکس و مک — آن را نمیخواند و invalid format میگوید. برعکسش هم صادق است: PuTTY کلید OpenSSH را مستقیم قبول نمیکند. تبدیل با PuTTYgen است: کلید را با Load باز کنید و برای OpenSSH از منوی Conversions ← Export OpenSSH key خروجی بگیرید، یا برای PuTTY کلید OpenSSH را Load و با Save private key به ppk ذخیره کنید. در لینوکس:
puttygen mykey.ppk -O private-openssh -o ~/.ssh/id_ed25519
۷. ویندوز: WARNING: UNPROTECTED PRIVATE KEY FILE
OpenSSH ویندوز هم مثل لینوکس کلید خصوصیای را که دیگران بتوانند بخوانند کنار میگذارد و پیام Permissions for '…\id_ed25519' are too open و بعد This private key will be ignored را چاپ میکند؛ نتیجهی نهایی باز همان Permission denied (publickey) است. این اتفاق معمولاً بعد از کپی کلید از فلش یا پوشهی دیگر میافتد. در ویندوز chmod کار نمیکند؛ در PowerShell ارثبری مجوز را قطع کنید و فقط به خودتان اجازهی خواندن بدهید:
icacls "$env:USERPROFILE\.ssh\id_ed25519" /inheritance:r
icacls "$env:USERPROFILE\.ssh\id_ed25519" /grant:r "$($env:USERNAME):(R)"
۸. تنظیمات sshd: PermitRootLogin، AllowUsers و تلهی پوشهی sshd_config.d
گاهی کلید سالم است و خود سرور ورود این کاربر را ممنوع کرده: PermitRootLogin no ورود root را حتی با کلید میبندد (مقدار prohibit-password فقط ورود root با رمز را میبندد)، AllowUsers هر کاربری را که در فهرستش نباشد رد میکند و PubkeyAuthentication no کل روش کلید را خاموش میکند. تلهای که در بسیاری از راهنماها گفته نمیشود این است: در اوبونتو ۲۲.۰۴ و دبیان، اولین دستور فایل /etc/ssh/sshd_config این خط است:
Include /etc/ssh/sshd_config.d/*.conf
و طبق مستند sshd_config برای هر تنظیم، اولین مقداری که خوانده شود برنده است. پس فایلی مثل 50-cloud-init.conf — که روی ایمیجهای ابری، از جمله سرورهایی که با cloud-init ساخته میشوند، خودکار نوشته میشود — بر خطی که شما پایین فایل اصلی اضافه کردهاید غلبه میکند. بهجای حدس، تنظیم نهاییای را که sshd واقعاً اجرا میکند بپرسید:
sudo sshd -T | grep -Ei '^(permitrootlogin|passwordauthentication|pubkeyauthentication|authorizedkeysfile|allowusers|pubkeyacceptedalgorithms) '
grep -r . /etc/ssh/sshd_config.d/
بعد از هر تغییر، پیش از اعمال، درستی فایل را بسنجید تا یک غلط تایپی سرویس را از کار نیندازد: sudo sshd -t && sudo systemctl reload ssh (روی آلمالینوکس و راکی: reload sshd).
۹. SELinux روی آلمالینوکس و راکی
روی توزیعهای خانوادهی RHEL که SELinux روشن است، فایل authorized_keysی که با mv از جای دیگری آمده برچسب امنیتی اشتباه دارد و sshd اجازهی خواندنش را ندارد، هرچند مجوزهای معمولی کاملاً درست باشند. ردش در /var/log/audit/audit.log با avc: denied پیدا میشود و درمانش یک خط است:
restorecon -Rv ~/.ssh
از سرور بیرون ماندهاید؟ برگشت با کنسول تحت وب، بدون SSH
وقتی ورود با رمز بسته است و کلید کار نمیکند، از راه شبکه راهی به داخل نیست؛ اما کنسول تحت وب پنل به صفحهنمایش مجازی سرور وصل میشود و به SSH و حتی شبکهی سرور وابسته نیست. ورود در کنسول هم یک ورود محلی است و تنظیمات sshd روی آن اثری ندارد، پس رمز root کار میکند.
سرور ابری ایران
- در پنل، صفحهی سرور را باز کنید. اگر رمز root را نمیدانید یا عوضش کردهاید، از بخش «تغییر / ریست رمز روت» همان صفحه یک رمز تازه بگیرید؛ سرور باید روشن باشد.
- در تب «کنسول»، دکمهی «باز کردن کنسول» را بزنید و با root و همان رمز وارد شوید. رمز هنگام تایپ نمایش داده نمیشود؛ اگر «Login incorrect» گرفتید، زبان صفحهکلید را روی انگلیسی و Caps Lock را خاموش کنید.
- کلید عمومی را با دکمهی «📋 پیست متن» بفرستید، نه با تایپ؛ یک کاراکتر اشتباه در کلید چنددهحرفی همان خطا را تکرار میکند:
mkdir -p /root/.ssh && chmod 700 /root/.ssh
echo 'ssh-ed25519 AAAAC3Nza…Q9x ali@laptop' >> /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys
sshd -t && systemctl reload ssh # AlmaLinux/Rocky: systemctl reload sshd
سرور خارج از ایران
کنسول سرورهای خارج از صفحهی همان سرور باز میشود اما دکمهی پیست ندارد و تایپ دستی یک کلید طولانی عملی نیست. راه سادهتر این است که ورود با رمز را موقتاً باز کنید، کلید را از کامپیوتر خودتان با ssh-copy-id بفرستید و دوباره ببندید. رمز root در کارت «دسترسی» صفحهی سرور است و اگر کار نکرد، دکمهی «ساخت رمز جدید» یک رمز تازه میسازد — پیام تأیید همان دکمه میگوید سرور ریاستارت میشود یا باید خاموش باشد. بعد در کنسول، بهعنوان root:
# "00-" sorts first, and the first value read wins
printf 'PasswordAuthentication yes\nPermitRootLogin yes\n' > /etc/ssh/sshd_config.d/00-temp.conf
sshd -t && systemctl reload ssh
از کامپیوتر خودتان کلید را بفرستید و ورود با کلید را در یک پنجرهی جدید امتحان کنید:
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@203.0.113.10
ssh -i ~/.ssh/id_ed25519 root@203.0.113.10
و وقتی کلید کار کرد، فایل موقت را پاک کنید تا وضعیت قبلی برگردد:
rm /etc/ssh/sshd_config.d/00-temp.conf && sshd -t && systemctl reload ssh
این روش روی اوبونتو و دبیان که پوشهی sshd_config.d را میخوانند کار میکند؛ روی آلمالینوکس ۸ همان دو خط را موقتاً بالای /etc/ssh/sshd_config بگذارید و بعد برگردانید.
Permission denied (publickey) در git push و گیتهاب
همین خطا با پیشوند git@github.com یعنی گیتهاب کلید سروری را که از آن git pull یا git push میزنید نمیشناسد. از یک سرور در دیتاسنتر ایران، SSH گیتهاب در دسترس بود و بدون کلید ثبتشده دقیقاً همین را برگرداند:
ssh -T git@github.com
git@github.com: Permission denied (publickey).
برای سروری که فقط یک مخزن را میکشد، تمیزترین راه «کلید استقرار» (Deploy key) است: روی سرور یک کلید بسازید و محتوای .pub آن را در تنظیمات همان مخزن، بخش Deploy keys اضافه کنید؛ پیشفرضش فقطخواندنی است، که برای سرور تولید همان چیزی است که میخواهید. پاسخ درست آزمون بعد از ثبت کلید این است:
ssh -T git@github.com
Hi ali/shop! You've successfully authenticated, but GitHub does not provide shell access.
چند نکته که بیشترِ «هنوز کار نمیکند»ها را توضیح میدهد:
- یک کلید استقرار فقط به یک مخزن وصل میشود؛ برای چند مخزن، چند کلید بسازید و در ~/.ssh/config برای هرکدام یک Host مستعار با IdentityFile خودش تعریف کنید.
- نشانی مخزن باید شکل SSH داشته باشد (git@github.com:ali/shop.git)؛ نشانی https:// اصلاً سراغ کلید نمیرود. با git remote -v ببینید.
- اسکریپت دیپلوی با همان کاربری اجرا شود که کلید در ~/.ssh او ساخته شده؛ sudo git pull یا اجرا با www-data کلید دیگری را میخواند. الگوی کامل یک دیپلوی گیت را در راهنمای دیپلوی لاراول روی سرور مجازی ببینید.
- اگر شبکهای پورت ۲۲ را بسته بود، گیتهاب SSH را روی پورت ۴۴۳ و نام ssh.github.com هم ارائه میدهد؛ راهنمای رسمی گیتهاب تنظیمش را آورده است.
چطور دیگر پشت در سرور نمانیم؟
بیشترِ قفلشدنها در همان پنج دقیقهای رخ میدهد که کسی ورود با رمز را میبندد. این چند عادت آن پنج دقیقه را بیخطر میکند:
- تا وقتی ورود با کلید را در یک پنجرهی جدید امتحان نکردهاید، نشست فعلی را نبندید؛ نشست باز با reload شدن sshd قطع نمیشود.
- قبل از هر reload، sshd -t بزنید و بعد از آن با sshd -T ببینید مقدار نهایی همان است که میخواستید.
- رمز root را در جای امنی نگه دارید؛ کلید برای ورود از شبکه است، رمز برای روز مبادا در کنسول.
- از کلید Ed25519 با عبارت عبور استفاده کنید و از کلید خصوصی یک نسخهی پشتیبان امن داشته باشید؛ گمشدن لپتاپ نباید یعنی گمشدن سرور.
- بستن ورود با رمز و ساخت کاربر جدا را طبق ترتیب درست چکلیست امنیت سرور لینوکس انجام دهید؛ ترتیب، همان چیزی است که شما را بیرون نگه نمیدارد.
سرور تمرینی میخواهید تا این تنظیمات را بیترس روی آن امتحان کنید؟ یک سرور ابری ساعتی بسازید، با کلید و رمز و کنسول کار کنید و بعد حذفش کنید؛ فقط بابت همان ساعتها پرداخت میکنید.
سؤالات پرتکرار
خطای Permission denied (publickey) یعنی چه؟
یعنی اتصال به سرور برقرار شده اما سرور SSH هیچیک از کلیدهایی را که کامپیوتر شما عرضه کرده برای آن کاربر نپذیرفته، و چون فقط publickey داخل پرانتز آمده، ورود با رمز هم روی سرور بسته است. پس مشکل از شبکه، فایروال یا خاموش بودن سرور نیست و فقط به احراز هویت مربوط است. با دستور ssh -v ببینید کدام کلید فرستاده شده و در لاگ سرور دنبال دلیل رد آن بگردید.
چرا بعد از بستن ورود با رمز دیگر به سرور وصل نمیشوم؟
چون کلیدی که فکر میکردید کار میکند، هرگز کار نمیکرده و تا آن لحظه با رمز وارد میشدید. رایجترین دلیلها ثبت کلید برای کاربر دیگر، مجوز نادرست پوشهی .ssh و فرستادهنشدن کلید درست از سمت کلاینت است. از کنسول تحت وب پنل با رمز root وارد شوید، کلید عمومی را در authorized_keys همان کاربر بگذارید و مجوزها را ۷۰۰ و ۶۰۰ کنید. دفعهی بعد پیش از بستن ورود با رمز، ورود با کلید را در یک پنجرهی جدید امتحان کنید.
مجوز درست پوشهی .ssh و فایل authorized_keys چیست؟
پوشهی .ssh باید ۷۰۰ باشد، فایل authorized_keys ۶۰۰، و مالک هر دو خود کاربر. خود پوشهی خانهی کاربر هم نباید برای گروه یا دیگران قابل نوشتن باشد، چون sshd با تنظیم پیشفرض StrictModes آن را هم بررسی میکند و در صورت ایراد کلید را نادیده میگیرد. دستورها: chmod 700 ~/.ssh و chmod 600 ~/.ssh/authorized_keys. سمت کامپیوتر شما هم کلید خصوصی نباید برای دیگران قابل خواندن باشد.
رمز root را دارم ولی SSH خطای Permission denied (publickey) میدهد؛ چطور وارد شوم؟
از کنسول تحت وب. تنظیمات sshd فقط ورود از راه شبکه را محدود میکند و روی ورود در کنسول اثری ندارد، پس با root و همان رمز وارد میشوید. در کنسول سرورهای ایران کلید عمومی را با دکمهی پیست متن به authorized_keys اضافه کنید؛ در سرورهای خارج، ورود با رمز را موقتاً با یک فایل در پوشهی sshd_config.d باز کنید، کلید را با ssh-copy-id بفرستید و فایل را پاک کنید. اگر رمز root را فراموش کردهاید، صفحهی سرور در پنل گزینهی ساخت رمز جدید دارد.
خطای git@github.com: Permission denied (publickey) را چطور رفع کنم؟
یعنی گیتهاب کلید این سرور را نمیشناسد. روی سرور یک کلید Ed25519 بسازید و محتوای فایل pub آن را در تنظیمات مخزن، بخش Deploy keys اضافه کنید، سپس با ssh -T git@github.com آزمایش کنید که پیام موفقیت بدهد. مطمئن شوید نشانی مخزن به شکل SSH است و دستور git با همان کاربری اجرا میشود که کلید برایش ساخته شده؛ sudo git pull کلیدهای root را میخواند. هر کلید استقرار فقط به یک مخزن وصل میشود.