ESC را فشار دهید تا بسته شود

رفع خطای cURL error 60 در وردپرس؛ عیب‌یابی SSL Certificate و CA Bundle

فهرست

وقتی وردپرس هنگام نصب افزونه، به‌روزرسانی یا اتصال به API پیام cURL error 60: SSL certificate problem: unable to get local issuer certificate می‌دهد، معمولاً اعتبارسنجی زنجیره گواهی TLS در یکی از لایه‌های WordPress، PHP/cURL، سیستم‌عامل یا سرور مقصد شکست خورده است. ابتدا با curl -Iv و یک درخواست wp_remote_get() مشخص کنید مشکل در کدام لایه است؛ سپس CA bundle یا زنجیره گواهیِ همان لایه را اصلاح کنید. خاموش‌کردن sslverify یا استفاده دائمی از curl -k راه‌حل امن نیست.

خطای cURL error 60 چه زمانی در وردپرس دیده می‌شود؟

سناریوی رایج این است که پنل مدیریت وردپرس باز می‌شود، اما به‌روزرسانی افزونه‌ها، ارتباط با سرویس پرداخت یا ارسال درخواست HTTPS به یک API خارجی ناموفق است. متن خطا ممکن است «unable to get local issuer certificate» یا «certificate verify failed» باشد. این پیام به معنی منقضی‌شدن قطعی گواهی سایت خودتان نیست؛ باید مقصد درخواست خروجی و مسیر اعتماد گواهی را پیدا کنید.

اگر Site Health نیز خطای اتصال خروجی یا Loopback دارد، مسیر تشخیص DNS، فایروال و درخواست‌های داخلی را با آموزش عیب‌یابی Loopback Request Failed در وردپرس مقایسه کنید؛ خطای Loopback لزوماً همان cURL 60 نیست.

پیش‌نیازها و اقدامات ایمن پیش از تغییر

  • دسترسی SSH به سرور یا امکان مشاهده تنظیمات PHP از کنترل‌پنل هاست، و در صورت امکان WP-CLI.
  • نام دامنه مقصدی که درخواست HTTPS به آن خطا می‌دهد؛ برای مثال https://api.example.com را با مقصد واقعی جایگزین کنید.
  • بکاپ از فایل php.ini و هر CA bundle سفارشی پیش از ویرایش؛ اگر هاست اشتراکی است از پشتیبانی بخواهید تغییر سطح سیستم را انجام دهد.
  • زمان سیستم و نسخه‌های WordPress، PHP و cURL را ثبت کنید؛ مسیر PHP در وب و CLI ممکن است متفاوت باشد.

احتیاط: خروجی phpinfo()، توکن API، مسیرهای حساس و کلید خصوصی را در صفحات عمومی منتشر نکنید. آزمایش‌های زیر را با دامنه قابل‌اعتماد و بدون ارسال اطلاعات محرمانه اجرا کنید.

مرحله ۱: مشخص کنید مشکل از سرور است یا فقط وردپرس

در SSH ابتدا از یک مقصد HTTPS شناخته‌شده و سپس از دامنه API مشکل‌دار تست بگیرید:

date -u
curl --version
curl -Iv --connect-timeout 10 https://wordpress.org/
curl -Iv --connect-timeout 10 https://api.example.com/

اگر curl در هر دو مقصد خطای 60 می‌دهد، CA store سیستم یا پراکسی TLS را بررسی کنید. اگر فقط یک دامنه خطا می‌دهد، گواهی و chain همان مقصد یا مسیر بازرسی TLS محتمل‌تر است. اگر curl موفق است ولی وردپرس خطا دارد، لایه PHP/WordPress را جداگانه آزمایش کنید. کد وضعیت HTTP مانند 403 یا 404 بعد از برقراری TLS، به‌خودی‌خود خطای گواهی نیست.

برای دیدن جزئیات chain سرور مقصد، نام میزبان واقعی را جایگزین کنید:

openssl s_client -connect api.example.com:443 
  -servername api.example.com 
  -verify_hostname api.example.com 
  -verify_return_error </dev/null

خروجی را از نظر Verify return code، گواهی صادرکننده و تاریخ اعتبار بررسی کنید. اگر سرور مقصد intermediate certificate را کامل ارائه نمی‌کند، باید تنظیمات TLS همان سرور اصلاح شود؛ اضافه‌کردن تصادفی گواهی به سرور وردپرس جایگزین تعمیر chain نیست.

مرحله ۲: درخواست واقعی WordPress HTTP API را تست کنید

در پوشه نصب وردپرس، با کاربر مناسب و WP-CLI این تست خواندنی را اجرا کنید:

