NAT Traversal - possible ideas and solutions

Check out hyperswarms-dht

The Hyperswarms DHT uses a series of holepunching techniques to establish direct connections between peers, even if they’re located on home networks with tricky NATs.


They also provide relaying options when NAT traversal “holepunching” is not possible:

Hyperswarm’s holepunching will fail if both the client peer and the server peer are on randomizing NATs, in which case the connection must be relayed through a third peer. Hyperswarm does not do any relaying by default.

A search before posting shows @happybeing first mentioning this project here.


Hmm - what became of that experiment, I wonder @SmoothOperatorGR @Southside ?


IIRC - we chatted over a keet connection . It JustWorked and I meant to look at it some more - and then forgot all about it.

It think it should be looked at harder by folk that have deeper knowledge of lower level networking than me TBH.

I’ll reinstall it and have another play. Did i ever uninstall it?


Great unanswered questions of our times.

1 Like

the answer seems to be - not completely…

willie@gagarin:~/projects/maidsafe/Gooey$ locate keet

Download the AppImage at

and here is an invitation to the safekeet room

or use the QR code


And all that was left was an image. Not having a go in any way, but it always bothers me that potentially great ideas die by the wayside through lack of attention, follow up, support, promotion or whatever. Wheels constantly being reinvented.

1 Like

Not sure if Im getting you here…

Keet seems to be under active development if a quick squint at their discord is anything to go by

If you mean I/we/Maidsafe dropped the ball by not following up on it - well yeah I could have made more noise about it - got mentioned in the forum and nobody picked up on it until just now…

thank you @krnelson

Hey @bochaco, @qi_ma - does this keet intersect appropriately with your work?


Well keet appears to just pretty much work.
Searched Keet on the Playstore and put it on my Samsung, made a profile - slight faffing to get that long punch URL onto the phone but after that it worked fine.

So someone else please have a go at this and see what you think.

I have not looked at video calling yet cos my webcam stopped working after a kernel upgrade a while back.


Keet by HolePunch JustWorks as South said! tried it now as well.

maybe maidsafe should contact them? if its really p2p and it works it should be applicable in safe network!


It looks great but I feel this is all post stable network for us. Right now, we have so many balls in the air that this would be a large distraction from the core protocol we need to get running.

Great to have folks looking though, it helps everyone a lot.


Thats exactly what I expected you to say.
Its up to the community to poke at this and see what we can rip off for ourselves err err collaborate.


In case useful… Fuchsia’s start-unsecure-internet

I tried to spin by Google’s Fuchsia environment - I do not recommend it!!.. it takes hours to build nothing useful.

but there is a file there in the setup, that switches on port-forwarding, in a way I’ve not seen having tried safe node setup previously
[don’t use this unless you know what it is]:: sudo sysctl -w net.ipv4.ip_forward=1

and I was surprised that the port-forwarding was not already on.

Perhaps that is nothing and I wonder the routers were more of an issue anyway??

So, unclear what Google is doing but for those who can parse this kind of code, this is what fuchsia is requiring… along with Google Account and dob which I wonder is all a bit intrusive and unnecessary, where other build types are just local.

expand for info only:: fuchsia start-unsecure-internet
## FOR INFO ONLY - do not run this

# Copyright 2021 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# This is an upscript to use with qemu. It creates a bridge device that
# connects to the qemu network interfaces and sets up network forwarding.
# The emulator is exposed to the internet, and there is no security
# implemented, so should be used with care.
# Example usage with the Fuchsia emulator:
# The -I can be any device name, this script creates br${INTERFACE}.
# To use this script with `ffx emu`, configure this file to be
# the upscript by running:
# ffx config set emu.upscript $FUCHSIA_ROOT/scripts/
# This script is designed to be invoked from qemu with an interface argument.
# It can also be run directly for testing as:
# scripts/ <interface>
# If a --cleanup argument is provided instead of <interface>, this
# script will remove the previously created bridge device.

