freenet-test-network
Reliable test network infrastructure for Freenet integration testing.
Problem
Testing Freenet requires spinning up multiple local peers, which has been unreliable and flaky. This crate provides a simple, reliable way to create test networks.
Quick Start
use TestNetwork;
use LazyLock;
// Shared network for all tests (starts once)
static NETWORK: = new;
async
Status
Alpha - Core functionality working, including remote SSH peer support for realistic NAT/firewall testing.
Diagnostics
When a network fails to reach the desired connectivity threshold the builder now:
- Prints the most recent log entries across all peers in chronological order
- Can optionally preserve each peer's data directory (including
peer.log, configs, and keys) for later inspection
Enable preservation with:
let network = builder
.gateways
.peers
.preserve_temp_dirs_on_failure
.build
.await?;
If startup fails, the preserved artifacts are placed under /tmp/freenet-test-network-<timestamp>/.
Remote Peer Support (SSH)
New in v0.2: Spawn peers on remote Linux machines via SSH for realistic NAT/firewall testing.
Why Remote Peers?
Testing on localhost (127.0.0.1) can't catch bugs related to:
- NAT traversal
- Address observation (e.g., issue #2087 - loopback address propagation)
- Real network latency and routing
- Firewall behavior
Quick Start
use ;
async
Setup Requirements
- SSH Access: Password-less SSH via key or agent
- Remote Machine: Linux with SSH server (OpenSSH recommended)
- Binary Deployment: Freenet binary is automatically uploaded via SCP
- Ports: Remote peer will bind to OS-allocated ports (tests default port selection)
Configuration Options
let remote = new
.user // SSH username (default: current user)
.port // SSH port (default: 22)
.identity_file // SSH private key
.freenet_binary // Pre-installed binary path (optional)
.work_dir; // Working directory (default: /tmp/freenet-test-network)
Advanced: Multiple Remote Machines
let remote1 = new;
let remote2 = new;
let network = builder
.gateways
.peers
.peer_location
.peer_location
// peer 0 and gateway remain local
.build
.await?;
Distribute Across Remotes
Round-robin distribution across multiple machines:
let machines = vec!;
let network = builder
.gateways
.peers
.distribute_across_remotes // Alternates peers across machines
.build
.await?;
How It Works
- Binary Deployment: Local freenet binary is uploaded to remote machine via SCP
- Process Spawning: Peer started via
nohupover SSH, PID captured - Address Discovery: Remote peer's public IP is auto-detected
- Gateway Keys: Gateway public keys are uploaded to remote peers
- Log Collection: Logs are downloaded via SCP on demand
- Cleanup: Remote processes are killed via SSH on Drop
Limitations
- GitHub Actions: Outbound SSH likely blocked, use for local testing
- Platform: Remote machines must be Linux (SSH + standard utilities)
- Network: Remote machines must be reachable from test runner
Example
See examples/remote_peer.rs for a complete example.
TODO
- Implement proper connectivity detection (fix FIXME from fdev)
- Add WebSocket connection helpers
- Add integration tests
- Optimize startup time
- Add remote peer health monitoring
- Support custom SSH connection pooling
License
LGPL-3.0-only