goquichttp3webtransportquic-go

Got "Opening Handshake Failed" when trying to run webtransport samples locally


I've been trying to run some of the samples of the implementation of WebTransport, like

But all of the samples got the same error when I tried accessing them through the browser, which is "Opening Handshake Failed".

Opening Handshake Failed

I created a self-signed certificate using this command

openssl req -newkey rsa:2048 -nodes -keyout cert.key \
-x509 -out cert.pem -subj '/CN=Test Certificate' \
-addext "subjectAltName = DNS:localhost"

I ran them through wsl2 and accessed the client from Google Chrome Canary version 121. I added these flags just like what's mentioned in the comments here.

--origin-to-force-quic-on=localhost:4443 localhost:1234 --allow-insecure-localhost --ignore-certificate-errors-spki-list=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=

Has anyone had this problem, or knows what I missed?


Solution

  • This was a major headache for me the last few days as well trying to get simple proofs of concept spun up.

    You mention you are using wsl2 -- that's the failure point. wsl2 does not support forwarding fragmented UDP packets, https://github.com/microsoft/WSL/issues/6351 . It looks like in some cases people have had luck with [experimental] settings for networkingMode=mirrored and hostAddressLoopback=true, that didn't seem to be the case as far as I've tried.

    You need to target your WSL2 IP, e.g. 172.6.2.1 (ip addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}' in WSL)

    A few additional things--as far as I understand, RSA keys are not supported. The way I was able to successfully connect to a local QUIC / WebTransport server was the following:

    1. Generating a pair of ECDSA keys that are valid <14 days via openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -x509 -nodes -days 10 -out ./certificate.pem -keyout ./certificate.key -subj '/CN=Test Certificate' -addext "subjectAltName = DNS:localhost"
    2. Compute base64 hash of public key with openssl x509 -in certificate.pem | openssl dgst -sha256 -binary | openssl enc -base64
    3. Start server and use those keys for tls options.
    4. Connect in the repl without horsing around with Chrome flags:
    
    function base64ToArrayBuffer(base64) {
        var binaryString = atob(base64);
        var bytes = new Uint8Array(binaryString.length);
        for (var i = 0; i < binaryString.length; i++) {
            bytes[i] = binaryString.charCodeAt(i);
        }
        return bytes.buffer;
    }
    const wt = new WebTransport('https://{WSL_IP}:{PORT}/counter', {
            serverCertificateHashes: [
              {
                algorithm: 'sha-256',
                value: base64ToArrayBuffer('{BASE64_HASH}')
              }
            ]
          });
    

    FWIW I'm using https://github.com/adriancable/webtransport-go implementation since it currently supports datagrams. I am still new to the whole ecosystem and it all seems difficult and flaky to set up. There is a current issue logged in the other webtransport-go repo here https://github.com/quic-go/webtransport-go/issues/112 where someone on mac arm64 can't connect in the same way. I was still able to successfully get a connection with the WSL IP and WebTransport options in regular Chrome, no canary or flags necessary.