Mixnet client

Clients

The Nym Client was built in the Installation section. If you haven't yet built Nym and want to run the code on this page, go there first.

From inside the nym directory, the nym-client binary got built to the ./target/debug/ directory, so you can run it by invoking ./target/debug/nym-client:

nym$ ./target/debug/nym-client


      _ __  _   _ _ __ ___
     | '_ \| | | | '_ \ _ \
     | | | | |_| | | | | | |
     |_| |_|\__, |_| |_| |_|
            |___/

             (client - version 0.3.2)

    usage: --help to see available options.

There are three commands you can issue to the client.

  1. init - initialize a new client instance. Requires --id clientname parameter.
  2. websocket - run a mixnet client process, and listen on a websocket for input messages. Requires --id clientname as a parameter
  3. tcpsocket - run a mixnet client process, and listen on a TCP socket for input messages. Takes --id clientname as a parameter

Let's try it out. First, you need to initialize a new client.

./target/debug/nym-client init --id alice

nym$ ./target/debug/nym-client init --id alice


      _ __  _   _ _ __ ___
     | '_ \| | | | '_ \ _ \
     | | | | |_| | | | | | |
     |_| |_|\__, |_| |_| |_|
            |___/

             (client - version 0.3.2)


Initialising client...
Writing keypairs to "~/.config/nym/clients/alice"...
Client configuration completed.

Have a look at the generated files if you'd like - they contain clientname, public/private keypairs, etc.

You can run the client with a websocket listener for user alice by doing this:

./target/debug/nym-client websocket --id alice

Output should look something like this:

$ ./target/debug/nym-client websocket --id alice


      _ __  _   _ _ __ ___
     | '_ \| | | | '_ \ _ \
     | | | | |_| | | | | | |
     |_| |_|\__, |_| |_| |_|
            |___/

             (client - version 0.3.2)


Starting websocket on port: 9001
Listening for messages...
Starting nym client
Using directory server: "http://directory.nymtech.net"

When you run the client, it immediately starts generating (fake) cover traffic and sending it to the Nym testnet.

Congratulations, you have just contributed a tiny bit of privacy to the world! <CTRL-C> to stop the client.

Try stopping and starting the client a few times. If you're interested, you should see your traffic reflected in the network traffic sent and received metrics at the Nym Dashboard. Have a look on the right hand side:

dashboard

Understanding the client

A large proportion of the Nym mixnet's functionality is implemented client-side, including:

  1. determining network topology
  2. registering with mixnet's default store-and-forward providers
  3. fetching stored messages from the store-and-forward providers
  4. sending a constant stream of Sphinx packet cover traffic messages
  5. sending Sphinx packets with real messages
  6. sending Sphinx packet cover traffic when no real messages are being sent

Determining network topology

The first thing to understand is that it's the local client which picks the path that each packet will take through the mixnet topology.

When you first run your client, the client needs to figure what mixnodes exist, which layers they're in, and their public keys.

The client asks the Nym directory for the current mixnet topology. The client handles all this automatically, but in order to understand what's happening, you can try it yourself:

curl -X GET "https://directory.nymtech.net/api/presence/topology" -H  "accept: application/json" | jq

This returns a JSON-formatted list of MixNodes and MixProviderNodes, among other things:

"MixNodes": [
  {
    "host": "52.56.99.196:1789",
    "pubKey": "_ObRUsYnHDJOPDHXyfq5bnIoSbdn3BsSRcrLl-FCY1c=",
    "layer": 2,
    "lastSeen": 1572258570490299400
  },
  {
    "host": "18.130.86.190:1789",
    "pubKey": "dMtoH6vWDBfwjrU0EzPd-fhZDOGJazELsTp2qLyt72U=",
    "layer": 1,
    "lastSeen": 1572258571193777000
  },
  {
    "host": "3.10.22.152:1789",
    "pubKey": "03FFZ5RgfeBPmVVERenJOCLb-yXlOUtstc6izYc-wFs=",
    "layer": 1,
    "lastSeen": 1572258570994450200
  },
  {
    "host": "35.176.155.107:1789",
    "pubKey": "oaEqLzA5nUxMAqfg6yW5pneWC342uDMfVsSHxyNQ-DE=",
    "layer": 3,
    "lastSeen": 1572258571709773800
  },
  {
    "host": "3.9.12.238:1789",
    "pubKey": "ALf35HwBzXZXxaS6V55W7cLsx4a26AaRefinwwJHrg4=",
    "layer": 3,
    "lastSeen": 1572258571616835600
  },
  {
    "host": "35.178.213.77:1789",
    "pubKey": "KlfEn07FzcN93nMzzlsgq3wN5O1ID6O3Pd4DbezHEWo=",
    "layer": 2,
    "lastSeen": 1572258570492776400
  }
],
"MixProviderNodes": [
  {
    "host": "35.178.212.193:1789",
    "pubKey": "R_rGKmwelVAVRpicMwMIJwsHvdYHMNfcItPwNipu5GQ=",
    "registeredClients": [
      {
        "pubKey": "u7UTjC3UNXdz0HsjMKoxozzbvXyi3KrEvl8BxNNPcAM="
      },
     ...
    ],
    "lastSeen": 1572258572070089000
  },
  {
    "host": "3.8.176.11:1789",
    "pubKey": "XiVE6xA10xFkAwfIQuBDc_JRXWerL0Pcqi7DipEUeTE=",
    "registeredClients": [
      {
        "pubKey": "HGTg5XPWe4eiluFKTnC958PuGUSipjLcIeFdLi6zsww="
      },
      ...
    ],
    "lastSeen": 1572258571843881700
  }
],
...

The client does this when it starts. Each mixnode reports what layer it's in, its public key, and its IP address. Provider nodes do the same.

The client now has all the information needed to pick a path through the mixnet for each Sphinx packet, and do packet encryption.

Registering at a provider

When the client is first started, it sends a registration request to one of the available providers, (see MixProviderNode list in the topology). This returns a unique token that the client attaches to every subsequent request to the provider.

This is required as mixnet clients cannot receive messages directly from other clients as this would have required them to reveal their actual IP address which is not a desirable requirement. Instead the providers act as a sort of proxy between the client and the mixnet. So whenever client receives a message, it is stored by the specified provider until the recipient fetches it.

Fetching stored messages

Upon completing the provider registration, the client starts a separate message stream that periodically fetches all the client's stored messages on the provider.

Note that once the message is pulled, the provider immediately deletes it.

Sending messages

Since it now understands the topology of the mixnet, the client can start sending traffic immediately. But what should it send?

If there's a real message to send (because you poked something down the client's inbound socket connection), then the client will send a real message. Otherwise, the client will send cover traffic.

Real messages and cover traffic are both encrypted using the Sphinx packet format, so that they're indistinguishable from each other.

Sphinx packet creation

Clients create Sphinx packets. These packets are a bit complicated, but for now all you need to know is that they have the following characteristics:

  1. they consist of a header and a body
  2. the header contains unencrypted routing data
  3. bodies are encrypted
  4. bodies are padded so that they're all the same size
  5. observers can't tell anything about what's inside the encrypted body
  6. the body is layer-encrypted - it may contain either another sphinx packet or a payload message

Now let's build the Nym Mixnode and see what happens when a Sphinx packet hits a mixnode.

Integrating the mixnet client in your applications

Depending on what language you're using, you can fire up the client in one of two ways.

Using TCP Socket

[TODO]

Using the Websocket

[TODO]