{"id":17257207,"url":"https://github.com/gaukas/clienthellod","last_synced_at":"2025-04-14T05:32:08.414Z","repository":{"id":138370313,"uuid":"603245832","full_name":"gaukas/clienthellod","owner":"gaukas","description":"TLS ClientHello/QUIC Initial Packet reflection service","archived":false,"fork":false,"pushed_at":"2024-06-06T16:40:37.000Z","size":14387,"stargazers_count":16,"open_issues_count":2,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-27T19:52:01.730Z","etag":null,"topics":["clienthello","quic","quic-fingerprint","tls","tls-fingerprint"],"latest_commit_sha":null,"homepage":"https://client.tlsfingerprint.io","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gaukas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-02-17T23:41:50.000Z","updated_at":"2025-03-14T12:08:47.000Z","dependencies_parsed_at":null,"dependency_job_id":"b06032ee-10a3-418f-b80d-7469273d7c83","html_url":"https://github.com/gaukas/clienthellod","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaukas%2Fclienthellod","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaukas%2Fclienthellod/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaukas%2Fclienthellod/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaukas%2Fclienthellod/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gaukas","download_url":"https://codeload.github.com/gaukas/clienthellod/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248826771,"owners_count":21167741,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clienthello","quic","quic-fingerprint","tls","tls-fingerprint"],"created_at":"2024-10-15T07:16:40.379Z","updated_at":"2025-04-14T05:32:08.150Z","avatar_url":"https://github.com/gaukas.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `clienthellod`: TLS ClientHello/QUIC Initial Packet reflection service\n![Go Build Status](https://github.com/gaukas/clienthellod/actions/workflows/go.yml/badge.svg)\n[![Go Report Card](https://goreportcard.com/badge/github.com/gaukas/clienthellod)](https://goreportcard.com/report/github.com/gaukas/clienthellod)\n[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fgaukas%2Fclienthellod.svg?type=shield\u0026issueType=license)](https://app.fossa.com/projects/git%2Bgithub.com%2Fgaukas%2Fclienthellod?ref=badge_shield\u0026issueType=license)\n[![Go Doc](https://pkg.go.dev/badge/github.com/refraction-networking/water.svg)](https://pkg.go.dev/github.com/refraction-networking/water)\n\n`clienthellod`, read as \"client-hello-D\", is a TLS ClientHello/QUIC Initial Packet reflection service. It can be used to parses TLS ClientHello messages and QUIC Initial Packets into human-readable and highly programmable formats such as JSON. \n\nIs is a part of the TLS fingerprintability research project which spans [tlsfingerprint.io](https://tlsfingerprint.io) and [quic.tlsfingerprint.io](https://quic.tlsfingerprint.io). It parses the ClientHello messages sent by TLS clients and QUIC Client Initial Packets sent by QUIC clients and display the parsed information in a human-readable format with high programmability. \n\nSee [tlsfingerprint.io](https://tlsfingerprint.io) and [quic.tlsfingerprint.io](https://quic.tlsfingerprint.io) for more details about the project.\n\n## Quick Start\n\n`clienthellod` comes as a Go library, which can be used to parse both TLS and QUIC protocols. \n\n### TLS/QUIC Fingerprinter\n\n```go\n    tlsFingerprinter := clienthellod.NewTLSFingerprinter()\n```\n\n```go\n    quicFingerprinter := clienthellod.NewQUICFingerprinter()\n```\n\n### TLS ClientHello\n\n#### From a `net.Conn`\n\n```go\n    tcpLis, err := net.Listen(\"tcp\", \":443\")\n    defer tcpLis.Close()\n\n    conn, err := tcpLis.Accept()\n\tif err != nil {\n        panic(err)\n\t}\n    defer conn.Close()\n\n\tch, err := clienthellod.ReadClientHello(conn) // reads ClientHello from the connection\n    if err != nil {\n        panic(err)\n    }\n\n    err := ch.ParseClientHello() // parses ClientHello's fields\n    if err != nil {\n        panic(err)\n    }\n\n    jsonB, err = json.MarshalIndent(ch, \"\", \"  \")\n    if err != nil {\n        panic(err)\n    }\n\n    fmt.Println(string(jsonB))\n    fmt.Println(\"ClientHello ID: \" + ch.HexID) // prints ClientHello's original fingerprint ID calculated using observed TLS extension order\n    fmt.Println(\"ClientHello NormID: \" + ch.NormHexID) // prints ClientHello's normalized fingerprint ID calculated using sorted TLS extension list\n```\n\n#### From raw `[]byte`\n\n```go\n    ch, err := clienthellod.UnmarshalClientHello(raw)\n    if err != nil {\n        panic(err)\n    }\n    \n    // err := ch.ParseClientHello() // no need to call again, UnmarshalClientHello automatically calls ParseClientHello\n```\n\n### QUIC Initial Packets (Client-sourced)\n\n#### Single packet\n\n```go\n    udpConn, err := net.ListenUDP(\"udp\", \":443\")\n    defer udpConn.Close()\n\n    buf := make([]byte, 65535)\n    n, addr, err := udpConn.ReadFromUDP(buf)\n    if err != nil {\n        panic(err)\n    }\n\n    ci, err := clienthellod.UnmarshalQUICClientInitialPacket(buf[:n]) // decodes QUIC Client Initial Packet\n    if err != nil {\n        panic(err)    \n    }\n\n    jsonB, err = json.MarshalIndent(cip, \"\", \"  \")\n    if err != nil {\n        panic(err)\n    }\n\n    fmt.Println(string(jsonB)) // including fingerprint IDs of: ClientInitialPacket, QUIC Header, QUIC ClientHello, QUIC Transport Parameters' combination\n```\n\n#### Multiple packets\n\nImplementations including Chrome/Chromium sends oversized Client Hello which does not fit into one single QUIC packet, in which case multiple QUIC Initial Packets are sent.\n\n```go\n    gci := GatherClientInitials() // Each GatherClientInitials reassembles one QUIC Client Initial Packets stream. Use a QUIC Fingerprinter for multiple potential senders, which automatically demultiplexes the packets based on the source address.\n    \n    udpConn, err := net.ListenUDP(\"udp\", \":443\")\n    defer udpConn.Close()\n\n    for {\n        buf := make([]byte, 65535)\n        n, addr, err := udpConn.ReadFromUDP(buf)\n        if err != nil {\n            panic(err)\n        }\n\n        if addr != knownSenderAddr {\n            continue\n        }\n\n        ci, err := clienthellod.UnmarshalQUICClientInitialPacket(buf[:n]) // decodes QUIC Client Initial Packet\n        if err != nil {\n            panic(err)    \n        }\n\n        err = gci.AddPacket(ci)\n        if err != nil {\n            panic(err)\n        }\n    }\n```\n\n### Use with Caddy\n\nWe also provide clienthellod as a Caddy Module in `modcaddy`, which you can use with Caddy to capture ClientHello messages and QUIC Client Initial Packets. See [modcaddy](https://github.com/gaukas/clienthellod/tree/master/modcaddy) for more details.\n\n## License\n\nThis project is developed and distributed under Apache-2.0 license. \n\n[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fgaukas%2Fclienthellod.svg?type=large\u0026issueType=license)](https://app.fossa.com/projects/git%2Bgithub.com%2Fgaukas%2Fclienthellod?ref=badge_large\u0026issueType=license)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaukas%2Fclienthellod","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgaukas%2Fclienthellod","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaukas%2Fclienthellod/lists"}