usage() {
  echo "Usage: $(basename "$0") <interface>"
  echo "  [--cleanup]"
  echo "    Remove previously created bridge device and stop"
  echo "  <interface>"
  echo "    Interface name typically 'qemu'"

# Check that we do not run this script in unsupported environments
if [[ "$(lsb_release --release --short)" == "rodete" ]]; then
  echo "This script cannot be run on rodete"
  exit 1
if [[ "$(hostname --fqdn)" == *"" ]]; then
  echo "This script cannot be run on *"
  exit 1

if [[ "$1" == "--cleanup" ]]; then
if [[ $1 == -* ]]; then
  echo "Unknown argument provided"
  exit 1
if [[ "$2" != "" ]]; then
  echo "Unexpected arguments provided"
  exit 1

if [[ "${INTERFACE}" == "" ]]; then
  echo "No network interface name provided by qemu -u"
  exit 1

# Enable error checking for all commands
err_print() {
  echo "Error at $1"
  stty sane
trap 'err_print $0:$LINENO' ERR
set -eu

# Show every command being executed
set -x

# qemu has already brought up ${INTERFACE}, but delete any previous ${BRIDGE} to start from a known state.
# If any other interface is using the address, everything will fail silently.
sudo ip link delete "${BRIDGE}" || echo "No existing bridge ${BRIDGE} to delete"
sudo iptables -D POSTROUTING -t nat -s ! -d -j MASQUERADE || echo "No existing POSTROUTING nat rule to delete"
for delbridge in $(ip --oneline address show to "" | awk '{ print $2 }'); do
  sudo ip link delete "${delbridge}"

# Exit out if the purpose was just to clean up
if (( CLEANUP )); then
  exit 0

# Enable packet forwarding
sudo sysctl -w net.ipv4.ip_forward=1
CHECK="$(cat /proc/sys/net/ipv4/ip_forward)"
if [[ "${CHECK}" != "1" ]]; then
  echo "ERROR: Could not enable ip_forward"
  exit 1

# Create bridge with DHCP and default gateway.
sudo ip link add name "${BRIDGE}" type bridge
sudo ip addr add dev "${BRIDGE}"

# UFW blocks DHCP/BOOTP and bridge traffic, so open this up if installed
if (command -v ufw && grep -q "^ENABLED=yes" /etc/ufw/ufw.conf) >/dev/null 2>&1; then
  sudo ufw allow proto udp from to port 67,68 comment 'Fuchsia qemu DHCP'
  sudo ufw allow dns comment 'Fuchsia qemu DNS'
  sudo ufw allow proto udp from to port 67 comment 'Fuchsia qemu DHCP'
  sudo ufw allow proto udp from to port 68 comment 'Fuchsia qemu DHCP'
  sudo ufw route allow in on "${BRIDGE}" comment 'Fuchsia qemu bridge in'
  sudo ufw route allow out on "${BRIDGE}" comment 'Fuchsia qemu bridge out'

# Remove any previous dnsmasq attached to the IP range we use
# Searching for the ${BRIDGE} is another alternative, but it may be different
DNSMASQ_PID=$(ps -axww | grep dnsmasq | grep "\-\-dhcp-range=172\.16\.243\.2," | awk '{ print $1 }')
if [[ "${DNSMASQ_PID}" != "" ]]; then
  sudo kill "${DNSMASQ_PID}"

# I've noticed that --listen-interface= is needed in some situations previously, but doesn't seem to be needed here
sudo dnsmasq --interface="${BRIDGE}" --bind-interfaces --dhcp-range=, --except-interface=lo || { echo "Failed to start dnsmasq"; exit 1; }
sudo ip link set "${BRIDGE}" up

# Remove pre-existing addresses from the interface as they'll no longer be routable
sudo ip addr flush "${INTERFACE}"

# Add qemu to the bridge
sudo ip link set "${INTERFACE}" master "${BRIDGE}"

# NAT packets arriving to the bridge
sudo iptables -A POSTROUTING -t nat -s ! -d -j MASQUERADE

Wondering about this one: rathole.

A secure, stable and high-performance reverse proxy for NAT traversal, written in Rust

rathole, like frp and ngrok, can help to expose the service on the device behind the NAT to the Internet, via a server with a public IP.

The blurb says.

rathole can automatically determine to run in the server mode or the client mode, according to the content of the configuration file, if only one of [server] and [client] block is present, like the example in Quickstart.

But the [client] and [server] block can also be put in one file. Then on the server side, run rathole --server config.toml and on the client side, run rathole --client config.toml to explicitly tell rathole the running mode.

Also UDP/TLS support planned.

Not anticipating the team to jump on this right now. As @dirvine said, hole punching is one for after beta launch. But maybe one to keep an eye on.


Such a UDP proxy is a nice solution for anyone having trouble exposing their node by forwarding ports through their router. It does come with the complexity of running a server on a public machine somewhere, but that shouldn’t come at a big cost.


I was wondering whether something like this could be incorporated into node and client software allowing the initially contacted node to act as a temporary server for this purpose. Maybe that wouldn’t be possible with anonymity though?


Perhaps the foundation or other groups could support that ends - assuming this is the best method ultimately.

1 Like

This is similar to the existing design. All nodes can perform as a proxy server.

With encrypted comms (payload) all they can do is forward messages or not, but they cannot change messages in transit. More specifically

  • Our payloads are message medium agnostic (i.e. you can deliver the payload on a USB disk, we don’t care).
  • The network messages have src and dst in them, but that’s OK (it’e the biggest attack proxies can do is identify this, but so can internet service providers etc.)
  • The client can decide if his messages are getting though by querying via another proxy if any write was done or indeed by requesting adults sending data back signed the messages on the way back (proof of network get form “trusted” source)

So there is legs on this. It would work like this

  • On starting a node you publish your IP:port (you have to anyway)
  • On that port you also run the proxy service (QUIC has multiplexed streams so we only need to identify proxy/direct and handle them properly)

Clients can then use proxies to get messages to other clients if both clients can find the other proxy and so on.

However what we had is more like STUN Servers running on each node. This allows many nodes and clients to find their external address and also if it’s reachable. Unfortunately modern routers are rarely allowing full cone NAT and that process is not as powerful any more.

In addition the QUIC protocol has started to make moves towards p2p comms, so in time it should bust NAT devices too.

i.e. Lot of wheels turning, but as usual way too slowly for us