wp eval '$r = wp_remote_get("https://wordpress.org/", ["timeout" => 15]); if (is_wp_error($r)) { echo $r->get_error_message() . PHP_EOL; } else { echo "HTTP " . wp_remote_retrieve_response_code($r) . PHP_EOL; }'

اگر پاسخ با HTTP 200 یا کد HTTP دیگری برگردد، ارتباط TLS در این تست برقرار شده است. اگر WP_Error با عبارت cURL 60 برگردد، خطا در مسیر اجرای وردپرس نیز بازتولید شده است. این تست را برای مقصد واقعیِ خطادار تکرار کنید، اما آدرس دارای توکن را داخل تاریخچه شِل قرار ندهید.

WordPress HTTP API به‌صورت پیش‌فرض sslverify=true دارد و از فایل CA bundle خود در wp-includes/certificates/ca-bundle.crt نیز استفاده می‌کند. بنابراین موفقیت curl سیستم به‌تنهایی سالم‌بودن CA مورد استفاده وردپرس را اثبات نمی‌کند. اگر هم‌زمان خطاهای 401 یا 403 دارید، آن‌ها را با راهنمای خطاهای احراز هویت REST API وردپرس جداگانه بررسی کنید.

مرحله ۳: CA Bundle سیستم‌عامل را بررسی و در صورت نیاز تعمیر کنید

Ubuntu و Debian

در توزیع‌های Debian-based مسیر معمول bundle سیستم /etc/ssl/certs/ca-certificates.crt است. قبل از تغییر، وجود و تاریخ فایل را بررسی کنید:

ls -lh /etc/ssl/certs/ca-certificates.crt
dpkg -l ca-certificates
sudo apt-get update
sudo apt-get install --reinstall ca-certificates
sudo update-ca-certificates

در خروجی update-ca-certificates تعداد گواهی‌های افزوده یا حذف‌شده گزارش می‌شود. این دستور فقط CAهای پیکربندی‌شده را بازسازی می‌کند و گواهی نامعتبر سرور مقصد را معتبر نمی‌سازد. در محیط تولید ابتدا اثر تغییر روی سرویس‌های وابسته را بسنجید.

AlmaLinux، Rocky Linux و RHEL

rpm -q ca-certificates
sudo dnf reinstall ca-certificates
sudo update-ca-trust extract
curl -Iv https://wordpress.org/

روی توزیع‌های قدیمی ممکن است ابزار مدیریت بسته متفاوت باشد. به‌جای دانلود فایل CA از منابع ناشناس، از بسته‌های رسمی توزیع و مخزن قابل‌اعتماد استفاده کنید.

مرحله ۴: مسیر CA در PHP و PHP-FPM را تشخیص دهید

تنظیمات curl.cainfo و openssl.cafile مربوط به PHP هستند و الزاماً با CA store خط فرمان یکسان نیستند. ابتدا از CLI بررسی کنید:

php --ini
php -r 'echo "curl.cainfo=".ini_get("curl.cainfo").PHP_EOL; echo "openssl.cafile=".ini_get("openssl.cafile").PHP_EOL;'
php -r 'print_r(openssl_get_cert_locations());'

اگر php -m افزونه curl را نشان نمی‌دهد، باید وجود و فعال‌بودن آن در نسخه PHP مرتبط با سایت بررسی شود. نکته مهم: خروجی php --ini برای CLI است؛ در PHP-FPM یا LiteSpeed ممکن است php.ini و مقدارها متفاوت باشند. مسیر واقعی را در پنل PHP Selector یا اطلاعات محدود و خصوصی PHP-FPM پیدا کنید. در هاست اشتراکی ممکن است تغییر CA store سیستم‌عامل در اختیار کاربر نباشد؛ در این حالت ابتدا موضوع را با پشتیبانی مطرح کنید. هنگام انتخاب سرویس میزبانی نیز می‌توانید پلن‌های هاست وان‌سرور را از نظر نسخه PHP، دسترسی به تنظیمات PHP و سطح پشتیبانی مقایسه کنید؛ وجود این دسترسی‌ها را برای هر پلن جداگانه استعلام بگیرید.

فقط در صورتی که تنظیمات CA فعلی اشتباه یا خالی است و نیاز به CA سفارشیِ معتبر دارید، در فایل پیکربندی همان نسخه PHP وب از مسیر مطلق معتبر استفاده کنید:

; php.ini — example for Debian/Ubuntu
curl.cainfo = "/etc/ssl/certs/ca-certificates.crt"
openssl.cafile = "/etc/ssl/certs/ca-certificates.crt"

