SkillAgentSearch skills...

Quic

In-kernel QUIC implementation with Userspace handshake

Install / Use

/learn @lxin/Quic
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

QUIC in Linux Kernel

Introduction

The QUIC protocol, defined in RFC 9000, is a secure, multiplexed transport built on top of UDP. It enables low-latency connection establishment, stream-based communication with flow control, and supports connection migration across network paths, while ensuring confidentiality, integrity, and availability.

This implementation introduces QUIC support in Linux Kernel, offering several key advantages:

  • In-Kernel QUIC Support for Subsystems: Enables kernel subsystems such as SMB and NFS to operate over QUIC with minimal changes. Once the handshake is complete via the net/handshake APIs, data exchange proceeds over standard in-kernel transport interfaces.

  • Standard Socket API Semantics: Implements core socket operations (listen(), accept(), connect(), sendmsg(), recvmsg(), close(), getsockopt(), setsockopt(), getsockname(), and getpeername()), allowing user space to interact with QUIC sockets in a familiar, POSIX-compliant way.

  • ALPN-Based Connection Dispatching: Supports in-kernel ALPN (Application-Layer Protocol Negotiation) routing, allowing demultiplexing of QUIC connections across different user-space processes based on the ALPN identifiers.

  • Performance Enhancements: Handles all control messages in-kernel to reduce syscall overhead, incorporates zero-copy mechanisms such as sendfile() minimize data movement, and is also structured to support future crypto hardware offloads.

Implementation

General Idea

The central design is to implement QUIC within the kernel while delegating the handshake to userspace.

  • What's in Userspace: Only the processing and creation of raw TLS Handshake Messages are handled in userspace, facilitated by a TLS library like GnuTLS. These messages are exchanged between kernel and userspace via sendmsg() and recvmsg(), with cryptographic details conveyed through control messages (cmsg). See: libquic/.

  • What's in Kernel: The entire QUIC protocol, aside from the TLS Handshake Messages processing and creation, is managed within the kernel. Rather than using a Upper Layer Protocol (ULP) layer, this implementation establishes a socket of type IPPROTO_QUIC (similar to IPPROTO_MPTCP), operating over UDP tunnels. See: modules/net/quic/.

  • How Kernel Consumers Use It: Kernel consumers can initiate a handshake request from the kernel to userspace using the existing net/handshake netlink. The userspace component, such as tlshd service in ktls-utils, then manages the processing of the QUIC handshake request.

Infrastructures

  • Handshake Architecture:

    +------+  +------+
    | APP1 |  | APP2 | ...
    +------+  +------+
    +------------------------------------------+
    |     {quic_client/server_handshake()}     |
    +------------------------------------------+       +-------------+
     {send/recvmsg()}      {set/getsockopt()}          |    tlshd    |
     [CMSG handshake_info] [SOCKOPT_CRYPTO_SECRET]     +-------------+
                           [SOCKOPT_TRANSPORT_PARAM_EXT]    |   ^
                  | ^                  | ^                  |   |
    Userspace     | |                  | |                  |   |
    --------------|-|------------------|-|------------------|---|-------
    Kernel        | |                  | |                  |   |
                  v |                  v |                  v   |
    +------------------+-----------------------+       +-------------+
    | protocol, timer, | socket (IPPROTO_QUIC) |<--+   | handshake   |
    |                  +-----------------------+   |   |netlink APIs |
    | common, family,  | outqueue  |  inqueue  |   |   +-------------+
    |                  +-----------------------+   |      |       |
    | stream, connid,  |         frame         |   |   +-----+ +-----+
    |                  +-----------------------+   |   |     | |     |
    | path, pnspace,   |         packet        |   |---| SMB | | NFS |...
    |                  +-----------------------+   |   |     | |     |
    | cong, crypto     |       UDP tunnels     |   |   +--+--+ +--+--+
    +------------------+-----------------------+   +------+-------|
    
  • Application Data Architecture:

    +------+  +------+
    | APP1 |  | APP2 | ...
    +------+  +------+
     {send/recvmsg()}   {set/getsockopt()}              {recvmsg()}
     [CMSG stream_info] [SOCKOPT_KEY_UPDATE]            [EVENT conn update]
                        [SOCKOPT_CONNECTION_MIGRATION]  [EVENT stream update]
                        [SOCKOPT_STREAM_OPEN/RESET/STOP]
                  | ^               | ^                     ^
    Userspace     | |               | |                     |
    --------------|-|---------------|-|---------------------|-----------
    Kernel        | |               | |                     |
                  v |               v |  |------------------+
    +------------------+-----------------------+
    | protocol, timer, | socket (IPPROTO_QUIC) |<--+{kernel_send/recvmsg()}
    |                  +-----------------------+   |{kernel_set/getsockopt()}
    | common, family,  | outqueue  |  inqueue  |   |{kernel_recvmsg()}
    |                  +-----------------------+   |
    | stream, connid,  |         frame         |   |   +-----+ +-----+
    |                  +-----------------------+   |   |     | |     |
    | path, pnspace,   |         packet        |   |---| SMB | | NFS |...
    |                  +-----------------------+   |   |     | |     |
    | cong, crypto     |       UDP tunnels     |   |   +--+--+ +--+--+
    +------------------+-----------------------+   +------+-------|
    

