1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
|
ngtcp2
======
"Call it TCP/2. One More Time."
ngtcp2 project is an effort to implement `RFC9000
<https://datatracker.ietf.org/doc/html/rfc9000>`_ QUIC protocol.
Documentation
-------------
`Online documentation <https://nghttp2.org/ngtcp2/>`_ is available.
Public test server
------------------
The following endpoints are available to try out ngtcp2
implementation:
- https://nghttp2.org:4433
- https://nghttp2.org:4434 (requires address validation token)
- https://nghttp2.org (powered by `nghttpx
<https://nghttp2.org/documentation/nghttpx.1.html>`_)
This endpoints sends Alt-Svc header field to clients if it is
accessed via HTTP/1.1 or HTTP/2 to tell them that HTTP/3 is
available at UDP 443.
Requirements
------------
The libngtcp2 C library itself does not depend on any external
libraries. The example client, and server are written in C++20, and
should compile with the modern C++ compilers (e.g., clang >= 11.0, or
gcc >= 11.0).
The following packages are required to configure the build system:
- pkg-config >= 0.20
- autoconf
- automake
- autotools-dev
- libtool
libngtcp2 uses cunit for its unit test frame work:
- cunit >= 2.1
To build sources under the examples directory, libev and nghttp3 are
required:
- libev
- `nghttp3 <https://github.com/ngtcp2/nghttp3>`_ for HTTP/3
ngtcp2 crypto helper library, and client and server under examples
directory require at least one of the following TLS backends:
- `OpenSSL with QUIC support
<https://github.com/quictls/openssl/tree/OpenSSL_1_1_1s+quic>`_
- GnuTLS >= 3.7.2
- BoringSSL (commit 31bad2514d21f6207f3925ba56754611c462a873)
- Picotls (commit 5e01b2b94dc77c500ed4fc0eaa77bd0cbe8e9274)
- wolfSSL >= 5.5.0
Build from git
--------------
.. code-block:: text
$ git clone --depth 1 -b OpenSSL_1_1_1s+quic https://github.com/quictls/openssl
$ cd openssl
$ # For Linux
$ ./config enable-tls1_3 --prefix=$PWD/build
$ make -j$(nproc)
$ make install_sw
$ cd ..
$ git clone https://github.com/ngtcp2/nghttp3
$ cd nghttp3
$ autoreconf -i
$ ./configure --prefix=$PWD/build --enable-lib-only
$ make -j$(nproc) check
$ make install
$ cd ..
$ git clone https://github.com/ngtcp2/ngtcp2
$ cd ngtcp2
$ autoreconf -i
$ # For Mac users who have installed libev with MacPorts, append
$ # ',-L/opt/local/lib' to LDFLAGS, and also pass
$ # CPPFLAGS="-I/opt/local/include" to ./configure.
$ # For OpenSSL >= v3.0.0, replace "openssl/build/lib" with
$ # "openssl/build/lib64".
$ ./configure PKG_CONFIG_PATH=$PWD/../openssl/build/lib/pkgconfig:$PWD/../nghttp3/build/lib/pkgconfig LDFLAGS="-Wl,-rpath,$PWD/../openssl/build/lib"
$ make -j$(nproc) check
Client/Server
-------------
After successful build, the client and server executable should be
found under examples directory. They talk HTTP/3.
Client
~~~~~~
.. code-block:: text
$ examples/client [OPTIONS] <HOST> <PORT> [<URI>...]
The notable options are:
- ``-d``, ``--data=<PATH>``: Read data from <PATH> and send it to a
peer.
Server
~~~~~~
.. code-block:: text
$ examples/server [OPTIONS] <ADDR> <PORT> <PRIVATE_KEY_FILE> <CERTIFICATE_FILE>
The notable options are:
- ``-V``, ``--validate-addr``: Enforce stateless address validation.
H09client/H09server
-------------------
There are h09client and h09server which speak HTTP/0.9. They are
written just for `quic-interop-runner
<https://github.com/marten-seemann/quic-interop-runner>`_. They share
the basic functionalities with HTTP/3 client and server but have less
functions (e.g., h09client does not have a capability to send request
body, and h09server does not understand numeric request path, like
/1000).
Resumption and 0-RTT
--------------------
In order to resume a session, a session ticket, and a transport
parameters must be fetched from server. First, run examples/client
with --session-file, and --tp-file options which specify a path to
session ticket, and transport parameter files respectively to save
them locally.
Once these files are available, run examples/client with the same
arguments again. You will see that session is resumed in your log if
resumption succeeds. Resuming session makes server's first Handshake
packet pretty small because it does not send its certificates.
To send 0-RTT data, after making sure that resumption works, use -d
option to specify a file which contains data to send.
Token (Not something included in Retry packet)
----------------------------------------------
QUIC server might send a token to client after connection has been
established. Client can send this token in subsequent connection to
the server. Server verifies the token and if it succeeds, the address
validation completes and lifts some restrictions on server which might
speed up transfer. In order to save and/or load a token,
use --token-file option of examples/client. The given file is
overwritten if it already exists when storing a token.
Crypto helper library
---------------------
In order to make TLS stack integration less painful, we provide a
crypto helper library which offers the basic crypto operations.
The header file exists under crypto/includes/ngtcp2 directory.
Each library file is built for a particular TLS backend. The
available crypto helper libraries are:
- libngtcp2_crypto_openssl: Use OpenSSL as TLS backend
- libngtcp2_crypto_gnutls: Use GnuTLS as TLS backend
- libngtcp2_crypto_boringssl: Use BoringSSL as TLS backend
- libngtcp2_crypto_picotls: Use Picotls as TLS backend
- libngtcp2_crypto_wolfssl: Use wolfSSL as TLS backend
Because BoringSSL and Picotls are an unversioned product, we only
tested their particular revision. See Requirements section above.
We use Picotls with OpenSSL as crypto backend. It does not work with
OpenSSL >= 3.0.0.
The examples directory contains client and server that are linked to
those crypto helper libraries and TLS backends. They are only built
if their corresponding crypto helper library is built:
- client: OpenSSL client
- server: OpenSSL server
- gtlsclient: GnuTLS client
- gtlsserver: GnuTLS server
- bsslclient: BoringSSL client
- bsslserver: BoringSSL server
- ptlsclient: Picotls client
- ptlsserver: Picotls server
- wsslclient: wolfSSL client
- wsslserver: wolfSSL server
QUIC protocol extensions
-------------------------
The library implements the following QUIC protocol extensions:
- `An Unreliable Datagram Extension to QUIC
<https://datatracker.ietf.org/doc/html/rfc9221>`_
- `Greasing the QUIC Bit
<https://datatracker.ietf.org/doc/html/rfc9287>`_
- `Compatible Version Negotiation for QUIC
<https://datatracker.ietf.org/doc/html/draft-ietf-quic-version-negotiation>`_
- `QUIC Version 2
<https://datatracker.ietf.org/doc/html/draft-ietf-quic-v2>`_
Configuring Wireshark for QUIC
------------------------------
`Wireshark <https://www.wireshark.org/download.html>`_ can be configured to
analyze QUIC traffic using the following steps:
1. Set *SSLKEYLOGFILE* environment variable:
.. code-block:: text
$ export SSLKEYLOGFILE=quic_keylog_file
2. Set the port that QUIC uses
Go to *Preferences->Protocols->QUIC* and set the port the program
listens to. In the case of the example application this would be
the port specified on the command line.
3. Set Pre-Master-Secret logfile
Go to *Preferences->Protocols->TLS* and set the *Pre-Master-Secret
log file* to the same value that was specified for *SSLKEYLOGFILE*.
4. Choose the correct network interface for capturing
Make sure you choose the correct network interface for
capturing. For example, if using localhost choose the *loopback*
network interface on macos.
5. Create a filter
Create A filter for the udp.port and set the port to the port the
application is listening to. For example:
.. code-block:: text
udp.port == 7777
License
-------
The MIT License
Copyright (c) 2016 ngtcp2 contributors
|