Critical Wormhole Tools - Secure network utilities using Magic Wormhole code-based addressing
Project description
Critical Wormhole Tools
Secure network utilities using Magic Wormhole code-based addressing
What is Critical Wormhole Tools?
Critical Wormhole Tools (cwt / wh) brings the power of Magic Wormhole code-based addressing to everyday network utilities. Instead of dealing with IP addresses, port forwarding, and firewall rules, simply share a human-readable code like 7-guitar-sunset and connect securely from anywhere in the world.
┌─────────────────┐ ┌─────────────────┐
│ Your Machine │ │ Remote Machine │
│ │ "7-guitar-sunset" │ │
│ wh ssh ───────┼──────────────────────────────┼─────── wh listen│
│ │ End-to-End Encrypted │ --ssh │
└─────────────────┘ NAT Traversal Built-in └─────────────────┘
Key Features
- No IP addresses - Use memorable codes like
7-guitar-sunset - Persistent addresses - WNS identities like
wh://laptop.wnsthat never change - No port forwarding - Works through NAT and firewalls automatically
- End-to-end encrypted - PAKE-based key agreement, no trusted third parties
- Cross-platform - Works on Linux, macOS, and Windows
- Familiar tools - Same interface as netcat, ssh, scp, sftp, curl, wget
Installation
Using pip (Recommended)
pip install critical-wormhole-tools
Using pipx (Isolated Environment)
pipx install critical-wormhole-tools
Using Homebrew (macOS/Linux)
brew tap bshuler/critical-wormhole
brew install critical-wormhole
Using Chocolatey (Windows)
choco install critical-wormhole-tools
From Source
git clone https://github.com/bshuler/critical-wormhole-tools.git
cd cwt
pip install -e ".[dev]"
Quick Start
1. Netcat (wh nc)
Machine A (Listen):
wh nc -l
# Output: Listening on code: 7-guitar-sunset
Machine B (Connect):
echo "Hello through the wormhole!" | wh nc 7-guitar-sunset
2. SSH (wh ssh)
Server (Listen):
wh listen --ssh
# Output: Listening on code: 3-castle-thunder
# SSH server ready
Client (Connect):
wh ssh 3-castle-thunder
# You're now in a shell on the remote machine!
3. File Transfer (wh scp)
Server:
wh listen --ssh
# Output: Listening on code: 5-river-mountain
Client - Download:
wh scp 5-river-mountain:/path/to/remote/file.txt ./local/
Client - Upload:
wh scp ./local/file.txt 5-river-mountain:/path/to/remote/
4. Interactive SFTP (wh sftp)
wh sftp 5-river-mountain
sftp> ls
sftp> get documents/report.pdf
sftp> put ./data.csv /home/user/
sftp> quit
5. HTTP Requests (wh curl)
Server (HTTP Proxy):
wh listen --http
# Output: Listening on code: 2-ocean-breeze
Client:
wh curl --code 2-ocean-breeze https://api.example.com/data
wh curl --code 2-ocean-breeze -X POST -d '{"key":"value"}' https://api.example.com/
6. File Download (wh wget)
wh wget --code 2-ocean-breeze https://example.com/large-file.zip
Wormhole Name Service (WNS)
Regular wormhole codes like 7-guitar-sunset are single-use—they're consumed when you connect. WNS provides persistent, self-certifying addresses that never change, even when the underlying wormhole code refreshes.
┌─────────────────┐ ┌─────────────────┐
│ Your Machine │ │ Remote Machine │
│ │ "wh://a7b3c9d2e1f4.wns" │ │
│ wh ssh ───────┼──────────────────────────────┼─────── wh serve │
│ │ Persistent Identity │ --ssh │
└─────────────────┘ Auto-refreshing Codes └─────────────────┘
How WNS Works
- Generate an identity - Creates an Ed25519 keypair; the address is derived from the public key
- Start a persistent server - Automatically generates and publishes ephemeral codes
- Clients look up the address - Discover the current code via DHT, verify the signature
- Connect using the code - Same PAKE security as regular wormhole connections
Creating an Identity
# Generate a new WNS identity
wh identity create
# Output: Created identity: wh://a7b3c9d2e1f4g5h6i7j8k9l0m1.wns
# Generate with a local name
wh identity create --name "my-server"
# List all identities
wh identity list
# Show details for an identity
wh identity show a7b3c9d2e1f4g5h6i7j8k9l0m1
# Export public key (for sharing)
wh identity export a7b3c9d2e1f4g5h6i7j8k9l0m1
Starting a Persistent Server
# Start SSH server with WNS identity
wh serve --ssh
# Output:
# Using identity: wh://a7b3c9d2e1f4g5h6i7j8k9l0m1.wns
# Publishing to DHT: 7-guitar-sunset
# [Client connected]
# [Client disconnected]
# Publishing to DHT: 3-castle-thunder ← New code, same address!
# With a specific identity
wh serve --ssh --identity a7b3c9d2e1f4g5h6i7j8k9l0m1
Connecting to a WNS Address
All client commands accept WNS addresses:
# SSH
wh ssh wh://a7b3c9d2e1f4g5h6i7j8k9l0m1.wns
# SCP
wh scp wh://a7b3c9d2e1f4g5h6i7j8k9l0m1.wns:/path/file ./local/
# SFTP
wh sftp wh://a7b3c9d2e1f4g5h6i7j8k9l0m1.wns
# With username
wh ssh admin@wh://a7b3c9d2e1f4g5h6i7j8k9l0m1.wns
Naming Your Addresses
WNS supports three types of human-readable names:
1. Local Aliases (Petnames)
SSH-config style aliases stored on your machine:
# Add an alias
wh alias add laptop wh://a7b3c9d2e1f4g5h6i7j8k9l0m1.wns
# Add with default username
wh alias add work-server wh://xyz789.wns --username admin
# Now use the alias instead of the full address
wh ssh laptop
wh scp laptop:/file ./
# List all aliases
wh alias list
# Remove an alias
wh alias remove laptop
2. Scoped Names (Publisher-Controlled)
Names controlled by the identity owner, namespaced to prevent collisions:
# Set a scoped name for your identity
wh identity set-name a7b3c9d2e1f4g5h6i7j8k9l0m1 laptop
# The server now advertises as:
# wh://laptop.a7b3c9d2e1f4g5h6i7j8k9l0m1.wns
# Clients can connect using either:
wh ssh wh://laptop.a7b3c9d2e1f4g5h6i7j8k9l0m1.wns
wh ssh wh://a7b3c9d2e1f4g5h6i7j8k9l0m1.wns
3. Global Names (First-Come-First-Served)
Short, memorable names registered in the DHT:
# Claim a global name (links to your identity)
wh identity claim-name my-laptop a7b3c9d2e1f4g5h6i7j8k9l0m1
# Now anyone can connect via:
wh ssh wh://my-laptop.wns
# List your claimed names
wh identity list-names
# Release a name
wh identity release-name my-laptop
Global Name Rules:
- First-come-first-served (no central authority)
- Claims expire after 7 days if not renewed
- Reserved names:
wh,wns,admin,root,localhost, etc. - Cannot start with a digit followed by a dash (avoids confusion with wormhole codes)
Name Resolution Order
When you connect, names are resolved in this order:
- Local aliases - Check
~/.wh/aliases.json - Global names - Look up in DHT (for
wh://name.wnsformat) - Scoped names - Parse
name.address.wnsformat - Full addresses - Use directly
Trust Model (TOFU)
WNS uses Trust-On-First-Use, similar to SSH:
# First connection - public key is saved
wh ssh wh://a7b3c9d2e1f4.wns
# Output: Adding a7b3c9d2e1f4 to known hosts (TOFU)
# Subsequent connections - key is verified
wh ssh wh://a7b3c9d2e1f4.wns
# If key changed: WARNING: Public key mismatch! Possible impersonation attack.
Known hosts are stored in ~/.wh/known_hosts/.
Commands Reference
Core Commands
| Command | Description | Example |
|---|---|---|
wh nc |
Netcat-style bidirectional pipe | wh nc 7-guitar-sunset |
wh nc -l |
Listen for incoming connections | wh nc -l |
wh listen |
Multi-purpose listener daemon | wh listen --ssh |
wh ssh |
SSH client over wormhole | wh ssh 3-castle-thunder |
wh scp |
Secure copy files | wh scp code:/remote ./local |
wh sftp |
Interactive SFTP session | wh sftp 3-castle-thunder |
wh curl |
HTTP requests through proxy | wh curl --code X http://... |
wh wget |
Download files via HTTP proxy | wh wget --code X http://... |
Network Tools
| Command | Description | Example |
|---|---|---|
wh ping |
Measure wormhole latency | wh ping 7-guitar-sunset |
wh ping -l |
Listen for ping requests | wh ping -l |
wh tunnel |
SSH-style port forwarding | wh tunnel -L 8080:localhost:80 CODE |
wh tunnel -l |
Accept tunnel connections | wh tunnel -l |
wh proxy |
SOCKS5 proxy client | wh proxy 7-guitar-sunset |
wh proxy -l |
SOCKS5 proxy server | wh proxy -l |
wh rsync |
Incremental file sync | wh rsync -r ./src CODE:./dest |
wh rsync -l |
Receive rsync files | wh rsync -l ./dest |
WNS Commands
| Command | Description | Example |
|---|---|---|
wh identity create |
Generate new WNS identity | wh identity create --name server |
wh identity list |
List all identities | wh identity list |
wh identity show |
Show identity details | wh identity show abc123 |
wh identity export |
Export public key | wh identity export abc123 |
wh identity delete |
Delete an identity | wh identity delete abc123 |
wh identity set-name |
Set scoped name | wh identity set-name abc123 laptop |
wh identity claim-name |
Claim global name | wh identity claim-name my-laptop abc123 |
wh identity list-names |
List claimed names | wh identity list-names |
wh identity release-name |
Release global name | wh identity release-name my-laptop |
wh serve |
Persistent server with identity | wh serve --ssh |
wh alias add |
Add local alias | wh alias add laptop wh://abc.wns |
wh alias remove |
Remove alias | wh alias remove laptop |
wh alias list |
List all aliases | wh alias list |
wh alias resolve |
Resolve alias to address | wh alias resolve laptop |
How It Works
Critical Wormhole Tools uses Magic Wormhole's Dilation protocol:
- Code Exchange: Both parties enter the same code (e.g.,
7-guitar-sunset) - PAKE Handshake: Password-Authenticated Key Exchange establishes shared secrets
- Direct Connection: Attempts direct P2P connection with NAT traversal
- Relay Fallback: If direct fails, uses relay server (data still encrypted)
- Streaming: Dilated wormhole provides reliable, ordered, bidirectional streams
┌────────┐ ┌─────────────┐ ┌────────┐
│ Client │◄───────►│ Mailbox │◄───────►│ Server │
│ │ Code │ Server │ Code │ │
└───┬────┘ └─────────────┘ └────┬───┘
│ │
│ PAKE Key Exchange │
│◄─────────────────────────────────────────►│
│ │
│ Direct P2P (if possible) │
│◄═════════════════════════════════════════►│
│ or via Transit Relay │
│ (still E2E encrypted) │
└───────────────────────────────────────────┘
Security
- PAKE (SPAKE2): No passwords transmitted, even to relay servers
- NaCl encryption: Industry-standard cryptographic primitives
- Forward secrecy: Each session uses unique keys
- No account required: Anonymous, decentralized by design
- Verifier display: Optional visual verification of connection
Use Cases
Remote Access Without VPN
Access your home server from anywhere without setting up port forwarding or dynamic DNS.
Quick File Sharing
Share files between machines without uploading to cloud services.
Pair Programming
Give a colleague SSH access to your development machine temporarily.
IoT Device Access
Connect to devices behind carrier-grade NAT.
Secure API Testing
Make HTTP requests to internal APIs through a trusted proxy.
Configuration
Environment Variables
| Variable | Description | Default |
|---|---|---|
WH_RELAY |
Mailbox relay URL | ws://relay.magic-wormhole.io:4000/v1 |
WH_TRANSIT |
Transit relay | tcp:transit.magic-wormhole.io:4001 |
WH_SSH_PASSWORD |
SSH password (avoid prompts) | - |
Custom Relay
For privacy or performance, run your own relay:
# Use custom relay
wh --relay ws://my-relay.example.com:4000/v1 nc -l
Data Directory
WNS stores data in ~/.wh/:
~/.wh/
├── identity/ # WNS identities (keypairs)
│ └── <address>/
│ ├── private.key
│ └── public.key
├── known_hosts/ # Cached public keys (TOFU)
│ └── <address>.json
├── advertise/ # Published advertisements
│ └── <address>.json
├── names/ # Claimed global names
│ └── <name>.json
└── aliases.json # Local alias mappings
Development
Setup
git clone https://github.com/bshuler/critical-wormhole-tools.git
cd cwt
pip install -e ".[dev]"
Run Tests
# All tests
pytest
# Unit tests only (fast)
pytest tests/unit
# With coverage
pytest --cov=wh --cov-report=html
Code Quality
# Linting
ruff check src tests
# Type checking
mypy src
Roadmap
- Wormhole Name Service (WNS): Persistent addresses with DHT discovery
- Local Aliases: SSH-config style petnames for addresses
- Global Names: First-come-first-served name registry
- wh ping: Network diagnostics through wormhole
- wh tunnel: SSH-style port forwarding
- wh proxy: SOCKS5 proxy through wormhole
- wh rsync: Efficient file synchronization
- Browser Extension: Browse wormhole-hosted sites in Chrome/Firefox
- Web Server Integration: Apache/Nginx/HAProxy wormhole modules
See ROADMAP.md for detailed plans.
Contributing
Contributions are welcome! Please read our Contributing Guide first.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing) - Open a Pull Request
License
MIT License - see LICENSE for details.
Acknowledgments
- Magic Wormhole - The amazing protocol this is built on
- AsyncSSH - SSH implementation
- Twisted - Async networking framework
Connect securely. Share easily. No IP addresses required.
GitHub • PyPI • Issues • Discussions
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file critical_wormhole_tools-0.3.0.tar.gz.
File metadata
- Download URL: critical_wormhole_tools-0.3.0.tar.gz
- Upload date:
- Size: 75.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f97edd9fde3fa5b32835de1ff4792c7bb34f9c508688216ac5d57a94fd0d4e68
|
|
| MD5 |
30fcc4600a6c8e6b936ba697f166c1d0
|
|
| BLAKE2b-256 |
7fb33ea332a58b7ba62c969987847bcf842e672b9b0cb5d5dcac774f05e8ac10
|
Provenance
The following attestation bundles were made for critical_wormhole_tools-0.3.0.tar.gz:
Publisher:
publish.yml on bshuler/critical-wormhole-tools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
critical_wormhole_tools-0.3.0.tar.gz -
Subject digest:
f97edd9fde3fa5b32835de1ff4792c7bb34f9c508688216ac5d57a94fd0d4e68 - Sigstore transparency entry: 801426295
- Sigstore integration time:
-
Permalink:
bshuler/critical-wormhole-tools@2112da4b78b89f30c435d71250c0bb43b66d313e -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/bshuler
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2112da4b78b89f30c435d71250c0bb43b66d313e -
Trigger Event:
release
-
Statement type:
File details
Details for the file critical_wormhole_tools-0.3.0-py3-none-any.whl.
File metadata
- Download URL: critical_wormhole_tools-0.3.0-py3-none-any.whl
- Upload date:
- Size: 91.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c2fc6fbd5b70fcb3e5498dc3e61e6e6190194729b5186c116e78c8be5386bd9e
|
|
| MD5 |
4ec7d2c4558b44a2acbba5e5b5289ea6
|
|
| BLAKE2b-256 |
13bca74850af5567736000de99f3ca056ede98f047b59764261d39883cabe156
|
Provenance
The following attestation bundles were made for critical_wormhole_tools-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on bshuler/critical-wormhole-tools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
critical_wormhole_tools-0.3.0-py3-none-any.whl -
Subject digest:
c2fc6fbd5b70fcb3e5498dc3e61e6e6190194729b5186c116e78c8be5386bd9e - Sigstore transparency entry: 801426338
- Sigstore integration time:
-
Permalink:
bshuler/critical-wormhole-tools@2112da4b78b89f30c435d71250c0bb43b66d313e -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/bshuler
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2112da4b78b89f30c435d71250c0bb43b66d313e -
Trigger Event:
release
-
Statement type: