You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
But I expected this output instead (with cURL <8.10):
0 "No error"
Seems like a cURL issue and not an issue with the wrapper, but cURL provides the CURLOPT_ECH to configure it, which the PHP wrapper does not. So I am a bit stuck. Do I have to treat errors differently depending on the cURL version I use or is there any possibility to configure the behavior here?
The CURLOPT_ECH documentation (see above) says the default setting is off, which does not seem to be true here. Is this an issue with cURL or with the wrapper changing the default somehow?
Hmm, the script doesn't error for me (Windows, cURL 8.10.1, but PHP master branch). That needs further investigation.
That's interesting. I tested on Windows 10 and in a GitLab CI with Alpine 3.20.2 (with cURL 8.9) and Alpine 3.20.3 (with cURL 8.10.1). I believed that would be independent enough to say that it is a platform independent problem.
By the way, I noticed that the problem depends on the website you are targeting, e.g. https://github.com works (they might have ECH support already) while most others don't (at least in my experience).
The point is not really the cURL version (unless it's older than 8.8.0), but whether ECH is enabled by the build; apparently, CMake builds have an option USE_ECH which is disabled by default, but our Windows builds still use Makefile.vc where apparently no such option exist.
Since ext/curl does not support CURLOPT_ECH at all, you cannot even try to change its value, nor can you find out whether it is supported (e.g. via phpinfo()), except by making an actual request as in the OP above.
It seems to me that we need to add support for CURLOPT_ECH, but given that it is a relative new cURL feature, I would treat that as feature request (not as a bug). Our official Windows builds should catch up, but as I understand it, there is no support in OpenSSL yet, so that probably takes some time.
I agree to everything you have said, but just to be clear:
The point is not really the cURL version (unless it's older than 8.8.0), but whether ECH is enabled by the build
With the php:8.3.12-alpine image, pre-installed cURL version is 8.9.1 and the problem does not occur. Although when upgrading cURL (curl and libcurl packages) to 8.10.1 leaving everything else alone (so with the same PHP and ext/curl build), I suddenly get the 101 "ECH attempted but failed".
So I am not that sure, if the cURL version itself is innocent.
I think this is working as expected. You are not supposed to use CURLINFO_OS_ERRNO value on curl_strerror. CURLINFO_OS_ERRNO is also allowed to be non-zero even if the connection is successful.
Note that the value is only set on failure, it is not reset upon a successful operation. The number is OS and system specific
The curl_strerror function merely returns the text value for a given CURLE_* constant, and in your case, the CURLINFO_OS_ERRNO info value happens to be 101, which is indeed the assigned value for an ECH error. This does not mean it was the real reason for the failure. You can also use curl_error($curl); to get a text error message.
The correct way to determine and get the error message is:
@Ayesh Thank you very much for the clarification! When I replace $error = curl_getinfo($curl, CURLINFO_OS_ERRNO); with $error = curl_errno($curl); it works as expected (that is 0 "No error"). Could have been that easy. I should probably read the documentation more carefully.
Still, I do not understand where the CURLE_ECH_REQUIRED would come from, unless an ECH attempt had been made, failed, but the connection succeeded nonetheless. According to https://curl.se/libcurl/c/CURLOPT_ECH.html that can only happen if the option was set to true, but that man page states that the default would be NULL.
I spent some time debugging this through, and I think I can explain this behavior.
For background, Curl attempts to connect to a server over IPv6 or IPv4. On a machine that does not have IPv6, if Curl attempted to connect to the server over IPv6, the socket fails with an ENETUNREACH error. Curl then attempts to connect over IPv4, and if the connection is successful, this leaves us with a situation where the last request's CURLINFO_OS_ERRNO remains ENETUNREACH, but the overall connection succeeds (CURLE_OK).
It just happens that ENETUNREACH has a value of 101 (depends on OS of course), which is the same error code for CURLE_ECH_REQUIRED. They are two sets of error codes, so this has absolutely nothing to do with ECH.
(I don't think this is a bug in Curl either; Curl indeed had an ENETUNREACH on the IPv6 attempt, so it probably makes sense to not clear it on a retry attempt.)
Ah right, thank you. I thought this was more of a bug report for CURLINFO_OS_ERRNO behavior, but you are right we can indeed add ECH option too. I could get curl to work with defo-project/openssl, I will work on a PR to add ECH support, although I don't think it's easy to test on CI just yet.
Thank you @Ayesh! And indeed, it will certainly take a while for OpenSSL to catch up. But even if we can't/won't test it in CI, it still might make sense to add support.
Activity
cmb69 commentedon Oct 8, 2024
Did you try with cURL 8.10.1? (8.10.0 was a bad release with known issues)
cracksalad commentedon Oct 8, 2024
Yes, I did. Actually tested with 8.8.0, 8.9.0 and 8.10.1 (did not even try 8.10.0). 8.10.1 is the only one of those three with the 101 error.
cmb69 commentedon Oct 8, 2024
Hmm, the script doesn't error for me (Windows, cURL 8.10.1, but PHP master branch). That needs further investigation.
cracksalad commentedon Oct 8, 2024
That's interesting. I tested on Windows 10 and in a GitLab CI with Alpine 3.20.2 (with cURL 8.9) and Alpine 3.20.3 (with cURL 8.10.1). I believed that would be independent enough to say that it is a platform independent problem.
By the way, I noticed that the problem depends on the website you are targeting, e.g. https://github.com works (they might have ECH support already) while most others don't (at least in my experience).
cracksalad commentedon Oct 12, 2024
Did a little investigation based on PHP's official docker images and the exact same script as in the original post^^:
cmb69 commentedon Oct 13, 2024
The point is not really the cURL version (unless it's older than 8.8.0), but whether ECH is enabled by the build; apparently, CMake builds have an option
USE_ECHwhich is disabled by default, but our Windows builds still use Makefile.vc where apparently no such option exist.Since ext/curl does not support
CURLOPT_ECHat all, you cannot even try to change its value, nor can you find out whether it is supported (e.g. viaphpinfo()), except by making an actual request as in the OP above.It seems to me that we need to add support for
CURLOPT_ECH, but given that it is a relative new cURL feature, I would treat that as feature request (not as a bug). Our official Windows builds should catch up, but as I understand it, there is no support in OpenSSL yet, so that probably takes some time.[-]cURL 8.10 gives error 101 "ECH attempted but failed"[/-][+]Support CURLOPT_ECH[/+]cracksalad commentedon Oct 15, 2024
I agree to everything you have said, but just to be clear:
With the
php:8.3.12-alpineimage, pre-installed cURL version is 8.9.1 and the problem does not occur. Although when upgrading cURL (curl and libcurl packages) to 8.10.1 leaving everything else alone (so with the same PHP and ext/curl build), I suddenly get the101 "ECH attempted but failed".So I am not that sure, if the cURL version itself is innocent.
Ayesh commentedon Oct 18, 2024
I think this is working as expected. You are not supposed to use
CURLINFO_OS_ERRNOvalue oncurl_strerror.CURLINFO_OS_ERRNOis also allowed to be non-zero even if the connection is successful.CURLINFO_OS_ERRNO libcurl doc has this note:
The
curl_strerrorfunction merely returns the text value for a givenCURLE_*constant, and in your case, theCURLINFO_OS_ERRNOinfo value happens to be 101, which is indeed the assigned value for an ECH error. This does not mean it was the real reason for the failure. You can also usecurl_error($curl);to get a text error message.The correct way to determine and get the error message is:
cracksalad commentedon Oct 18, 2024
@Ayesh Thank you very much for the clarification! When I replace
$error = curl_getinfo($curl, CURLINFO_OS_ERRNO);with$error = curl_errno($curl);it works as expected (that is0 "No error"). Could have been that easy. I should probably read the documentation more carefully.Nevertheless, ECH support is still desirable.
cmb69 commentedon Oct 18, 2024
Still, I do not understand where the
CURLE_ECH_REQUIREDwould come from, unless an ECH attempt had been made, failed, but the connection succeeded nonetheless. According to https://curl.se/libcurl/c/CURLOPT_ECH.html that can only happen if the option was set totrue, but that man page states that the default would beNULL.Ayesh commentedon Oct 21, 2024
I spent some time debugging this through, and I think I can explain this behavior.
For background, Curl attempts to connect to a server over IPv6 or IPv4. On a machine that does not have IPv6, if Curl attempted to connect to the server over IPv6, the socket fails with an
ENETUNREACHerror. Curl then attempts to connect over IPv4, and if the connection is successful, this leaves us with a situation where the last request'sCURLINFO_OS_ERRNOremainsENETUNREACH, but the overall connection succeeds (CURLE_OK).It just happens that
ENETUNREACHhas a value of101(depends on OS of course), which is the same error code forCURLE_ECH_REQUIRED. They are two sets of error codes, so this has absolutely nothing to do with ECH.If you try this,
oserrorstays 0:(I don't think this is a bug in Curl either; Curl indeed had an
ENETUNREACHon the IPv6 attempt, so it probably makes sense to not clear it on a retry attempt.)cmb69 commentedon Oct 21, 2024
Thank you @Ayesh – that makes perfect sense.
Ayesh commentedon Oct 22, 2024
Think we can close this?
cmb69 commentedon Oct 22, 2024
We do not yet support
CURLOPT_ECHto my knowledge.Ayesh commentedon Oct 22, 2024
Ah right, thank you. I thought this was more of a bug report for
CURLINFO_OS_ERRNObehavior, but you are right we can indeed add ECH option too. I could get curl to work with defo-project/openssl, I will work on a PR to add ECH support, although I don't think it's easy to test on CI just yet.cmb69 commentedon Oct 22, 2024
Thank you @Ayesh! And indeed, it will certainly take a while for OpenSSL to catch up. But even if we can't/won't test it in CI, it still might make sense to add support.
Sjord commentedon Nov 12, 2026
This is now merged into master in #22840