In BOTH direction, the TX loop now injects 12-byte status messages every 1 second between data packets, reporting rx_bytes to the client. Multi-connection mode also updated with same logic for all 3 cases: - TX only: pure data - RX only: status sender on writer - BOTH: TX data + interleaved status messages Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
btest-rs
A Rust reimplementation of the MikroTik Bandwidth Test (btest) protocol. Both server and client modes, compatible with MikroTik RouterOS devices.
Based on
This project is a clean-room Rust reimplementation based on the protocol reverse-engineering work done by Alex Samorukov in btest-opensource. The original C implementation and protocol documentation were invaluable in making this project possible. Full credit to Alex and all contributors to that project.
The original btest-opensource project is included as a git submodule for reference and protocol documentation.
Why Rust?
- Single static binary - 2 MB, zero dependencies, runs anywhere
- Cross-platform - macOS, Linux (x86_64, ARM64), Docker
- Async I/O - tokio-based, handles many concurrent connections efficiently
- Memory safe - no buffer overflows, no use-after-free, no data races
- Easy deployment -
scpone file, done. Or use the systemd installer.
Performance
Tested over WiFi 6E (MikroTik RouterOS <-> macOS):
| Mode | Protocol | Speed |
|---|---|---|
| Server RX (1 conn) | UDP | 1.05 Gbps |
| Client TCP download | TCP | 530 Mbps |
| Client TCP upload | TCP | 840 Mbps |
| Client UDP download | UDP | 433 Mbps |
| Client TCP bidirectional | TCP | 264/264 Mbps |
| Server bidirectional | UDP | 280/393 Mbps |
Installation
Pre-built binary
# Build for Linux x86_64 from macOS (requires Docker)
scripts/build-linux.sh
# Copy to server
scp dist/btest root@yourserver:/usr/local/bin/btest
From source
cargo install --path .
Docker
docker compose up -d # Server on port 2000
systemd service
# On the target Linux server:
sudo ./scripts/install-service.sh
sudo ./scripts/install-service.sh --auth-user admin --auth-pass secret
Usage
Server mode
MikroTik devices connect to this server to run bandwidth tests.
# Basic server (no auth)
btest -s
# With authentication
btest -s -a admin -p password
# Custom port with verbose logging
btest -s -P 2000 -v
Client mode
Connect to a MikroTik device's built-in btest server.
# TCP download test
btest -c 192.168.88.1 -r
# TCP upload test
btest -c 192.168.88.1 -t
# Bidirectional
btest -c 192.168.88.1 -t -r
# UDP with bandwidth limit
btest -c 192.168.88.1 -r -u -b 100M
# With authentication
btest -c 192.168.88.1 -r -a admin -p password
Debug logging
btest -s -v # info + debug
btest -s -vv # info + debug + trace (hex dumps of status exchange)
MikroTik Setup
Enable btest server on MikroTik (for client mode)
/tool/bandwidth-server set enabled=yes
Run btest from MikroTik (connecting to our server)
Important: Set Connection Count to 1 — multi-connection mode is not supported.
/tool/bandwidth-test address=<server-ip> direction=both protocol=udp user=admin password=password connection-count=1
Protocol
The MikroTik btest protocol uses:
- TCP port 2000 for control (handshake, auth, status exchange)
- UDP ports 2001+ for data transfer
- MD5 challenge-response authentication (RouterOS < 6.43)
- 1-second status interval with dynamic speed adjustment
See the original protocol documentation for wire-format details.
Authentication
Both MD5 (legacy) and EC-SRP5 (RouterOS >= 6.43) authentication are supported:
# Server with MD5 auth (legacy clients)
btest -s -a admin -p password
# Server with EC-SRP5 auth (modern RouterOS clients)
btest -s -a admin -p password --ecsrp5
# Client auto-detects auth type
btest -c 192.168.88.1 -r -a admin -p password
Known Limitations
- Multi-connection UDP is supported. MikroTik's multi-connection mode sends from multiple source ports which are all accepted by the server.
Testing
cargo test # Unit + integration tests
scripts/test-local.sh # Loopback self-test
scripts/test-mikrotik.sh <ip> # Test against MikroTik device
scripts/test-docker.sh # Docker container test
Credits
- btest-opensource by Alex Samorukov — Original C implementation and protocol reverse-engineering. Licensed under MIT.
- Margin Research — EC-SRP5 authentication reverse-engineering (Curve25519 Weierstrass, SRP key exchange). Licensed under Apache 2.0.
- MikroTik — Creator of the bandwidth test protocol and RouterOS.
License
MIT License - see LICENSE.
This project is derived from btest-opensource (MIT License, Copyright 2016 Alex Samorukov). The original license and copyright notice are preserved as required.