Skip to content
Xin Long edited this page Mar 7, 2024 · 7 revisions

Introduction

This is an implementation of the QUIC protocol as defined in RFC9000. QUIC is an UDP-Based Multiplexed and Secure Transport protocol, and it provides applications with flow-controlled streams for structured communication, low-latency connection establishment, and network path migration. QUIC includes security measures that ensure confidentiality, integrity, and availability in a range of deployment circumstances.

This implementation of QUIC in the kernel space enables users to utilize the QUIC protocol through socket APIs in user space. Additionally, kernel subsystems like SMB and NFS can seamlessly operate over the QUIC protocol after handshake using net/handshake APIs.

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
  • Handshake APIs for tlshd Use - NFS/SMB over QUIC

Implementation

The central idea is to implement QUIC within the kernel, incorporating an userspace handshake approach.

The processing and creation of only raw TLS Handshake Messages, facilitated by tls library like gnutls, take place in userspace. These messages are exchanged through sendmsg/recvmsg() mechanisms, with cryptographic details handled in the control message (cmsg).

The entirety of QUIC protocol, excluding TLS Handshake Messages processing and creation, resides in the kernel. Instead of utilizing a User Level Protocol (ULP) layer, it establishes a socket of IPPROTO_QUIC type (similar to IPPROTO_MPTCP) operating over a UDP tunnel.

Kernel consumers can initiate a handshake request from the kernel to userspace via handshake netlink. The userspace component, tlshd from ktls-utils, manages the QUIC handshake request processing.

  • Handshake:

    +-----------------------------------------------------------------------+
    |                           GNUTLS USER LIBRARY                         |
    +---------+-+-----------------+-+----------------------+-+--------------+
       TLS HANDSHAKE MSGS   TLS TRANSPORT PARAMS EXT  TLS SECRETS
       [send/recvmsg()      [set/getsockopt() with    [set/getsockopt() with
        with cmsg quic_      optname QUIC_SOCKOPT_     optname QUIC_SOCKOPT_
        handshake_info]      TRANSPORT_PARAM_EXT]      CRYPTO_SECRET]
              | ^                 | ^                      | ^
    Userspace | |                 | |                      | |
    ----------+-+-----------------+-+----------------------+-+---------------
    Kernel    | |                 | |                      | |
              v |                 v |                      v |
        QUIC CRYPTO FRAMES  QUIC TRANSPORT PARAMS     QUIC KEYS
        [create/parse long  [en/decode transport      [derive key/iv/hp_key
         packet and crypto   params from tls           for handshake/app
         frame]              transport params ext]     data send/recv]
    +-----------------------------------------------------------------------+
    |    QUIC CONNECTION  |    PACKET      |      FRAME     |      CRYPTO   |
    +-----------------------------------------------------------------------+
    |                           UDP TUNNEL KERNEL APIs                      |
    +-----------------------------------------------------------------------+
    
  • Post Handshake:

       APPLICATION DATA                QUIC PRIMITIVES
       [sendmsg/recvmsg()              [setsockopt/getsockopt()
        with cmsg quic_                 with optname like QUIC_SOCKOPT
        stream_info]                    _KEY_UPDATE and _STREAM_RESET ...]
              | ^                            | ^
    Userspace | |                            | |
    ----------+-+----------------------------+-+------------------------------
    Kernel    | |                            | |
              v |                            v |
        QUIC STREAM FRAMES              QUIC CONTROL FRAMES
        [quic short packet and          [quic short packet and
         stream frame creating           corresponding ctrl frames
         and processing]                 creating and processing]
    +------------------------------------------------------------------------+
    | QUIC CONNECTION | STREAM | PACKET | FRAME | CRYPTO | FLOW | CONGESTION |
    +------------------------------------------------------------------------+
    |                           UDP TUNNEL KERNEL APIs                       |
    +------------------------------------------------------------------------+
    

Usage

This implementation supports a mapping of QUIC into sockets APIs. Similar to TCP and SCTP, a typical Server and Client use the following system call sequence to communicate:

   Client                    Server
------------------------------------------------------------------
sockfd = socket(IPPROTO_QUIC)      listenfd = socket(IPPROTO_QUIC)
bind(sockfd)                       bind(listenfd)
                                   listen(listenfd)
connect(sockfd)
quic_client_handshake()
                                   sockfd = accecpt(listenfd)
                                   quic_server_handshake()

sendmsg(sockfd)                    recvmsg(sockfd)
close(sockfd)                      close(sockfd)
                                   close(listenfd)

Please note that quic_client_handshake() and quic_server_handshake() functions are sourced from libquic in the github lxin/quic repository. These functions are responsible for receiving and processing TLS handshake messages until the completion of the handshake process.

For utilization by kernel consumers, it is essential to have the tlshd service (from ktls-utils) installed and running in userspace. This service receives and manages kernel handshake requests for kernel sockets. In kernel space, the APIs closely resemble those used in userspace:

   Client                    Server
------------------------------------------------------------------------
__sock_create(IPPROTO_QUIC, &sock)  __sock_create(IPPROTO_QUIC, &sock)
kernel_bind(sock)                   kernel_bind(sock)
                                    kernel_listen(sock)
kernel_connect(sock)
tls_client_hello_x509(args:{sock})
                                    kernel_accept(sock, &newsock)
                                    tls_server_hello_x509(args:{newsock})

kernel_sendmsg(sock)                kernel_recvmsg(newsock)
sock_release(sock)                  sock_release(newsock)
                                    sock_release(sock)

Please be aware that tls_client_hello_x509() and tls_server_hello_x509() are APIs from net/handshake/. They are employed to dispatch the handshake request to the userspace tlshd service and subsequently block until the handshake process is completed.

See man for more details.

Contribution

fork https://github.com/lxin/quic.git

make changes

submit a Pull Request

Clone this wiki locally