Skip to content

one-d-wide/yggdrasil-jumper

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Yggdrasil-jumper

This project aims to transparently reduce latency of a connection over Yggdrasil network by on-demand establishing direct peer-to-peer connections, bypassing intermediary nodes, using NAT traversal.

Features

  • Peer-to-peer level latency for any traffic between pair of peers, running the jumper.
  • Automatic NAT/Firewall traversal (aka hole-punching).
  • Neither firewall configuration nor port mapping is required at all.
  • No configuration of the jumper is required by default.
  • Transparent integration with yggdrasil router.

How it works

By default, yggdrasil-go routes data only through explicitly connected peers and doesn't attempt to reach other nodes accessible over the internet. Therefore, path usually contains 1-2 intermediary nodes, namely public peers of both sides. If both you and your peer use internet, you can send traffic directly (aka peer-to-peer), thus reducing latency.

  • Jumper connects to Admin API of the running router. And monitors active sessions (peers you have data exchange over Yggdrasil network with).
  • Once any such session appears, jumper tries to connect to associated peer, assuming it has another jumper running on the same listen_port.
  • Both jumpers exchange their external internet addresses and use NAT traversal technique to instantiate direct bridge over the internet.
  • If previous step was successful, jumper will relay all data passing the bridge to the router until session is closed or other error occurs.

Usage

Jumper can run without additional configuration. All it needs is access to Admin API of the router and to the IP network.

$ yggdrasil-jumper --loglevel info # off/error/warn/info/debug
...

It may be helpful to know what the defaults are.

$ yggdrasil-jumper --print-default
...
# List of possible admin socket locations
yggdrasil_admin_listen = [
  "unix:///var/run/yggdrasil/yggdrasil.sock",
  "unix:///var/run/yggdrasil.sock",
  "tcp://localhost:9001",
]
...
# List of allowed yggdrasil peer addresses
# Uncomment to apply
#whitelist = [ ]
...
# List of peering protocols
# Supported: "tcp", "tls", "quic"
yggdrasil_protocols = [ "tcp" ]

# List of yggdrasil listen addresses
# Listed in the yggdrasil config as `Listen`
# Needed for protocols: "tls", "quic"
yggdrasil_listen = [ ]
...
# Default connect/listen port on yggdrasil network
listen_port = 4701
...
# List of STUN servers
stun_servers = [
  ...
]
...

You can also overwrite some if needed.

$ yggdrasil-jumper --config <path> # standard input is read if path is "-"
...

Installation

  • Downloading: Check the Releases page.
  • Compiling:
    $ git clone https://github.com/one-d-wide/yggdrasil-jumper
    $ cd yggdrasil-jumper
    $ cargo build --bin yggdrasil-jumper --release
    $ sudo cp target/release/yggdrasil-jumper /usr/local/bin/yggdrasil-jumper

Details

External address lookup

In order to know what address to use with NAT traversal, jumper must know self external internet address and port. This task is performed using STUN protocol with TCP extension, hence not every STUN server is supported. STUN standard is quite broad, but jumper utilities only address lookup feature.

You can check compatibility using stun-test binary from this repository.

$ cargo build --bin stun-test --release
$ # ./target/release/stun-test

stun-test takes network protocol and STUN server(s) as argument and outputs resolved address.

$ stun-test --tcp --print-servers stunserver.stunprotocol.org:3478
stunserver.stunprotocol.org:3478 244.13.30.107:28674

You can also take servers from hardcoded defaults or your configuration.

$ stun-test --tcp --default
244.13.30.107:28674
...

If stun-test fails to connect to any server it will print error and exit with code 1.

$ stun-test --tcp stunserver.stunprotocol.org:3478 127.0.0.1:3478
244.13.30.107:28674
ERROR While resolving {server=127.0.0.1:3478}: Failed to connect: Connection refused

It also checks whether all servers return same address. You can skip this check by passing --no-check argument.

$ stun-test --tcp stunserver.stunprotocol.org:3478 false.resolver
244.13.30.107:28674
ERROR While resolving {server=false.resolver}: {received=0.0.0.0:0}: Previously resolved addresses do not match
Establishing direct connection over the internet

NAT traversal procedure described in this paper.

  • Create and bind listen and connection sockets to the same port (using SO_REUSEADDR and SO_REUSEPORT flags).
  • Lookup self external address and port.
  • Exchange external addresses with peer.
  • Try to connect to the peer and listen for connection simultaneously.