The caveat of using Chrome to test QUIC implementation

This document gives a detailed information about how to use Chrome to test QUIC implementation. But from my test:

$ /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
  --enable-quic \
  --quic-version=h3-T051 \
  --origin-to-force-quic-on=r2---sn-fxc25nn-nwje.googlevideo.com:443 \
  https://r2---sn-fxc25nn-nwje.googlevideo.com/

Opening in existing browser session.

If Chrome is already running, the above command will open tab in existing browser session, and it will use current existing Chrome process’s QUIC version, e.g, T050. So to test different QUIC versions, you should close current running Chrome processes.

Use Wireshark to decrypt TLS flows

TLS debugging is an awesome introduction of using Wireshark to debug TLS issues (The presentation material can be found here). I just summarise how to decrypt TLS flows here:

(1) Set the filter and capture only TLS flows:

(2) Open chromium and save session secrets in command line:

SSLKEYLOGFILE="$PWD/keys.txt" /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir=/tmp/cr

(3)After saving pcap file, Load key and decrypt TLS flows:

Split TCP packets in pcap file

Sometimes, to simulate one corner case, i.e., the TCP layer splits one application record into multiple packets, I need to use libpcap to tweak pcap files. E.g., for following diagram:

I split frame 8 into 3 parts, one will be appended to frame 7, and the remaining 2 parts will be 2 separated packets.

Generally speaking, only length field in IP header and Sequence number field in TCP header need to be modified. The source code and pcap file can be referenced here.

Create IETF QUIC pcap file

I couldn’t find some off-the-shelf QUIC pcap files which conform to IETF draft versions, so I decided to create them myself. Take Client Initial packet in draft-29 as an example:

(1) Copy following raw packet info into payload.txt:

c5ff00001d088394c8f03e5157080000 449e4a95245bfb66bc5f93032b7ddd89
fe0ff15d9c4f7050fccdb71c1cd80512 d4431643a53aafa1b0b518b44968b18b
......

Use awk command to create string from payload.txt:

$ awk '{for (i = 1; i <= NF; i++) {printf("\"%s\"\n", $i)}}' payload.txt
"c5ff00001d088394c8f03e5157080000"
"449e4a95245bfb66bc5f93032b7ddd89"
"fe0ff15d9c4f7050fccdb71c1cd80512"
"d4431643a53aafa1b0b518b44968b18b"
......

(2) Use a C program to generate payload array:

#include <stdio.h>

char payload[] =
"c5ff00001d088394c8f03e5157080000"
"449e4a95245bfb66bc5f93032b7ddd89"
......
;

int main(void) {
    size_t count = 0;
    printf("const uint8_t payload[] = {\n");
    for (size_t i = 0; i < strlen(payload); i += 2) {
        printf("0x%c%c,", payload[i], payload[i + 1]);
        if (++count == 8) {
            count = 0;
            printf("\n");
        } else {
            printf(" ");
        }
    }
        printf("};");
    return 0;
}

(3) Forge ethernetIP and UDP headers and use libpcap APIs to generate pcap file. The code can be referred here.