<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    I was able to solve the issue, fixing both squid-side
    "error:1425F175:SSL routines:ssl_choose_client_version:inappropriate
    fallback (1/-1/0)" and client-side certificate verification errors
    when attempting to contact TLS 1.3 server over a TLS 1.3-enabled
    squid from a TLS 1.2 client. I will first explain what causes the
    issue before presenting my solution, which involves changes of the
    squid code base, for anybody who is affected by the same problem.<br>
    <br>
    I have inspected the squid source code and noticed that TLS peeking
    works roughly like this:<br>
    <br>
    1. The client sends a client_hello, which is parsed by squid using a
    custom handshake parser.¬† <-- Uses TLS 1.2<br>
    2. Squid creates an OpenSSL TLS session for the peeked connection¬†
    <-- Uses TLS 1.3!<br>
    3. Squid forwards the original client_hello handshake message to the
    server <-- TLS 1.2<br>
    4. Squid passes the received server_hello response to the OpenSSL
    session created previously¬† <-- Response uses TLS 1.2 - Problem!<br>
    <br>
    Now, the "problem" is that TLS 1.3 defines a set of new protocol
    downgrade attack prevention mechanisms (can be found e.g. here:
<a class="moz-txt-link-freetext" href="https://blog.gypsyengineer.com/en/security/how-does-tls-1-3-protect-against-downgrade-attacks.html">https://blog.gypsyengineer.com/en/security/how-does-tls-1-3-protect-against-downgrade-attacks.html</a>).
    Both OpenSSL and most likely the server implement these. This
    includes that the server random in the TLS 1.2 server_hello contains
    an indicator that the server is TL 1.3-capable. The OpenSSL session
    created by squid detects this, notices that it is TLS 1.3-capable
    itself, and closes the connection because it assumes a protocol
    downgrade attack! Little does it know, that our client actually only
    supports TLS 1.2, so we *want* the lower protocol version.<br>
    <br>
    My solution includes setting the maximum TLS version of the OpenSSL
    session to the version received from the client. This proved a
    little bit difficult, since the way TLS versions are negotiated has
    also been changed by the TLS 1.3 specification, and the squid
    handshake parser was not yet able to detect TLS 1.3 correctly - I
    have therefore also implemented parsing of the <span
      class="blob-code-inner blob-code-marker" data-code-marker="+"><span
        class="pl-c">SupportedVersions TLS Extension and a preliminary
        support for sparse version ranges. You can find all these
        changes at
        <a class="moz-txt-link-freetext" href="https://github.com/nthuemmel/squid/tree/tls_downgrade_compatibility">https://github.com/nthuemmel/squid/tree/tls_downgrade_compatibility</a>
        , which is a fork of squid 4.9. Feel free to compile & test
        it if you have a transparent peek-and-splice setup and are
        affected by the "</span></span><span class="blob-code-inner
      blob-code-marker" data-code-marker="+"><span class="pl-c">inappropriate
        fallback" problem.<br>
        <br>
        I would of course be glad if the fix could be merged into the
        main squid repository. If you are a dev, please let me know what
        you think and if I should open a pull request. There are still
        some TODOs left, because I wasn't sure what the best way is to
        integrate some of the changes. Notably, there was also a comment
        which discourages setting a maximum version for the OpenSSL
        session to improve peek+bump compatibility - I don't have a
        setup to which this applies, so I don't know how big of an
        impact this is or if it is still relevant.<br>
        <br>
        Best Regards<br>
        Nikolaus<br>
      </span></span>
  </body>
</html>