12 releases

Uses old Rust 2015

0.2.10 Feb 17, 2020
0.2.9 Feb 14, 2020
0.2.2 Jan 24, 2020
0.1.2 Jun 24, 2018
0.1.1 Apr 2, 2018

#1886 in Network programming

30 downloads per month

GPL-3.0 license

430KB
10K SLoC

Rust 8K SLoC // 0.1% comments Python 1.5K SLoC // 0.1% comments Shell 42 SLoC // 0.2% comments

KIPA: Key to IP Address

Crates.io Build Status Documentation

A distributed Key to IP Address query network.

What is KIPA?

KIPA is a look-up service for finding out which IP addresses belong to a public key. Everyone on the KIPA network allows themselves to be looked up by their key, and is helps to look up others in the network.

It is distributed, meaning that there is no single server on which the network relies (backed up by benchmarks).

It is zero-trust, meaning it is resilient against bad actors.

It is scalable, performing well with large network sizes (backed up by benchmarks) and slow network speeds (backed up by benchmarks).

KIPA is still a work in progress, and should be used with caution. It is recommended that you generate a new key to try out KIPA.

How does it work?

When a node joins the KIPA network, its public key is mapped to an n-dimensional space, where n is constant throughout the network. The mapping is done uniformly and deterministically. This space is called key space. (For a discussion on the value of n, see selecting dimensions).

Each node will attempt to find the IP addresses of other nodes which are close to it in key space, and set those nodes to be its neighbours. Once this is achieved, look-ups can be performed using simple graph search algorithms: a node can map a chosen public key into key space, and then identify its neighbour closest to that point, and ask that neighbour for its closest neighbour to that point. The process continues until the correct node is found (or until it is determined that no such node exists). This is a slightly modified greedy best-first search algorithm, where the metric is distance in key space.

Nodes connect to the network through an initial node - this node can be any node in the network, but its IP address and public key must be known before connecting. In order to find its neighbours, the connecting node performs a search for itself in the network (in a similar style to above), and selects the closest nodes it encounters.

You can find a more detailed overview of KIPA's design here, and a summary of planned future work here.

Why does it exist?

KIPA is a tool for use in distributed systems. It can replace DNS in scenarios where DNS isn't appropriate - for example, when:

  • The IP addresses of nodes change often.
  • There are too many nodes to enrol in DNS registrars.
  • Deploying distributed systems with community nodes, where community enrollment is difficult.
  • DNS does not guarantee high enough security.

It can also be used for casual cases, for example sending files between computers when IP addresses are not known, but public keys are:

# Run on receiver
nc -l -p 8080 > file.txt
# Run on sender
cat file.txt > nc $(kipa search --key $RECEIVER_KEY_ID --print ip) 8080

Any use of KIPA requires that keys are already known in the system - it does not solve the problem of key distribution. What it does do is provide a secure and distributed infrastructure for resolving up-to-date IP addresses.

Why distributed?

Distributed systems have several advantages over centralised ones. In the case of KIPA, some specific advantages arise from its distributed architecture:

  • Privacy: As messages are spread evenly throughout the network, no single node sees all messages. Therefore, total information control is impossible to achieve unless all nodes are controlled by one organisation*.
  • Robustness: No single node can fail and corrupt the entire network.
  • Community control: Control of the network is not given to one organisation, meaning that the performance and stability of the network is dependent upon the community. If the community uses KIPA, KIPA stays up. Alternatively if no one does, KIPA goes down.

* This design has the effect that each node is aware of a portion of the look-ups in the network. However, as the amount of nodes in the network increases, this portion becomes smaller and smaller. Therefore, no significant amount of information is seen by any single node.

Usage

Prerequisites:

  • Rust and Cargo >= 1.26.0
  • Protobuf compiler >= 3.5.1
  • GnuPG >= 2.2.8
    • gpgme crate requires autogen, gettext to build
# KIPA is a work in progress - to be cautious, make a KIPA-specific key when trying it out.
gpg --generate-key
# KIPA reads the key password from a file.
echo "my-secret-key-p@ssword" > secret.txt

# Install KIPA.
cargo install kipa

# Start the daemon, and connect to any node in the network. A live example is given.
kipa-daemon --key "$MY_KEY_ID" \
    --connect-key D959094C \
    --connect-address 46.101.16.228:10842 &
# This will listen on port 10842 (overridable with --port) to communicate with other KIPA nodes - so
# if you're behind NAT, be sure to expose the port!

# Now you can search for key IDs that you have in GPG!
kipa search "$THEIR_KEY_ID"

Docker

You can also set up a daemon in a Docker container.

# Set up a new key, export it to a file, and export the password to a file.
gpg --generate-key
gpg --export-secret-keys --output "$KEY_PATH" "$KEY_ID"
echo "my-secret-key-p@ssword" > $KEY_PASSWORD_PATH

# Start the container, and connect to any node in the network. A live example is given.
docker run \
    --name kipa \
    # Mount the secret key files.
    --mount type=bind,source=$KEY_PATH,target=/root/key \
    --mount type=bind,source=$KEY_PASSWORD_PATH,target=/root/key-password \
    # If running as a production instance, set up restarts, detach, and expose the port.
    --restart on-failure --publish 10842:10842 --detach \
    mishajw/kipa:latest
    --key "$KEY_ID"
    --connect-key D959094C
    --connect-address 46.101.16.228:10842

# You can use `docker exec` to run KIPA commands.
# Note that only the keys in `./resources/keys` are in the container's GPG.
docker exec kipa \
    kipa search "$THEIR_KEY_ID"

Simulations

KIPA network simulation code is found in ./simulation. This also includes end-to-end tests, and benchmarking. Simulation results are written to ./simulation_output.

The benchmarks document discusses how the simulations are used to evaluate the performance of KIPA.

The simulations create a network of Docker containers. All created resources are prefixed with kipa_simulation_ and are removed after the simulation is finished.

Prerequisites:

  • All previously mentioned prerequisites
  • Python and Pip >= 3.6
  • virtualenv >= 15.1.0
  • Docker >= 18.05.0, with daemon running
# Install dependencies in virtualenv
python -m venv .env && source .env/bin/activate
pip install -r simulation/requirements.txt

# Run end-to-end tests
python -m unittest discover simulation

# Run simulation configuration
# Example network configurations exist in `./resources/simulaton_configs/`
python -m simulation --network_config $NETWORK_CONFIGURATION_FILE

Dependencies

~21–33MB
~510K SLoC