The pitfall of using tshark to analyse QUIC protocol

Check the wireshark’s QUIC related code, we will find it heavily depends on 2 macros:

#ifdef HAVE_LIBGCRYPT_AEAD
......
#endif

#ifdef HAVE_LIBGCRYPT_CHACHA20
......
#endif

And these 2 macros rely on the version of libgcrypt (refer here):

/*
 * Define HAVE_LIBGCRYPT_AEAD here, because it's used in several source
 * files.
 */
#if GCRYPT_VERSION_NUMBER >= 0x010600 /* 1.6.0 */
/* Whether to provide support for authentication in addition to decryption. */
#define HAVE_LIBGCRYPT_AEAD
#endif

/*
 * Define some other "do we have?" items as well.
 */
#if GCRYPT_VERSION_NUMBER >= 0x010700 /* 1.7.0 */
/* Whether ChaCh20 PNE can be supported. */
#define HAVE_LIBGCRYPT_CHACHA20
/* Whether AEAD_CHACHA20_POLY1305 can be supported. */
#define HAVE_LIBGCRYPT_CHACHA20_POLY1305
#endif

On CentOS 7, the libgcrypt version is 1.5.3, so the above 2 macros will not be defined, and some functions are not available. While on CentOS 8, the libgcrypt version is 1.8.5, so the functions are fully supported. I met an issue, i.e., for the same pcap file, tshark (I built myself) on CentOS 7 assumes there is an error in decrypting QUIC flow:

$ /home/nanxiao/wireshark/build/run/tshark -nr 435.pcap -Y '(quic.decryption_failed)'
    1   0.000000 172.27.232.168 → 216.183.220.159 GTP <QUIC> 1310 Initial, DCID=68a3ee8706f87817

while tshark on CentOS 8 works OK:

$ /home/nanxiao/wireshark/build/run/tshark -nr 435.pcap -Y '(quic.decryption_failed)'
$

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.

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.