C 30 сентября 2021 года на сайтах WordPress, для которых был установлен сертификат Let’s Encrypt, могут перестать работать HTTP API запросы.
Например такой запрос будет выдавать ошибку:
$res = wp_remote_get( 'https://wp-kama.ru/' ); if( is_wp_error( $res ) ){ echo $res->get_error_message(); }
Получим:
cURL error 60: SSL certificate problem: certificate has expired
Такую ошибку можно будет увидеть где угодно, например:
- в админке при проверке обновлений WordPress
- при проверке обновлений плагинов
- при обращении к апи любого сервиса. Например, перестанет работать плагин TinyPNG — JPEG, PNG & WebP image compression и куча других, которые используют какие бы то ни было запросы.
Почему мы видим ошибку certificate has expired?
Почему так происходит подробно расписано на хабре.
Если коротко, то в ядре WP есть файл корневых сертификатов /wp-includes/certificates/ca-bundle.crt
который используется для проверки SSL всех запросов созданных через HTTP API. В этом файле просрочен один из корневых сертификатов на основе которого был создан сертификат для вашего сайта. Поэтому запрос не может пройти проверку и выдается такая ошибка.
С очередными обновлениями WP эта ошибка должна пропасть, но вот что делать если решение нужно уже сегодня, или если вы не планируете обновлять WordPress, а рабочие HTTP запросы нужны.
Решение ошибки: cURL error 60: SSL certificate has expired
Вариант 1
Нужно обновить контент файла /wp-includes/certificates/ca-bundle.crt
изменить его на контент этого файла https://curl.haxx.se/ca/cacert.pem.
Изменять в данном случае файл ядра допустимо, потому что при следующем обновлении WP проблема исчезнет. См. соответствующий коммит на GitHub.
Это можно сделать вручную:
- Скачайте файл по ссылке https://curl.haxx.se/ca/cacert.pem.
- Обновите контент
/wp-includes/certificates/ca-bundle.crt
контентом из скаченного файла.
Или используйте следующий код
Использовать код удобно, когда у вас есть возможность запустить код из админки или как-то еще, например через плагин Code Snippets.
Добавьте следующий код куда угодно и перейдите на страницу http://ВАШСАЙТ.com/?update-wp-ca-bundle
.
/** * Goto http://yoursite.com/?update-wp-ca-bundle */ if( isset( $_GET['update-wp-ca-bundle'] ) ){ $crt_file = ABSPATH . WPINC . '/certificates/ca-bundle.crt'; $new_crt_url = 'https://curl.haxx.se/ca/cacert.pem'; if( is_writable( $crt_file ) ){ $new_str = file_get_contents( $new_crt_url ); if( $new_str && strpos( $new_str, 'Bundle of CA Root Certificates' ) ){ $up = file_put_contents( $crt_file, $new_str ); echo $up ? 'OK: ca-bundle.crt updated' : 'ERROR: can`t put data to ca-bundle.crt'; } else { echo 'ERROR: cant download https://curl.haxx.se/ca/cacert.pem'; } } else { echo 'ERROR: ca-bundle.crt not writable'; } exit; }
После использования, код нужно удалить.
Вариант 2
Решить проблему можно через хук http_request_args. Этот хук нужно использовать в MU плагине.
-
Создайте файл
loader.php
в папкеwp-content/mu-plugins
(если такой папки у вас нет, создайте её). -
Добавьте следующий код в этот файл:
<?php require_once __DIR__ .'/fix-wp-ca-bundle/main.php';
-
Создайте папку
wp-content/mu-plugins/fix-wp-ca-bundle
. -
Создайте файлы:
main.php
иca-bundle.crt
в папкеfix-wp-ca-bundle
.Добавьте следующий код в эти файлы.
Код файла
main.php
:<?php defined( 'ABSPATH' ) || exit; /** * Update the path to the WordPress trusted root certificates. * * Actual certificates can be downloaded at this link: http://curl.haxx.se/ca/cacert.pem */ add_filter( 'http_request_args', 'http_request_change_sslsertificates' ); function http_request_change_sslsertificates( $parsed_args ){ $parsed_args[ 'sslcertificates' ] = __DIR__ . '/ca-bundle.crt'; return $parsed_args; }
Контент файла
ca-bundle.crt
:Скопируйте контент этого файла http://curl.haxx.se/ca/cacert.pem
Должна получится такая структура:
Готово! Теперь все должно работать как и прежде.
Based on my recent experience, I believe that the message «self signed certificate in certificate chain» tells you the issue exactly — which is that whichever SSL site you are trying to access has a certificate in the chain that is not in the bunch that is referenced by cacert.pem.
This makes sense because the error reports that it is a self-signed certificate.. i.e. It would never be included in the downloaded cacert.pem file.
My solution was to get a Base64 encoded file containing the certificate chain of the site that I am trying to access.
How to: Use a browser to access the site you are trying to access, click the
certificate part of the address (usually to the left of the address box with
a lock icon) and the click on whatever your interface supports to see the
list of certificates in the chain. Manually export those certificates to a
text file.
Then append this text file with a text editor to the list of certificates (cacert.pem) that PHP is using for CURL actions.
You mention WordPress.. WordPress v4.9.6 has a bundle of certificates that it specifically references when it is upgrading or installing plugins at ./WordPress Instancewp-includescertificates. My stop-gap solution was to append the text file above (containing the local self signed-certificate chain) to the ca-bundle.crt file that you will find in that location.
One caveat — when you upgrade WordPress it will overwrite the ca-bundle.crt file, so you will have to re-add them — unless someone has a better solution..?
From September 30, 2021, HTTP API requests may stop working on WordPress sites that have a Let’s Encrypt certificate installed.
For example, a request like this will result in an error:
$res = wp_remote_get( 'https://wp-kama.com/' ); if( is_wp_error( $res ) ){ echo $res->get_error_message(); }
We get it:
cURL error 60: SSL certificate problem: certificate has expired
Such an error can be seen anywhere, for example:
- In the admin panel when checking for WordPress updates.
- When checking for plugin updates.
- When accessing the api of any service. For example, will stop working plugin TinyPNG — JPEG, PNG & WebP image compression and a bunch of others that use any kind of requests.
Why do we see the error certificate has expired?
In brief, WP core has a file of root certificates /wp-includes/certificates/ca-bundle.crt
which is used to check SSL of all requests created through HTTP API. In this file one of the root certificates has expired which was used to create a certificate for your site. Therefore, the request can not pass verification and generates this error.
More detailed explanation:
Without going into too much detail, a couple of words for non-specialists as to why the expiration of a DST Root CA X3
certificate will affect certificates issued by Let’s Encrypt. Each system that validates a certificate has its own repository of trusted root certificates. The system will trust certificates that are signed using the private key of one of these root certificates during validation. Root certificates themselves normally have long expiration dates, are seldom changed and are not used when generating end subject certificates (in this case domain name certificates), instead a public key infrastructure implies using chains of trust — root certificates are used to sign intermediate certificates and already using them to sign end subject certificates (domain certificates). Furthermore, in order for a system to trust an end subject certificate, it must be able to trace the full chain from this certificate to one of the root certificates it trusts.
When Let’s Encrypt appeared, its ISRG Root X1
root certificate (like any new root certificate) could not quickly find its way into the trusted certificate stores of a significant number of systems. At the same time, for the successful functioning of the project the issued certificates from the very beginning had to be trusted by the maximum number of systems «out of the box» (without any additional actions from the users of these systems). In this regard, for certificates Let’s Encrypt began to use the chain of trust leading to the root certificate DST Root CA X3
, which is recognized by most systems.
With the next WP update this error disappear, but here’s what to do if you need the solution today, or if you do not plan to update WordPress, but need working HTTP requests.
Solution: cURL error 60: SSL certificate has expired
You need to update the content of /wp-includes/certificates/ca-bundle.crt
file. You need to change it to the content of the https://curl.se/ca/cacert.pem file.
Changing the core file in this case is acceptable, because the next time you update WP, the problem will go away. See corresponding commit on GitHub.
It can be done manually
-
Download this file https://curl.se/ca/cacert.pem.
-
Update content of
/wp-includes/certificates/ca-bundle.crt
with content from the downloaded file. - DONE! Everything should now work as before.
Or use the following code to perform this operation programmatically
Using the code is handy when you have the ability to run the code from the admin panel, for example using Code Snippets plugin.
-
Add the following code into the themes functions.php file (or in Code Snippets plugin):
/** * Goto http://yoursite.com/?update-wp-ca-bundle */ if( isset( $_GET['update-wp-ca-bundle'] ) ){ $crt_file = ABSPATH . WPINC . '/certificates/ca-bundle.crt'; $new_crt_url = 'http://curl.haxx.se/ca/cacert.pem'; if( is_writable( $crt_file ) ){ $new_str = file_get_contents( $new_crt_url ); if( $new_str && strpos( $new_str, 'Bundle of CA Root Certificates' ) ){ $up = file_put_contents( $crt_file, $new_str ); echo $up ? 'OK: ca-bundle.crt updated' : 'ERROR: can`t put data to ca-bundle.crt'; } else { echo 'ERROR: can't download curl.haxx.se/ca/cacert.pem'; } } else { echo 'ERROR: ca-bundle.crt not writable'; } exit; }
After use, delete this code.
-
Visit
http://YOURSITE.com/?update-wp-ca-bundle
the page.Replace
YOURSITE.com
to your domain… - DONE! Everything should now work as before.
Everything worked fine a week ago. Lets Encrypt certificate on the site is valid. I am currently getting the following error while creating a product:
{"code":"woocommerce_product_image_upload_error","message":"Error getting remote image https://mysite.com/wp-content/uploads/2021/10/60c739fd1-1.jpg. Error: cURL error 60: SSL certificate problem: certificate has expired","data":{"status":400}}
In this case, the picture is available by the URL.
Tried these solutions (https://wp-kama.com/note/error-making-request-wordpress[enter link description here]1) but doesn’t help.
asked Oct 9, 2021 at 5:44
In the file /etc/ca-certificates.conf, you need to find the line:
mozilla / DST_Root_CA_X3.crt
and put the «!» symbol at the beginning of the dates:
! mozilla / DST_Root_CA_X3.crt
Next, you need to run the command:
sudo update-ca-certificates
answered Oct 9, 2021 at 6:28
This is a one liner, that can be added to a Dockerfile
with RUN
or just ran in the terminal
# Fix Outdate Let's Encrypt cert
curl --silent --insecure https://letsencrypt.org/certs/isrgrootx1.pem >> /usr/local/share/ca-certificates/isrgrootx1.pem &&
sed -i 's=mozilla/DST_Root_CA_X3.crt=!mozilla/DST_Root_CA_X3.crt=g' /etc/ca-certificates.conf &&
update-ca-certificate
It pulls down the latest cert insecurely so carries risk.
This didn’t resolve the problem for me because PHP was using a different trust store from the systemwide one.
Our apache2 instance which is running PHP was in a Docker container. The trust store needed to be updated with a script just before the start of apache2, because it was created at runtime overwriting any changes made before execution.
Setting the path to true
should use the system trust store rather than a custom bundle.
# Pull updated CA cert bundle
CERT_PATH=/var/www/html/wp-includes/certificates
mkdir -p $CERT_PATH && curl --silent https://curl.se/ca/cacert.pem > $CERT_PATH/ca-bundle.crt
answered Oct 28, 2021 at 15:18
tomwjtomwj
112 bronze badges
‘cURL error 60 SSL certificate problem’ occurs when we make a cURL call to third party services.
Here at Bobcares, we have seen several such cURL command related errors as part of our Server Management Services for web hosts and online service providers.
Today we’ll take a look at the causes for this error and see the fix.
What causes ‘cURL error 60 SSL certificate problem’ error to occur
Digital certificates are mainly used in transferring sensitive content. These digital certificates are issued by certificate authorities or CA.
When a cURL receives a server CA that is not signed by one of the trusted certificates in the installed CA certificate store, then it will lead to an error: “failed to verify the legitimacy of the server” during the SSL handshake. As a result, SSL will then refuse the communication with the server leading to an SSL error.
In short, this error occurs because cURL makes sure to verify and make a secure connection request using a self-signed certificate. But when it doesn’t find any valid certificate then it throws this error message.
How we fix the error ‘cURL error 60 SSL certificate problem’
Now let’s see how our Support Engineers resolve this error message.
1. Re-download the cURL CA-Bundle from the cURL site to fix this error. Here are the steps for it.
- First, download the “cacert.pem” from the link: http://curl.haxx.se/docs/caextract.html
- Next copy the complete page and save it as “cacert.pem”
- Now, open the php.ini file and add the following line in it.
curl.cainfo = “[pathtofile]cacert.pem”
In, case, if the php.ini file doesn’t have the curl.cainfo line, then just add it to the end of the file. Then add the file path where cacert.pem file is saved. - Finally, restart the web server or on Windows, restart the application pool and try the request again.
2. If the insecure certificate is a self-signed, known-trusted certificate, then load the certificate to your local trusted certificate location for your OS.
[Need any further assistance in fixing curl errors? – We are here to help you.]
Conclusion
In short, this error occurs when cURL doesn’t find any valid certificate to communicate over https. Today, we saw how our Support Engineers fix this error.
PREVENT YOUR SERVER FROM CRASHING!
Never again lose customers to poor server speed! Let us help you.
Our server experts will monitor & maintain your server 24/7 so that it remains lightning fast and secure.
GET STARTED
var google_conversion_label = «owonCMyG5nEQ0aD71QM»;
“cURL error 60: SSL certificate problem: unable to get local issuer certificate” is a common error that occurs when your website tries to communicate with an external API via HTTPS and the SSL certificate on the server is not verified or properly configured. Although this error can be seen on any server you are more likely to see this issue on a localhost environment running on wampp/xampp.
Contact your web host to make sure that the SSL certificate is properly configured on the server. As of PHP 5.6 if the certificate is not verified you will also get a warning notice on your website.
How to fix cURL error 60: SSL certificate problem: unable to get local issuer certificate on localhost
1. Download the cacert.pem file from the official cURL website here.
2. Go the directory where you have installed xampp and put it in the ssl folder. For example,
C:xamppphpextrassslcacert.pem D:programxamppphpextrassslcacert.pem
3. Open your php.ini file and search for “curl.cainfo”.
4. Once you have found it, specify the path to the .pem file in the curl.cainfo section. For example,
curl.cainfo = "C:xamppphpextrassslcacert.pem"
The line could be commented out with a semicolon right before curl.cainfo. So make sure to uncomment it and replace ;curl.cainfo = with the line above.
5. Restart Apache so the new changes take effect on your localhost server.
That should fix the cURL error 60 issue on your web server. If you have any other suggestions for fixing this issue feel free to share it in the comments.
Не активируется/не обновляется тема или плагин?
Если у Вас не активируется/не обновляется тема или плагин, большая вероятность, что не проходит запрос от Вашего сайта до нашего сервера. Попробуйте выполнить следующие шаги, проверяя после каждого активацию/обновление темы.
- Проверьте, нет ли в файле wp-config.php строчки, блокирующей внешние HTTP-запросы. Если есть, удалите или закомментируйте строчку:
define( 'WP_HTTP_BLOCK_EXTERNAL', true );
- Добавьте в wp-config.php следующую строчку, разрешающую запросы к нашим серверам:
define( 'WP_ACCESSIBLE_HOSTS', 'wpshop.ru,*wpshop.ru,*wpgenerator.ru,*wpshop.biz,*.wordpress.org,localhost' );
- Если у Вас включены плагины безопасности, попробуйте временно деактивировать их и проверить еще раз. Часто в таких плагинах есть защита от запросов к внешним ресурсам.
Проблема при активации может быть связана с устаревшей версией TLS протокола, подробнее здесь.
Вам помог ответ?
Похожие вопросы
Открепить
При отправке запроса средствами cURL можно получить ошибку: SSL certificate problem: unable to get local issuer certificate
.
Можно просто отключить проверку SSL-сертификата. Например, вот так:
$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://site.com'); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); $result = curl_exec($ch);
Более правильным решением будет добавление сертификата в доверенные. Скачать свежую версию сертификата по адресу https://curl.haxx.se/ca/cacert.pem. Поместить данный файл на сервер. У меня это директория S:Serverbinphpextrasssl
.
Далее в настройках файла php.ini
указать путь к данному файлу:
[curl] curl.cainfo = S:Serverbinphpextrassslcacert.pem
Перезапустить apache.
// Находясь в директории bin ( путь/к/файлу/httpd ) httpd -k start httpd -k restart httpd -k stop (httpd - k shutdown) // Работа с apache как со службой Windows net stop apache2.4 net start apache2.4 // Мой httpd.exe S:ServerbinApache24binhttpd -k restart