{"id":18892373,"url":"https://github.com/hf/quicpipe","last_synced_at":"2026-01-12T01:47:09.399Z","repository":{"id":64919981,"uuid":"559544310","full_name":"hf/quicpipe","owner":"hf","description":null,"archived":false,"fork":false,"pushed_at":"2023-01-22T16:31:07.000Z","size":36,"stargazers_count":12,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-01T12:39:57.530Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hf.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":null,"support":null}},"created_at":"2022-10-30T13:01:17.000Z","updated_at":"2025-07-07T06:49:16.000Z","dependencies_parsed_at":"2023-02-12T16:55:13.385Z","dependency_job_id":null,"html_url":"https://github.com/hf/quicpipe","commit_stats":null,"previous_names":["hf/quicket"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hf/quicpipe","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hf%2Fquicpipe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hf%2Fquicpipe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hf%2Fquicpipe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hf%2Fquicpipe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hf","download_url":"https://codeload.github.com/hf/quicpipe/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hf%2Fquicpipe/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28331253,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T00:36:25.062Z","status":"ssl_error","status_checked_at":"2026-01-12T00:36:15.229Z","response_time":60,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2024-11-08T08:01:39.001Z","updated_at":"2026-01-12T01:47:09.384Z","avatar_url":"https://github.com/hf.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"Quicpipe\n=======\n\nQuicpipe (QUIC + Socket) is a way of establishing point-to-point QUIC\nconnections between two devices that are unable to directly connect to each\nother via traditional means.\n\nFor example, devices on the modern internet are often unable to directly talk\nto each other due to the use of NAT. Sometimes devices even change their IP\naddress due to changing their physical location or connectivity status.\n\nTechnologies such as WebRTC were aimed at solving this problem. However, they\ncome from a time where QUIC did not exist and real-time communication between\ndevices was mainly attempting to solve the video/audio over IP problem. Thus\nthe complexity of WebRTC is still prohibitive both in system complexity and\ncost of operation as well.\n\nQuicpipe, or this implementation of it at least, attempts to solve this problem\nin a novel way, one that is both simpler and cheaper to operate than WebRTC.\nIt's a proof-of-concept at this stage.\n\n## Quicpipe protocol\n\nQuicpipe is really just plain QUIC with some carefully chosen parameters that\nenable point-to-point communication.\n\nWhenever `A` wants to open a point-to-point connection to `B` the following\napplies:\n\n- `A` is the dialer, `B` is the accepter\n- Both have previously exchanged TLS trust information\n- Both *always* use 12-byte connection IDs (this can be modified)\n- Both assume QUIC version 1, and do no MTU discovery\n- `A` produces an initial packet and discloses its connection IDs to `R`\n- `B` receives the initial handshake out-of-band and discloses its connection\n  IDs to `R`\n- `A` and `B` talk to `R` via HTTP3 or another QUIC-based protocol\n- `R` maps all of `A`'s connection IDs to its public UDP address, and forwards\n  packets with such destination IDs to `A`; vice versa for `B`\n\n`R` provides these important features:\n\n- Hole punching: since the connection ID sharing occurs over HTTP3, a UDP hole\n  is punched through NAT before the handshake continues between `A` and `B`\n- Efficient forwarding: Given that `R` knows all connection IDs that will ever\n  be used between `A` and `B`, it only needs to look up destination connection\n  IDs for each QUIC packet and forward to the correct destination\n\nOnce `A` and `B` are able to reach each other over `R`'s relay service, they\ncan agree to attempt direct NAT hole punching over UDP. QUIC makes it really\neasy for `A` and `B` to migrate their stream over any transmission medium and\naddress space -- while they can always fall back to using `R`'s services at any\ntime as a guaranteed fallback. This is why `R` always needs to know all of the\npossible connection IDs that `A` and `B` are going to use _through it_.\n\nThe initial packet from `A` to `B` can be delivered via `R` or via any other\nmedium: Apple Push-Notifications, Firebase Cloud Messaging, Bluetooth, camera\nvia QR code, audio, ...\n\n## Comparison to WebRTC\n\n**Signaling**: WebRTC requires that peers figure out a way to discover (i.e.\ndial) each other. This is often done over SIP and requires non-trivial and\nsometimes expensive infrastructure to set up well. With Quicpipe signaling is\n\"built in\" and is based on regular HTTP3 requests. At this time there's no\nofficial request/response encoding standard but applications can design it to\nbe as complex as they choose, and can use text or binary encodings as well.\n\n**Protocol**: WebRTC uses SCTP (UDP) over DTLS, which has similar but not\nequivalent properties with QUIC. QUIC has TLS built in and the connection is\nbetween the peers, rather than through a middle-box. QUIC offers both streams\nand datagrams, in various modes, and has excellent privacy features.\n\n**Support**: WebRTC is supported in browsers, while Quicpipe is not supported in\nbrowsers at this time.\n\n**Architecture**: WebRTC prefers establishing direct connections between peers\n(via the ICE framework) but in the modern internet a TURN server (a relay\nserver) is often and increasingly necessary. TURN servers are expensive to run\nsince they often do stream processing, re-encoding and re-encrypting. A Quicpipe\nserver is a TURN-style server by default and can use optimization techniques\nsuch as eBPF to implement an incredibly cost-effective, privacy preserving\nrelay.\n\n**End-to-end encryption**: QUIC does not allow unencrypted streams. Furthermore\nTLS must be used.. A Quicpipe relay has no way to decode the traffic between the\npeers, given that peers properly exchange certificates that guards against a\nmiddle-person attack. Using QUIC between peers is also a good idea since peers\ndon't have to reinvent (an insecure) TLS.\n\n## Example\n\nThe `example` directory has an example implementing the tree parties. Start\nthem like so:\n\nRelay server:\n\n```shell\ngo run github.com/hf/quicpipe/example/server\n```\n\nTo use eBPF on Linux in the example, you should set this type of environment\nvariable `QUICPIPE_XDP_IFACE=\"lo\"` which will attach the Quicpipe eBPF XDP\nfilter on the interface with the provided name.\n\nCopy the port of the listening address, called `\u003cport\u003e`:\n\n```shell\nQHOST='127.0.0.1:\u003cport\u003e' go run github.com/hf/quicpipe/example/dialer\n```\n\nDialer will now attempt to dial the *accepter* (which we're yet to start). To\ndo this it will print out its initial packet to standard output. Copy the JSON\nand add it to a file `/tmp/packet.json`. This simulates the out-of-band\ntransmission of the QUIC initial packet.\n\n```shell\ncat /tmp/packet.json | QHOST='127.0.0.1:\u003cport\u003e' go run github.com/hf/quicpipe/example/accepter\n```\n\nAccepter will now read the initial packet from the file and begin talking to\nthe dialer over the server. You should see a `hello` message being printed\nevery second, this is a message sent from the dialer.\n\n## eBPF (XDP) filter\n\nThis implementation offers an eBPF XDP filter that significantly improves\nperformance in relaying QUIC packets to peers.\n\nIt works by mapping the 12 byte connection IDs (CID) to an IPv4 + UDP port\npair. It transmits only short-form QUIC packets directly out of the NIC.\n\nThe filter uses a LRU map of about 36MB which can hold about 2m redirect\nentries. When the map gets full, some QUIC packets are likely to be rejected by\nthe filter. A ring-buffer map (which can hold about 5k CIDs) is provided for\nthis case which will notify userspace of any rejected CIDs, so that it can\nre-populate the map with any improperly dropped packets.\n\nSince UDP is assumed to be unreliable, this approach suffices for most\nuse-cases.\n\n## Further work\n\nThis has not been tested on a live network yet. Performance is improving but\nmore work is needed.\n\nSome guidelines or standardization of the registration protocol is probably\nuseful. Right now the examples use a `POST /v1/register` unsecured endpoint to\nregister their connection IDs, which are derived using Blake2b MACs and a\nsimple sequential counter.\n\n## License\n\nCopyright \u0026copy; 2022-2023 Stojan Dimitrovski. Some rights reserved.\n\nLicensed under the MIT X11 license. You can get a copy of it in `LICENSE`.\n\nThe eBPF XDP filter can also be licensed under GPLv2 if you so please. This is\nnecessary if you want to debug it with `bpf_printk`. You can find a copy of\nGPLv2 online.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhf%2Fquicpipe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhf%2Fquicpipe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhf%2Fquicpipe/lists"}