Neqo, the Mozilla Firefox implementation of QUIC in Rust
Rust
2,244
3,660 commits
updated Oct 18, 2026

Neqo is the QUIC implementation used by Mozilla in Firefox and other products. It is written in Rust and provides a library for QUIC transport, HTTP/3, and QPACK. The TLS security backend is the Mozilla NSS library, which is also used by Firefox.
Neqo is designed to be used in Firefox, but it can also be used
standalone. We include command line tools for testing and debugging, such as
neqo-client and neqo-server, which can be used to test HTTP/3 servers
and clients.
Note: The neqo server functionality is experimental, since it is not in production use at Mozilla, and it is not as mature as the client functionality. It is intended to be standards-compliant when interoperating with a compliant client, but it may not implement all optional protocol features, and it may not handle all edge cases. It is also not optimized for performance or resource usage, and while it implements many of the necessary features for a server, it does not include configuration of a number of options that are suited to a live deployment. Do not use the neqo server code in production.
To build Neqo:
cargo build
This will use a system-installed NSS library if it is new enough. (See "Build with separate NSS/NSPR" below if NSS is not installed or it is deemed too old.)
To run test HTTP/3 programs (neqo-client and neqo-server):
./target/debug/neqo-server '[::]:12345'
./target/debug/neqo-client 'https://[::]:12345/'
Clone NSS and NSPR into the same directory and export an environment variable called NSS_DIR pointing to NSS.
For example if you have a folder $HOME/neqo-dependencies and cloned NSS and NSPR into it you'd set NSS_DIR=$HOME/neqo-dependencies/nss.
If you did not already compile NSS separately, you need to have Mercurial (hg) installed. NSS builds require GYP and Ninja to be installed.
Run cargo build in your neqo checkout. The prior steps enable cargo build to use the existing NSS build or build it from the existing checkout if it hasn't been built yet.
Now that NSS has been built you need to set another environment variable to be able to actually do anything that depends on NSS.
For Linux:
export LD_LIBRARY_PATH="$(find $NSS_DIR/.. -name libssl3.so -print | head -1 | xargs dirname | xargs realpath)"
For macOS:
export DYLD_LIBRARY_PATH="$(find $NSS_DIR/.. -name libssl3.dylib -print | head -1 | xargs dirname | xargs realpath)"
(optional) After having an NSS build you can set the NSS_PREBUILT=1 environment variable to skip building NSS again on future cargo build invocations.
Enable generation of QLOG logs with:
target/debug/neqo-server '[::]:12345' --qlog-dir .
target/debug/neqo-client 'https://[::]:12345/' --qlog-dir .
You can of course specify a different directory for the QLOG files. You can upload QLOG files to qvis to visualize the flows.
To export QLOG files for Neqo Simulator runs, set the
environment variable QLOGDIR. For example:
QLOGDIR=/tmp/qlog cargo bench --bench min_bandwidth --features bench
SSLKEYLOGFILE to decrypt Wireshark logsYou can export TLS keys by setting the SSLKEYLOGFILE environment variable
to a filename to instruct NSS to dump keys in the
standard format
to enable decryption by Wireshark and other tools.
As documented in the env_logger documentation,
the RUST_LOG environment variable can be used to selectively enable log messages
from Rust code. This works for Neqo's command line tools, as well as for when Neqo is
incorporated into Gecko, although Gecko needs to be built in debug mode.
Some examples:
RUST_LOG=neqo_transport::dump ./mach run
lists sent and received QUIC packets and their frames' contents only.
RUST_LOG=neqo_transport=debug,neqo_http3=trace,info ./mach run
sets a debug log level for transport, trace level for http3, and info log
level for all other Rust crates, both Neqo and others used by Gecko.
RUST_LOG=neqo=trace,error ./mach run
sets trace level for all modules starting with neqo, and sets error as minimum log level for other unrelated Rust log messages.
In a checked-out copy of Gecko source, set [patches.*] values for the
Neqo crates to local versions in the root Cargo.toml. For example, if Neqo
was checked out to /home/alice/git/neqo, add the following lines to the root
Cargo.toml.
[patch."https://github.com/mozilla/neqo"]
neqo-bin = { path = "/home/alice/git/neqo/neqo-bin" }
neqo-common = { path = "/home/alice/git/neqo/neqo-common" }
neqo-http3 = { path = "/home/alice/git/neqo/neqo-http3" }
neqo-qpack = { path = "/home/alice/git/neqo/neqo-qpack" }
neqo-transport = { path = "/home/alice/git/neqo/neqo-transport" }
neqo-udp = { path = "/home/alice/git/neqo/neqo-udp" }
Then run the following:
./mach vendor rust
Compile Gecko as usual with
./mach build
Note: Using newer Neqo code with Gecko may also require changes (likely to neqo_glue) if
something has changed.
neqo-server via cargo run --bin neqo-server -- 'localhost:12345'.about:config preferences:
network.http.http3.alt-svc-mapping-for-testing to localhost;h3=":12345"network.http.http3.disable_when_third_party_roots_found to falseabout:logging or profiling via https://profiler.firefox.com/.Neqo follows semantic versioning. While the version is
still below 1.0, a minor bump (0.X.0) signals a breaking change and a
patch bump (0.X.Y) is reserved for backwards-compatible fixes.
v0.26.0 → v0.27.0)Cargo.toml. Commit the
resulting Cargo.toml and Cargo.lock change and open a pull request
against main.vX.Y.Z git tag pointing at the merged commit on main and
push it.Update neqo to vX.Y.Z (see bug 2030978
for an example).firefox checkout, bump
the neqo-* dependency versions in
netwerk/socket/neqo_glue/Cargo.toml
and
netwerk/test/http3server/Cargo.toml
(see Phabricator D293565
for an example)../mach -v vendor rust --force --ignore-modified../mach cargo vet and obtain the necessary supply-chain audits.v0.26.0 → v0.26.1)Patch releases ship from a long-lived release branch so that main can keep
moving with breaking changes.
vX.Y branch on GitHub off the
vX.Y.0 tag (e.g. the
v0.26 branch was cut from
v0.26.0). Backport the fixes onto that branch.vX.Y branch, open a pull request that bumps the version to
vX.Y.Z in Cargo.toml and targets vX.Y (not main).vX.Y branch instead of main. See
bug 2034178 and
Phabricator D296371 for
an example.(top 24 of 84)
310 followers · starred Nov 2022
1,327 followers · starred Oct 2019
1,045 followers · starred Sep 2019
378 followers · starred Apr 2019
Neqo, the Mozilla Firefox implementation of QUIC in Rust
Rust
2,244
3,660 commits
updated Oct 18, 2026

Neqo is the QUIC implementation used by Mozilla in Firefox and other products. It is written in Rust and provides a library for QUIC transport, HTTP/3, and QPACK. The TLS security backend is the Mozilla NSS library, which is also used by Firefox.
Neqo is designed to be used in Firefox, but it can also be used
standalone. We include command line tools for testing and debugging, such as
neqo-client and neqo-server, which can be used to test HTTP/3 servers
and clients.
Note: The neqo server functionality is experimental, since it is not in production use at Mozilla, and it is not as mature as the client functionality. It is intended to be standards-compliant when interoperating with a compliant client, but it may not implement all optional protocol features, and it may not handle all edge cases. It is also not optimized for performance or resource usage, and while it implements many of the necessary features for a server, it does not include configuration of a number of options that are suited to a live deployment. Do not use the neqo server code in production.
To build Neqo:
cargo build
This will use a system-installed NSS library if it is new enough. (See "Build with separate NSS/NSPR" below if NSS is not installed or it is deemed too old.)
To run test HTTP/3 programs (neqo-client and neqo-server):
./target/debug/neqo-server '[::]:12345'
./target/debug/neqo-client 'https://[::]:12345/'
Clone NSS and NSPR into the same directory and export an environment variable called NSS_DIR pointing to NSS.
For example if you have a folder $HOME/neqo-dependencies and cloned NSS and NSPR into it you'd set NSS_DIR=$HOME/neqo-dependencies/nss.
If you did not already compile NSS separately, you need to have Mercurial (hg) installed. NSS builds require GYP and Ninja to be installed.
Run cargo build in your neqo checkout. The prior steps enable cargo build to use the existing NSS build or build it from the existing checkout if it hasn't been built yet.
Now that NSS has been built you need to set another environment variable to be able to actually do anything that depends on NSS.
For Linux:
export LD_LIBRARY_PATH="$(find $NSS_DIR/.. -name libssl3.so -print | head -1 | xargs dirname | xargs realpath)"
For macOS:
export DYLD_LIBRARY_PATH="$(find $NSS_DIR/.. -name libssl3.dylib -print | head -1 | xargs dirname | xargs realpath)"
(optional) After having an NSS build you can set the NSS_PREBUILT=1 environment variable to skip building NSS again on future cargo build invocations.
Enable generation of QLOG logs with:
target/debug/neqo-server '[::]:12345' --qlog-dir .
target/debug/neqo-client 'https://[::]:12345/' --qlog-dir .
You can of course specify a different directory for the QLOG files. You can upload QLOG files to qvis to visualize the flows.
To export QLOG files for Neqo Simulator runs, set the
environment variable QLOGDIR. For example:
QLOGDIR=/tmp/qlog cargo bench --bench min_bandwidth --features bench
SSLKEYLOGFILE to decrypt Wireshark logsYou can export TLS keys by setting the SSLKEYLOGFILE environment variable
to a filename to instruct NSS to dump keys in the
standard format
to enable decryption by Wireshark and other tools.
As documented in the env_logger documentation,
the RUST_LOG environment variable can be used to selectively enable log messages
from Rust code. This works for Neqo's command line tools, as well as for when Neqo is
incorporated into Gecko, although Gecko needs to be built in debug mode.
Some examples:
RUST_LOG=neqo_transport::dump ./mach run
lists sent and received QUIC packets and their frames' contents only.
RUST_LOG=neqo_transport=debug,neqo_http3=trace,info ./mach run
sets a debug log level for transport, trace level for http3, and info log
level for all other Rust crates, both Neqo and others used by Gecko.
RUST_LOG=neqo=trace,error ./mach run
sets trace level for all modules starting with neqo, and sets error as minimum log level for other unrelated Rust log messages.
In a checked-out copy of Gecko source, set [patches.*] values for the
Neqo crates to local versions in the root Cargo.toml. For example, if Neqo
was checked out to /home/alice/git/neqo, add the following lines to the root
Cargo.toml.
[patch."https://github.com/mozilla/neqo"]
neqo-bin = { path = "/home/alice/git/neqo/neqo-bin" }
neqo-common = { path = "/home/alice/git/neqo/neqo-common" }
neqo-http3 = { path = "/home/alice/git/neqo/neqo-http3" }
neqo-qpack = { path = "/home/alice/git/neqo/neqo-qpack" }
neqo-transport = { path = "/home/alice/git/neqo/neqo-transport" }
neqo-udp = { path = "/home/alice/git/neqo/neqo-udp" }
Then run the following:
./mach vendor rust
Compile Gecko as usual with
./mach build
Note: Using newer Neqo code with Gecko may also require changes (likely to neqo_glue) if
something has changed.
neqo-server via cargo run --bin neqo-server -- 'localhost:12345'.about:config preferences:
network.http.http3.alt-svc-mapping-for-testing to localhost;h3=":12345"network.http.http3.disable_when_third_party_roots_found to falseabout:logging or profiling via https://profiler.firefox.com/.Neqo follows semantic versioning. While the version is
still below 1.0, a minor bump (0.X.0) signals a breaking change and a
patch bump (0.X.Y) is reserved for backwards-compatible fixes.
v0.26.0 → v0.27.0)Cargo.toml. Commit the
resulting Cargo.toml and Cargo.lock change and open a pull request
against main.vX.Y.Z git tag pointing at the merged commit on main and
push it.Update neqo to vX.Y.Z (see bug 2030978
for an example).firefox checkout, bump
the neqo-* dependency versions in
netwerk/socket/neqo_glue/Cargo.toml
and
netwerk/test/http3server/Cargo.toml
(see Phabricator D293565
for an example)../mach -v vendor rust --force --ignore-modified../mach cargo vet and obtain the necessary supply-chain audits.v0.26.0 → v0.26.1)Patch releases ship from a long-lived release branch so that main can keep
moving with breaking changes.
vX.Y branch on GitHub off the
vX.Y.0 tag (e.g. the
v0.26 branch was cut from
v0.26.0). Backport the fixes onto that branch.vX.Y branch, open a pull request that bumps the version to
vX.Y.Z in Cargo.toml and targets vX.Y (not main).vX.Y branch instead of main. See
bug 2034178 and
Phabricator D296371 for
an example.(top 24 of 84)
310 followers · starred Nov 2022
1,327 followers · starred Oct 2019
1,045 followers · starred Sep 2019
378 followers · starred Apr 2019