Low-level access to the QUIC Initial Packet for mimicry purposes, hard fork of quic-go. https://quic.tlsfingerprint.io
Find a file
2025-04-01 11:48:45 -06:00
.clusterfuzzlite sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
.github bump go.mod version to Go 1.23, run 1.23 and 1.24 on CI (#4880) 2025-02-13 12:49:54 +01:00
docs Add files via upload 2023-08-15 22:56:50 -06:00
example sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
fuzzing sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
http3 sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
integrationtests sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
internal sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
logging sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
metrics sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
qlog sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
quicvarint quicvarint: migrate tests away from Ginkgo (#4662) 2024-09-11 22:22:17 -07:00
testutils sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
.gitignore implement qlog JSONSEQ format, bump qlog version (#4609) 2024-08-03 20:19:51 -07:00
.golangci.yml ci: disable SA1029 staticcheck (context key check) in test files (#4802) 2024-12-27 17:31:21 +08:00
buffer_pool.go break: update repo url [ci skip] 2023-08-03 18:58:52 -06:00
buffer_pool_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
Changelog.md break: update repo url [ci skip] 2023-08-03 18:58:52 -06:00
client.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
client_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
closed_conn.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
closed_conn_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
codecov.yml logging: use code generation to generate the multiplexed tracers (#4677) 2024-11-28 23:57:11 +08:00
config.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
config_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
conn_id_generator.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
conn_id_generator_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
conn_id_manager.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
conn_id_manager_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
connection.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
connection_logging.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
connection_logging_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
connection_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
connection_timer.go break: update repo url [ci skip] 2023-08-03 18:58:52 -06:00
connection_timer_test.go refactor connection timer logic (#4927) 2025-01-28 05:08:05 +01:00
crypto_stream.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
crypto_stream_manager.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
crypto_stream_manager_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
crypto_stream_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
datagram_queue.go sync: quic-go 0.42.0 2024-04-23 22:34:55 -06:00
datagram_queue_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
errors.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
errors_test.go fix errors.Is for StreamError and DatagramTooLargeError (#4825) 2024-12-29 17:56:38 +08:00
frame_sorter.go break: update repo url [ci skip] 2023-08-03 18:58:52 -06:00
frame_sorter_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
framer.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
framer_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
go.mod sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
go.sum sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
interface.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
LICENSE add Google to license file 2016-12-14 11:54:01 +01:00
mock_ack_frame_source_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_conn_runner_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_frame_source_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_mtu_discoverer_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_packer_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_packet_handler_manager_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_packet_handler_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_packetconn_test.go update GoMock to v0.5.0 (#4776) 2024-12-21 10:56:18 +08:00
mock_quic_conn_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_raw_conn_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_receive_stream_internal_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_sealing_manager_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_send_conn_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_send_stream_internal_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_sender_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_stream_control_frame_getter_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_stream_internal_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_stream_manager_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_stream_sender_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mock_unpacker_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mockgen.go migrate platform-dependent UDP socket test code away from Ginkgo (#4797) 2024-12-26 15:02:18 +08:00
mtu_discoverer.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
mtu_discoverer_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
oss-fuzz.sh sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
packet_handler_map.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
packet_handler_map_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
packet_packer.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
packet_packer_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
packet_unpacker.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
packet_unpacker_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
path_manager.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
path_manager_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
quic_suite_linux_test.go disable GSO and ECN on kernels older than version 5 (#4456) 2024-04-24 07:10:22 -07:00
quic_suite_test.go remove validation enforcing one Transport per net.PacketConn (#4851) 2025-01-10 09:32:52 +08:00
README.md Support non-zero lowest frame offset 2024-11-22 15:12:57 -07:00
receive_stream.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
receive_stream_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
retransmission_queue.go sync: quic-go 0.42.0 2024-04-23 22:34:55 -06:00
retransmission_queue_test.go break: update repo url [ci skip] 2023-08-03 18:58:52 -06:00
SECURITY.md deps: upgrade dependencies after Go 1.21 releases (#12) 2023-08-08 23:15:52 -06:00
send_conn.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
send_conn_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
send_queue.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
send_queue_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
send_stream.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
send_stream_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
server.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
server_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
stateless_reset.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
stateless_reset_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
stream.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
stream_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
streams_map.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
streams_map_incoming.go break: update repo url [ci skip] 2023-08-03 18:58:52 -06:00
streams_map_incoming_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
streams_map_outgoing.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
streams_map_outgoing_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
streams_map_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
sys_conn.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
sys_conn_buffers.go break: update repo url [ci skip] 2023-08-03 18:58:52 -06:00
sys_conn_buffers_write.go break: update repo url [ci skip] 2023-08-03 18:58:52 -06:00
sys_conn_df.go check for WSAEMSGSIZE errors when receiving UDP packets on Windows (#3982) 2023-07-20 20:31:57 -07:00
sys_conn_df_darwin.go enable DPLPMTUD on macOS dual-stack sockets (#4723) 2024-12-01 14:50:49 +08:00
sys_conn_df_darwin_test.go enable DPLPMTUD on macOS dual-stack sockets (#4723) 2024-12-01 14:50:49 +08:00
sys_conn_df_linux.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
sys_conn_df_windows.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
sys_conn_helper_darwin.go disable GSO and ECN on kernels older than version 5 (#4456) 2024-04-24 07:10:22 -07:00
sys_conn_helper_freebsd.go disable GSO and ECN on kernels older than version 5 (#4456) 2024-04-24 07:10:22 -07:00
sys_conn_helper_linux.go disable GSO and ECN on kernels older than version 5 (#4456) 2024-04-24 07:10:22 -07:00
sys_conn_helper_linux_test.go migrate platform-dependent UDP socket test code away from Ginkgo (#4797) 2024-12-26 15:02:18 +08:00
sys_conn_helper_nonlinux.go sync: quic-go 0.42.0 2024-04-23 22:34:55 -06:00
sys_conn_helper_nonlinux_test.go sync: quic-go 0.42.0 2024-04-23 22:34:55 -06:00
sys_conn_no_oob.go use a netip.Addr instead of a net.IP in the packetInfo struct 2023-06-03 10:44:15 +03:00
sys_conn_oob.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
sys_conn_oob_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
sys_conn_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
sys_conn_windows.go use a netip.Addr instead of a net.IP in the packetInfo struct 2023-06-03 10:44:15 +03:00
sys_conn_windows_test.go migrate platform-dependent UDP socket test code away from Ginkgo (#4797) 2024-12-26 15:02:18 +08:00
token_store.go sync: quic-go 0.42.0 2024-04-23 22:34:55 -06:00
token_store_test.go migrate the TokenStore tests away from Ginkgo (#4795) 2024-12-24 18:25:15 +08:00
tools.go switch from unmaintained golang/mock to go.uber.org/mock (#4050) 2023-08-28 02:23:55 -07:00
transport.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
transport_test.go sync: merge changes from quic-go v0.50.0 2025-04-01 11:48:45 -06:00
u_client.go fix: build error after sync 2024-04-23 23:20:14 -06:00
u_conn_id_manager.go new: uquic 2023-08-02 15:38:16 -06:00
u_connection.go fix: build error after sync 2024-04-23 23:20:14 -06:00
u_initial_packet_spec.go new: support variable length quic frame padding (#10) 2023-08-05 22:47:08 -06:00
u_packet_packer.go Fix panic when using QUICRandomFrames 2025-01-17 19:06:48 -07:00
u_parrot.go fix: uquic sync error 2023-08-28 16:53:19 -06:00
u_parrot_test.go Add panic test 2025-01-17 19:06:48 -07:00
u_quic_frames.go Support non-zero lowest frame offset 2024-11-22 15:12:57 -07:00
u_quic_frames_test.go Support non-zero lowest frame offset 2024-11-22 15:12:57 -07:00
u_quic_spec.go new: support variable length quic frame padding (#10) 2023-08-05 22:47:08 -06:00
u_transport.go fix: uquic sync error 2023-08-28 16:53:19 -06:00

drawing uQUIC

Go Build Status Ginkgo Test Status godoc


uQUIC is a fork of quic-go, which provides Initial Packet fingerprinting resistance and other features. While the handshake is still performed by quic-go, this library provides interface to customize the unencrypted Initial Packet which may reveal fingerprint-able information.

Golang 1.20+ is required.

If you have any questions, bug reports or contributions, you are welcome to publish those on GitHub. You may also reach out to one of the maintainers via gaukas.wang@colorado.edu.

Development is still in progress and we welcome any contributions adding new features or fixing extant bugs.

Disclaimer

This repository belongs to a large research project on how to fingerprint QUIC clients and how to mitigate such fingerprinting. We do not encourage any malicious use of this project's output, including this repository, uTLS, and clienthellod.

Our research paper is still yet to be published and therefore this repository is neither ready for production use nor peer-reviewed. And the scope of our research is limited that such mimicry backed by this library MAY NOT be realisticly indistinguishable from the real QUIC clients being mimicked, and some misuses of this library MAY lead to easier fingerprinting against the mimic. We welcome any contributions to improve the realism of the mimicry, as well as expanding the scope of this project.

For anyone intending to use this library for censorship circumvention, please be sure to understand the risks and limitations of this library.

If you are interested in our research, please stay tuned for our paper.

Development in Progress

Development Roadmap

  • Customize Initial Packet
    • QUIC Header
    • QUIC Frame (#3)
      • QUIC Crypto Frame
      • QUIC Padding Frame
      • QUIC Ping Frame
      • QUIC ACK Frame (on hold)
    • TLS ClientHello Message (by uTLS)
      • QUIC Transport Parameters (in a uTLS extension)
  • Customize Initial ACK behavior (#1, quic-go#4007)
  • Customize Initial Retry behavior (#2)
  • Add preset QUIC parrots
    • Google Chrome parrot (call for parrots w/ Token/PSK)
    • Mozilla Firefox parrot (call for parrots w/ Token/PSK)
    • Apple Safari parrot
    • Microsoft Edge parrot

Features

Initial Packet fingerprinting resistance

uQUIC provides a mechanism to customize the Initial Packet, which is unencrypted and is almost unique to every QUIC client implementation. We provide an interface to customize the Initial Packet and makes the fingerprinting of QUIC clients harder.

Build a QUIC Spec

A QUIC Spec sets parameters and policies for uQUIC in establishing a QUIC connection.

See u_parrot.go for examples of building a QUIC Spec (parrot).

Use a preset QUIC Spec

We provide a few preset QUIC Specs (parrots) for popular QUIC clients in u_parrot.go.

To use one, simple invoke QUICID2Spec(id). See below for a complete example of using a preset QUIC Spec in an HTTP3 client.

package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"

	tls "github.com/refraction-networking/utls"

	quic "github.com/refraction-networking/uquic"
	"github.com/refraction-networking/uquic/http3"
)

func main() {
	roundTripper := &http3.RoundTripper{
		TLSClientConfig: &tls.Config{},
		QuicConfig:      &quic.Config{},
	}

	quicSpec, err := quic.QUICID2Spec(quic.QUICFirefox_116)
	// quicSpec, err := quic.QUICID2Spec(quic.QUICChrome_115)
	if err != nil {
		log.Fatal(err)
	}

	uRoundTripper := http3.GetURoundTripper(
		roundTripper,
		&quicSpec,
		// getCRQUICSpec(),
		nil,
	)
	defer uRoundTripper.Close()

	h3client := &http.Client{
		Transport: uRoundTripper,
	}

	addr := "https://quic.tlsfingerprint.io/qfp/?beautify=true"

	rsp, err := h3client.Get(addr)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Got response for %s: %#v", addr, rsp)

	body := &bytes.Buffer{}
	_, err = io.Copy(body, rsp.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Response Body: %s", body.Bytes())
}