This repo contains components to measure the Direct Connection Upgrade through Relay (DCUtR) performance.
Specifically, this repo contains the following components:
Dashboards:
Talks
IPFS þing Jul 2022 | IPFS Camp Oct 2022 |
---|---|
The goal is to measure the hole punching success rate. For that, we are using a honeypot to attract inbound connections from DCUtR capable peers behind NATs. These are then saved into a database which get served to hole punching clients via a server component. The hole punching clients ask the server if it knows about DCUtR capable peers. If it does, the clients connect to the remote peer via a relay and waits for the remote to initiate a hole punch. The result is reported back to the server.
For macOS there is a menu bar application that you can download here: M1/M2
Intel
For the CLI version head over to the GitHub releases page and download the appropriate binary.
For Linux there's also a system tray application that you can download here: amd64
386
You can install it by running: tar -xf punchr-gui-linux-amd64.tar.xz && make user-install
For the CLI version head over to the GitHub releases page and download the appropriate binary.
Run make build
and find the executables in the dist
folder. To participate in the measurement campaign you only need to pay attention to the punchrclient
binary.
cd rust-client
cargo build --release
export API_KEY=<YOUR_API_KEY>
./target/release/rust-client
# As an alternative via cargo
cargo run --release
If you are running Arch (or Manjaro), you can grab rust-punchr
from AUR: https://aur.archlinux.org/packages/rust-punchr-bin
honeypot
The honeypot operates as a DHT server and periodically walks the complete DHT to announce itself to the network. The idea is that other peers add the honeypot to their routing table. This increases the chances of peers behind NATs passing by the honeypot when they request information from the DHT network.
When the honeypot registers an inbound connection it waits until the identify
protocol has finished and saves the following information about the remote peer to the database: PeerID, agent version, supported protocols, listen multi addresses.
server
The server exposes a gRPC api that allows clients to query for recently seen NAT'ed DCUtR capable peers that can be probed and then report the result of the hole punching process back.
go-client
The client announces itself to the server and then periodically queries the server for peers to hole punch. If the server returns address information the client connects to the remote peer via the relay and waits for the remote to initiate a hole punch. Finally, the outcome gets reported back to the server.
Resource requirements:
Storage
- ~35MB
Memory
- ~100MB
CPU
- ~2.5%
Bandwidth
- ~0.25MB
/minrust-client
Rust implementation of the punchr client.
Resource requirements:
Storage
- ~12MB
Memory
- ~20MB
CPU
- ~0.2%
Run make tools
to install all necessary tools for code generation (protobuf and database models). Specifically, this will run:
go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@v4.14.1
go install github.com/volatiletech/sqlboiler/v4@v4.6.0
go install github.com/volatiletech/sqlboiler/v4/drivers/sqlboiler-psql@v4.6.0
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
go install fyne.io/fyne/v2/cmd/fyne@latest
go install github.com/fyne-io/fyne-cross@latest
Then start the database with make database
or run:
docker run --rm -p 5432:5432 -e POSTGRES_PASSWORD=password -e POSTGRES_USER=punchr -e POSTGRES_DB=punchr postgres:14
Database migrations are applied automatically when starting either the honeypot or server component. To run them manually you have make migrate-up
, make migrate-down
and make database-reset
at your disposal.
To create and apply a new database migration run:
migrate create -ext sql -dir migrations -seq create_some_table
make migrate-up
Download a linux_armv6
or linux_armv7
release from the GitHub releases page, rename it to punchrclient
, and give it execute permissions chmod +x punchrclient
. Then you could install a systemd service at /etc/systemd/system/punchr-client.service
:
[Unit]
Description=Punchr Client
After=network-online.target
[Service]
User=pi
WorkingDirectory=/home/pi
ExecStart=/home/pi/punchrclient --api-key <some-api-key>
Restart=on-failure
[Install]
WantedBy=multi-user.target
To start the service run:
sudo service punchr-client start
If you're running NixOS, you can use the client option with the NixOS Module included in the flake.
Usage:
{
inputs.punchr = {
url = "github:dennis-tra/punchr";
};
# ...
outputs = inputs@{ self , nixpkgs }: {
# ...Inside NixOS config
{
imports = [ inputs.punchr.nixosModules.client ];
services.punchr-client.apiKey = "<API-KEY>";
# Make sure this is readable/writable by the `punchr` user or `punchr` group.
services.punchr-client.clientKeyFile = "/var/lib/punchr/client.keys"; # default value
}
};
}
You can run the client by itself with nix run github:dennis-tra/punchr#client
.
Systemd service example at /etc/systemd/system/punchr-server.service
:
[Unit]
Description=Punchr Server
After=network.target
[Service]
User=punchr # your user name
WorkingDirectory=/home/punchr # configure working directory
ExecStart=/home/punchr/punchrserver # path to binary
Restart=on-failure
[Install]
WantedBy=multiuser.target
To start the service run:
sudo service punchr-client start
Systemd service example at /etc/systemd/system/punchr-honeypot.service
:
[Unit]
Description=Punchr Honeypot
After=network.target
[Service]
User=punchr # your user
WorkingDirectory=/home/punchr # configure working directory
ExecStart=/home/punchr/punchrhoneypot # path to binary
Restart=on-failure
[Install]
WantedBy=multiuser.target
To start the service run:
sudo service punchr-honeypot start
Run:
SIGNING_CERTIFICATE="Developer ID Application: Firstname Lastname (DevID)" NOTARIZATION_PROFILE="APPSTORE_CONNECT" make gui
UNKNOWN
- There was no information why and how the hole punch completedNO_CONNECTION
- The client could not connect to the remote peer via any of the provided multi addresses. At the moment this is just a single relay multi address.NO_STREAM
- The client could connect to the remote peer via any of the provided multi addresses but no /libp2p/dcutr
stream was opened within 15s. That stream is necessary to perform the hole punch.CONNECTION_REVERSED
- The client only used one or more relay multi addresses to connect to the remote peer, the /libp2p/dcutr
stream was not opened within 15s, and we still end up with a direct connection. This means the remote peer succesfully reversed it.CANCELLED
- The user stopped the client (also returned by the rust client for quic multi addresses)FAILED
- The hole punch was attempted multiple times but none succeeded OR the /libp2p/dcutr
was opened but we have not received the internal start event OR there was a general protocol error.SUCCESS
- Any of the three hole punch attempts succeeded.Any connection to a remote peer can consist of multiple attempts to hole punch a direct connection. Each individual attempt could yield the following outcomes:
UNKNWON
- There was no information why and how the hole punch attempt completedDIRECT_DIAL
- The connection reversal from our side succeeded (should never happen)PROTOCOL_ERROR
- This can happen if e.g., the stream was reset mid-flightCANCELLED
- The user stopped the clientTIMEOUT
- We waited for the internal start event for 15s but timed outFAILED
- We exchanged CONNECT
and SYNC
messages on the /libp2p/dcutr
stream but the final direct connection attempt failed -> the hole punch was unsuccessfulSUCCESS
- We were able to directly connect to the remote peer.@dennis-tra, @elenaf9, @mxinden
Feel free to dive in! Open an issue or submit PRs.
Standard Readme follows the Contributor Covenant Code of Conduct.