Skip to content

Support CURLOPT_ECH #16305

Open
Open

Description

@cracksalad

Description

Not sure, if this is really a bug. It is more like a question if this is a bug

The following code:

<?php
$curl = curl_init('https://php.net');
curl_exec($curl);

$error = curl_getinfo($curl, CURLINFO_OS_ERRNO);
echo $error.' "'.curl_strerror($error).'"'.PHP_EOL;

curl_close($curl);

Resulted in this output (with cURL >=8.10):

101 "ECH attempted but failed"

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?

PHP Version

PHP 8.3.12

Operating System

No response

Activity

  1. cmb69 commented on Oct 8, 2024

    @cmb69
    Member

    Did you try with cURL 8.10.1? (8.10.0 was a bad release with known issues)

  2. cracksalad commented on Oct 8, 2024

    @cracksalad
    Author

    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.

  3. cmb69 commented on Oct 8, 2024

    @cmb69
    Member

    Hmm, the script doesn't error for me (Windows, cURL 8.10.1, but PHP master branch). That needs further investigation.

  4. cracksalad commented on Oct 8, 2024

    @cracksalad
    Author

    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).

  5. cracksalad commented on Oct 12, 2024

    @cracksalad
    Author

    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
  6. cmb69 commented on Oct 13, 2024

    @cmb69
    Member

    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.

  7. changed the title [-]cURL 8.10 gives error 101 "ECH attempted but failed"[/-] [+]Support CURLOPT_ECH[/+] on Oct 13, 2024
  8. cracksalad commented on Oct 15, 2024

    @cracksalad
    Author

    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.

  9. Ayesh commented on Oct 18, 2024

    @Ayesh
    Member

    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;
    }
  10. cracksalad commented on Oct 18, 2024

    @cracksalad
    Author

    @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.

  11. cmb69 commented on Oct 18, 2024

    @cmb69
    Member

    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.

  12. Ayesh commented on Oct 21, 2024

    @Ayesh
    Member

    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.)

  13. cmb69 commented on Oct 21, 2024

    @cmb69
    Member

    Thank you @Ayesh – that makes perfect sense.

  14. Ayesh commented on Oct 22, 2024

    @Ayesh
    Member

    Think we can close this?

  15. cmb69 commented on Oct 22, 2024

    @cmb69
    Member

    We do not yet support CURLOPT_ECH to my knowledge.

  16. Ayesh commented on Oct 22, 2024

    @Ayesh
    Member

    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.

  17. cmb69 commented on Oct 22, 2024

    @cmb69
    Member

    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.

  18. Sjord commented on Nov 12, 2026

    @Sjord
    Contributor

    This is now merged into master in #22840

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions