Open cracksalad opened 1 month ago
Did you try with cURL 8.10.1? (8.10.0 was a bad release with known issues)
Did you try with cURL 8.10.1? (8.10.0 was a bad release with known issues)
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.
Hmm, the script doesn't error for me (Windows, cURL 8.10.1, but PHP master branch). That needs further investigation.
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).
Did a little investigation based on PHP's official docker images and the exact same script as in the original post^^: | Image | cURL version | Affected by this issue? |
---|---|---|---|
8.3.12-alpine | 8.9.1 (pre-installed) | not affected | |
8.3.12-alpine | 8.10.1 (upgraded) | affected | |
8.3.12-bookworm | 7.88.1 (latest for Bookworm) | not affected | |
8.2.24-alpine | 8.10.1 (upgraded) | affected | |
8.4.0RC2-alpine | 8.10.1 (pre-installed) | affected |
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.
$error = curl_getinfo($curl, CURLINFO_OS_ERRNO);
CURLINFO_OS_ERRNO libcurl doc has this note:
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:
$error = curl_errno($curl);
if ($error !== CURLE_OK) {
echo $error.' "'.curl_strerror($error).'"'.PHP_EOL;
}
@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.
Nevertheless, ECH support is still desirable.
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.
If you try this, oserror
stays 0:
$curl = curl_init('https://php.net');
curl_setopt($curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_exec($curl);
$error = curl_getinfo($curl, CURLINFO_OS_ERRNO); // 0
echo $error.' "'.curl_strerror($error).'"'.PHP_EOL; // 0
(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.)
Thank you @Ayesh – that makes perfect sense.
Think we can close this?
We do not yet support CURLOPT_ECH
to my knowledge.
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.
Description
Not sure, if this is really a bug. It is more like a question if this is a bug
The following code:
Resulted in this output (with cURL >=8.10):
But I expected this output instead (with cURL <8.10):
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? TheCURLOPT_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?PHP Version
PHP 8.3.12
Operating System
No response