Features

This implementation offers fundamental support for the following RFCs:

  • RFC9000 - QUIC: A UDP-Based Multiplexed and Secure Transport
  • RFC9001 - Using TLS to Secure QUIC
  • RFC9002 - QUIC Loss Detection and Congestion Control
  • RFC9221 - An Unreliable Datagram Extension to QUIC
  • RFC9287 - Greasing the QUIC Bit
  • RFC9368 - Compatible Version Negotiation for QUIC
  • RFC9369 - QUIC Version 2

The socket APIs for QUIC follow the RFC draft:

  • The Sockets API Extensions for In-kernel QUIC Implementations

Next Step

  • Submit QUIC module to upstream kernel.
  • Submit quic_handshake() in libquic to gnutls library.
  • Implement HW crypto offloading infrastructure.

INSTALL

Both QUIC Kernel Module and Libquic will be built and installed simply by the commands below:

Packages Required: (kernel_version >= 6.1)
- make autoconf automake libtool pkg-config
- gnutls-devel kernel-devel (yum)
  gnutls-dev linux-headers-$(uname -r) (apt-get)

# cd /home/lxin (my home directory)
# git clone https://github.com/lxin/quic.git
# cd quic/
# ./autogen.sh
# ./configure --prefix=/usr
# make
# sudo make install
# sudo make check (optional, run selftests)

NOTE: For these who want to integrate QUIC modules into kernel source code (e.g. /home/lxin/net-next/), follow the instruction below to build and install kernel first, then the commands above will skip QUIC modules building and use the one provided by kernel.

# cp -r modules/include modules/net /home/lxin/net-next
# cd /home/lxin/net-next/
# sed -i 's@.*sctp.*@&\nobj-$(CONFIG_IP_QUIC)\t\t+= quic/@' net/Makefile
# sed -i 's@.*sctp.*@&\nsource "net/quic/Kconfig"@' net/Kconfig

Then build kernel with:

CONFIG_IP_QUIC=m
CONFIG_IP_QUIC_TEST=m

Also libquic is not necessary if you're able to use raw socket APIs and gnutls APIs to complete the QUIC handshake, see Raw Socket APIs with more Control.

USE CASES

Kernel Consumers with ktls-utils:

Packages Required:
- keyutils
- glib2-devel libnl3-devel keyutils-libs-devel (yum)
  libglib2.0-dev libnl-genl-3-dev libkeyutils-dev (apt-get)

# cd /home/lxin
# git clone https://github.com/oracle/ktls-utils
# cd ktls-utils/
# ./autogen.sh
# ./configure --with-systemd --sysconfdir=/etc
# make
# sudo make install

# sudo vim /etc/tlshd/config
  [debug]
  loglevel=0
  tls=0
  nl=0

  [authenticate]
  keyrings=quic

  [authenticate.client]
  x509.truststore= /home/lxin/quic/tests/keys/ca-cert.pem
  x509.certificate=/home/lxin/quic/tests/keys/client-cert.pem
  x509.private_key=/home/lxin/quic/tests/keys/client-key.pem

  [authenticate.server]
  x509.truststore= /home/lxin/quic/tests/keys/ca-cert.pem
  x509.certificate=/home/lxin/quic/tests/keys/server-cert.pem
  x509.private_key=/home/lxin/quic/tests/keys/server-key.pem

# sudo systemctl enable --now tlshd

# cd /home/lxin/quic
# sudo make check tests=tlshd (optional, run some tests for tlshd)

After tlshd service is started, Kernel Consumers can use these user APIs from kernel space, see Use in Kernel Space.

HTTP/3 Client with Curl:

# cd /home/lxin
# git clone --recurse-submodules https://github.com/ngtcp2/nghttp3.git
# cd nghttp3
# autoreconf -i
# ./configure --prefix=/usr/
# make
# sudo make install

# cd /home/lxin/quic
# sudo make check tests=http3 (optional, run some tests for http3)

Moritz Buhl has made curl http3 work over linuxquic:

# git clone https://github.com/moritzbuhl/curl.git -b linux_curl
# cd curl
# autoreconf -i
# ./configure --prefix=/usr/ --with-gnutls --with-linux-quic --with-nghttp3
# make -j$(nproc)
# sudo make install

The test can be done with curl:

# curl --http3-only --ipv4 https://cloudflare-quic.com/
# curl --http3-only --ipv4 https://facebook.com/
# c

Related Skills

View on GitHub
GitHub Stars259
CategoryDevelopment
Updated10h ago
Forks23

Languages

C

Security Score

85/100

Audited on Mar 22, 2026

No findings