در بعضی استقرارها مقدار خالی طبیعی است و PHP از CA store پیش‌فرض سیستم استفاده می‌کند؛ آن را صرفاً برای «پرکردن فیلد» تغییر ندهید. بعد از اصلاح، فقط سرویس PHP-FPM مرتبط با همان سایت را با روش مدیریت هاست خود Reload/Restart کنید؛ نام سرویس را حدس نزنید. سپس مقادیر را در محیط وب و تست WordPress دوباره بررسی کنید.

مرحله ۵: CA bundle خود وردپرس را بررسی کنید

اگر PHP و cURL سیستم سالم‌اند ولی wp_remote_get() همچنان خطای 60 دارد، از پوشه وردپرس وجود فایل bundle را بررسی کنید:

wp eval 'echo ABSPATH . WPINC . "/certificates/ca-bundle.crt" . PHP_EOL;'
wp core verify-checksums

اگر checksum فایل‌های هسته با نسخه رسمی سازگار نیست، ابتدا بکاپ و منشأ تغییر را بررسی کنید و از مسیر امن به‌روزرسانی/بازنصب هسته اقدام کنید. فایل‌های هسته وردپرس را دستی با bundle ناشناس جایگزین نکنید. اگر افزونه‌ای مسیر sslcertificates را override کرده، تنظیمات همان افزونه را نیز بررسی کنید.

مرحله ۶: وقتی فقط یک دامنه HTTPS خطا دارد

اگر curl -Iv https://wordpress.org/ موفق ولی مقصد دیگری ناموفق است، گواهی همان مقصد را از نظر نام دامنه (SAN)، زمان اعتبار، intermediate CA و تنظیمات reverse proxy/CDN بررسی کنید. تفاوت صدور و اعتبارسنجی گواهی را در آموزش DNS Validation برای SSL و TLS ببینید. داشتن SSL روی سایت وردپرسی به این معنی نیست که زنجیره گواهی همه APIهای مقصد درست است.

اگر سازمان از TLS inspection/proxy استفاده می‌کند، فقط CA ریشه‌ای را که مدیر شبکه و سیاست امنیتی سازمان تأیید کرده است به trust store مناسب اضافه کنید؛ از اعتماد به هر گواهی دریافت‌شده از شبکه ناشناس خودداری کنید.

چرا خاموش‌کردن SSL verification خطرناک است؟

استفاده از curl -k، تنظیم CURLOPT_SSL_VERIFYPEER=false یا قرار دادن sslverify=false در کد وردپرس، خطا را پنهان می‌کند اما احراز هویت سرور مقصد را از بین می‌برد و امکان حمله میانجی را بالا می‌برد. این گزینه‌ها را به‌عنوان راهکار عملیاتی یا تغییر سراسری WordPress پیشنهاد نمی‌کنیم. راه درست، اصلاح CA مورد اعتماد یا chain مقصد است.

تست نهایی و معیار موفقیت

  1. در همان سرور curl -Iv برای مقصد واقعی بدون خطای certificate verify اجرا شود.
  2. در WordPress، wp_remote_get() دیگر WP_Error مربوط به cURL 60 برنگرداند؛ کد HTTP مقصد جداگانه بررسی شود.
  3. در محیط PHP-FPM وب، تنظیمات CA و نسخه PHP مورد استفاده سایت با انتظار شما مطابقت داشته باشد.
  4. عملیات واقعیِ شکست‌خورده (به‌روزرسانی افزونه یا فراخوانی API) در محیط کنترل‌شده تکرار و موفق شود.
  5. هیچ تنظیم sslverify=false یا استثنای ناامن TLS در کد باقی نمانده باشد.

Rollback و بازیابی در صورت اختلال پس از تغییر

اگر بعد از اصلاح php.ini یا trust store سرویس دیگری از کار افتاد، فایل تنظیمات نسخه پشتیبان را برگردانید و فقط سرویس PHP مرتبط را Reload کنید. اگر CA سفارشی جدید افزوده‌اید، همان CA مشخص را پس از تأیید وابستگی‌ها حذف و trust store را بازسازی کنید؛ کل CA store را پاک نکنید. تغییرات را در تیکت یا لاگ نگهداری ثبت کنید تا علت خطا و اقدام انجام‌شده قابل ردیابی باشد.

منابع فنی برای بررسی بیشتر

این راهنما بر پایه مستندات رسمی cURL TLS Certificate Verification، PHP curl.cainfo، PHP openssl.cafile و WordPress HTTP API تنظیم شده است. تفاوت مسیر CA در نسخه‌های PHP و توزیع‌های لینوکس را همیشه با محیط واقعی سرور تطبیق دهید.

Rate this post
اشتراک گذاری نوشته در:

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *