All work

P2P Name Lookup over Kademlia

A distributed hash table that resolves names between peers

Year
2024
Kind
Systems
Status
Finished

An alpha peer-to-peer naming system in Python. Nodes join through an introduction server, then register and resolve domain names in a Kademlia distributed hash table.

A first cut at DNS-like name resolution inside a peer-to-peer network. New nodes join through an introduction server, which hands out a virtual IP and a few known peers. Names are hashed with SHA-1 and stored on the nodes whose IDs are closest by XOR distance, and lookups query the closest known nodes in rounds until the value turns up. Each record is signed with Ed25519, and a name belongs to the first key that registers it. The demo runs 10 nodes on one machine; NAT traversal and encryption are planned.

The problem

The idea is a naming system that lives inside a peer-to-peer network instead of DNS. Once a peer resolves a name to an address, it talks to that host directly, so the network carries lookups, not traffic. This repository is the first cut, in its commit message's words a basic implementation: a bootstrap server and a Kademlia hash table, demonstrated with 10 nodes on one machine.

How it works

  1. 01

    Join through an introduction server

    A new node connects to the introduction server over TCP and sends the address it listens on. The server assigns it a virtual IP in 10.0.0.0/8 and replies with up to 5 known peers, picked at random. It plays no part in storing or resolving names.

  2. 02

    Sort peers by XOR distance

    Each node's ID is the SHA-1 hash of its ip:port, a 160-bit number. Kademlia, the distributed hash table design used here, measures the distance between two IDs as their bitwise XOR. Peers are filed into 160 buckets by the highest bit where the IDs differ, up to 20 per bucket. A joining node pings the peers it was given and keeps the ones that answer.

  3. 03

    Register a name

    A domain is hashed into the same 160-bit space, so the nodes with the closest IDs are its home. The registering node sends STORE to up to 20 of the closest nodes in its own table, in parallel, then looks the name up to confirm. Full Kademlia would search the network for those nodes first. Each STORE is signed with the node's Ed25519 key, which is kept on disk so it survives restarts, over the name, a sequence number and the value. A node that has never seen the name binds it to that key, trust on first use, and from then on accepts a change only from the same key with a higher sequence number, so another key can't take the name and an old signed record can't be replayed to roll it back.

  4. 04

    Resolve a name

    A lookup asks the 3 closest nodes it hasn't asked yet. Each returns the value, or the closest nodes it knows. The asker keeps the 20 closest by XOR distance and repeats until the replicas have answered or nobody is left to ask. Every reply carries the signed record, and the asker checks the signature itself, so a node can withhold a name but can't forge one. If replicas disagree on the owner, the owner most of them report wins, and from then on the asker pins that owner for the name. Each request is its own TCP connection with a short text command, PING, STOR or FIND, framed by a 4-byte length prefix that is capped at 1 MB, and a peer that stalls mid-message is dropped after 10 seconds.

Decisions

  • A hash table, not a directory

    The README picks Kademlia for scale, replication and fast lookups by XOR distance. Each name lives on up to 20 nodes, not on one server.

  • A server only for joining

    A new node has to learn about someone before it can join. Past that, names never touch the introduction server, which the README calls a bootstrap node.

Known issues

  • Contacts passed around in replies aren't authenticated, so an attacker running most of the nodes closest to a name can still win the first lookup of it.