Files
btest-rs/README.md
Siavash Sameni a28fc1dc08
All checks were successful
CI / test (push) Successful in 1m25s
Build & Release / release (push) Successful in 3m0s
v0.5.0: IPv6 off by default, mark as experimental
IPv6 listener now requires explicit --listen6 flag (disabled by default).
TCP over IPv6 works fully. UDP over IPv6 has macOS kernel limitations
(ENOBUFS on send_to). On Linux, IPv6 UDP works fine.

Usage:
  btest -s                    # IPv4 only (default)
  btest -s --listen6          # IPv4 + IPv6 on ::
  btest -s --listen6 ::1      # IPv4 + IPv6 on specific address

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 20:54:53 +04:00

175 lines
5.1 KiB
Markdown

# btest-rs
A Rust reimplementation of the [MikroTik Bandwidth Test (btest)](https://wiki.mikrotik.com/wiki/Manual:Tools/Bandwidth_Test) 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](https://github.com/samm-git/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** - `scp` one 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
```bash
# 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
```bash
cargo install --path .
```
### Docker
```bash
docker compose up -d # Server on port 2000
```
### systemd service
```bash
# 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.
```bash
# 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.
```bash
# 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
```bash
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](btest-opensource/README.md) for wire-format details.
## Authentication
Both MD5 (legacy) and EC-SRP5 (RouterOS >= 6.43) authentication are supported:
```bash
# 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
- **IPv6 support is experimental** (`--listen6`). TCP over IPv6 works fully. UDP over IPv6 has issues on macOS due to kernel ENOBUFS limitations with `send_to()`. On Linux, IPv6 UDP works fine. IPv6 is disabled by default.
- **Multi-connection UDP** is supported. MikroTik's multi-connection mode sends from multiple source ports which are all accepted by the server.
## Testing
```bash
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](https://github.com/samm-git/btest-opensource)** by [Alex Samorukov](https://github.com/samm-git) — Original C implementation and protocol reverse-engineering. Licensed under MIT.
- **[Margin Research](https://github.com/MarginResearch/mikrotik_authentication)** — 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](LICENSE).
This project is derived from [btest-opensource](https://github.com/samm-git/btest-opensource) (MIT License, Copyright 2016 Alex Samorukov). The original license and copyright notice are preserved as required.