Files
udp_nostr/drafts/tweet.md
T
2026-08-12 16:34:22 -04:00

5.4 KiB

NOSTR over single packet UDP

TLDR

Send a Nostr event as one-way UDP packet instead of using TCP. This one-way send is very censorship resistant compared to the alternatives. I currently have it implemented on my relay and you can test it now on the command line using nc and nostr:npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6's nak. ''' nak event -k 1 -c "I don't shake hands, because Ewwwwww!" | nc -u -w1 laantungir.net 443 '''

The problem:

https://blossom.laantungir.net/b63479f895a207fccfbac9323ac7a4bd47cbc20e43ebfcd60f3c54e41bfb1d1d.jpg As far as I know, every circumvention tool [VPN, Tor, Shadowsocks, obfs4] has a handshake. You start off messaging the server, and the server replies before you can send your information. National firewalls detect those handshakes, fingerprint them, probe the handshake, then block the IP or take other action. The handshake is a vulnerability. Every tool plays cat-and-mouse obfuscating it.

For example Tor bridges are vulnerable to active probing. The adversary connects to a suspected bridge and sends data. If the server responds with a valid obfs4 handshake, the adversary knows it is a bridge. This is how China blocks many Tor bridges.

The idea:

UDP Nostr eliminates the handshake entirely. The Nostr event is already signed before it touches the network. The signature replaces the handshake. There is no SYN, no TLS ClientHello, no SNI, no key exchange, no recognizable structure — just a blob of bytes in one UDP packet under 1472 bytes.

The adversary can send a probe, but the relay doesn't respond at all. No handshake to detect. No TCP RST to inject (UDP has no RST). No DNS to poison (send to the IP directly).

Live example — full zero-config round-trip

My relay runs my c-nostr-pg project and has fully implemented UDP Nostr.

https://blossom.laantungir.net/5b1c5fc4ddf89b4aec123c7a2a5934e9a22c3271fa641b071cc8f7740a342bbd.png

command line

# Console 1 - Set up a live watch for the nak default events on the relay
nak req -a 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 --stream laantungir.net/relay

# Console 2 - Send via UDP (no --sec needed, nak uses the default key)
nak event -k 1 -c "Hello!" | nc -u -w1 laantungir.net 443

Python:

import socket, sys
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto(sys.stdin.buffer.read(), (sys.argv[1], int(sys.argv[2])))
nak event -k 1 -c "Hello!" | python3 send.py laantungir.net 443

JavaScript (Node.js):

const dgram = require("dgram"), s = dgram.createSocket("udp4");
process.stdin.on("data", b => s.send(b, +process.argv[3], process.argv[2]));
nak event -k 1 -c "Hello!" | node send.js laantungir.net 443

An example of largest kind:1 that fits in one packet

With the default nak key, empty tags, and a 10-digit timestamp, the Nostr JSON overhead (structural syntax + hex-expanded id/pubkey/sig) is ~340 bytes, leaving ~1132 characters of content in the 1472-byte UDP budget. Below is an illustrative event at full capacity — its single-line JSON form is exactly 1472 bytes on the wire, one Ethernet frame, unfragmented. (The id and sig shown are placeholders for readability; a real event carries a SHA-256 id and valid Schnorr sig.)

{"id":"426462725f7061636b65745f626f756e646172795f746573745f303030303030",
"pubkey":"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
"created_at":1772019044,
"kind":1,
"tags":[],
"content":"The cypherpunk problem: how do two computers communicate freely when the network between them is controlled by an adversary? The standard approaches are anonymity (hide which computer is talking) and decentralization (make copies everywhere so you can't stop them all). But there is a third approach that is less explored: protocol substrate hardening. Design the communication protocol so that interference requires violating physics or OS-level guarantees. The simplest example: fit your message in a single UDP datagram under 1472 bytes. At this size, your message is exactly one Ethernet frame. The adversary cannot block it without blocking all UDP traffic on that port. They cannot fragment it. They cannot reassemble it. They cannot probe for a handshake because there is no handshake. The Nostr event is self-validating: it carries its own signature. The signature replaces the handshake. This is the key insight. Every other protocol announces itself with a handshake. TCP has SYN. TLS has ClientHello. QUIC has its Initial packet. WireGuard has its handshake initiation. All of these create a pattern that can be fingerprinted and blocked. A Nostr event over UDP has no pattern. It is just bytes on the wire. The receiver validates the signature using only the pubkey in the event. No shared secrets. No session setup. No state. This is the no-handshake property. It is the fundamental advantage of Nostr over every other protocol for censorship resistance. Combine this with the MTU boundary and you have a protocol that cannot be blocked without blocking all UDP traffic. The adversary faces a dilemma: block UDP entirely and break the internet, or let your messages through. This is the asymmetry we exploit.",
"sig":"4b57c22b1797b109530ffe5d04cabac468b1a5942873a5141334ecbc77694fc968a1b941979ba13602fceb1dad8014ab6469c6ae9cef0b5668cc23ad1449e103"}

Future work

I'm currently working on an encryption scheme specifically for this protocol.