Add client syslog events, fix client UDP TX error threshold
All checks were successful
CI / test (push) Successful in 1m26s
All checks were successful
CI / test (push) Successful in 1m26s
- Client mode now emits TEST_START and TEST_END syslog events - Client UDP TX threshold raised from 1000 to 50000 with adaptive backoff (matching server behavior) — prevents premature TX death on macOS - Updated all docs (README, user-guide, architecture, protocol, docker) - Added results.csv to gitignore Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
178
README.md
178
README.md
@@ -1,20 +1,22 @@
|
||||
# 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.
|
||||
A Rust reimplementation of the [MikroTik Bandwidth Test (btest)](https://wiki.mikrotik.com/wiki/Manual:Tools/Bandwidth_Test) protocol. Both server and client modes, fully compatible with MikroTik RouterOS devices.
|
||||
|
||||
## Based on
|
||||
## Features
|
||||
|
||||
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.
|
||||
- **Full protocol support** -- TCP and UDP data transfer, IPv4 and IPv6
|
||||
- **EC-SRP5 authentication** -- modern RouterOS >= 6.43 Curve25519-based auth (server and client)
|
||||
- **MD5 authentication** -- legacy RouterOS < 6.43 challenge-response auth
|
||||
- **Multi-connection support** -- handles MikroTik's multi-connection UDP mode
|
||||
- **Bidirectional testing** -- simultaneous upload and download
|
||||
- **Syslog logging** -- send structured events (auth, test start/end) to a remote syslog server
|
||||
- **CSV output** -- append machine-readable test results to a CSV file
|
||||
- **Timed tests** -- `--duration` flag to automatically stop after N seconds
|
||||
- **Quiet mode** -- suppress terminal output for scripted/automated use
|
||||
- **NAT traversal** -- probe packet to open firewall holes for UDP receive
|
||||
- **Single static binary** -- ~2 MB, zero runtime dependencies (musl build)
|
||||
- **Cross-platform** -- macOS, Linux (x86_64, ARM64), Docker
|
||||
- **Async I/O** -- tokio-based, handles many concurrent connections efficiently
|
||||
|
||||
## Performance
|
||||
|
||||
@@ -29,53 +31,65 @@ Tested over WiFi 6E (MikroTik RouterOS <-> macOS):
|
||||
| Client TCP bidirectional | TCP | **264/264 Mbps** |
|
||||
| Server bidirectional | UDP | **280/393 Mbps** |
|
||||
|
||||
On wired gigabit links, expect line-rate performance in both TCP and UDP modes.
|
||||
|
||||
## 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 .
|
||||
```
|
||||
|
||||
### Pre-built binary (Linux x86_64)
|
||||
|
||||
```bash
|
||||
# Cross-compile from macOS (requires Docker)
|
||||
scripts/build-linux.sh
|
||||
|
||||
# Copy to server
|
||||
scp dist/btest root@yourserver:/usr/local/bin/btest
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
```bash
|
||||
docker compose up -d # Server on port 2000
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
See [docs/docker.md](docs/docker.md) for full Docker and deployment options.
|
||||
|
||||
### systemd service
|
||||
|
||||
```bash
|
||||
# On the target Linux server:
|
||||
sudo ./scripts/install-service.sh
|
||||
sudo ./scripts/install-service.sh --auth-user admin --auth-pass secret
|
||||
sudo ./scripts/install-service.sh --auth-user admin --auth-pass secret --port 2000
|
||||
```
|
||||
|
||||
## Usage
|
||||
The installer creates a dedicated `btest` system user, installs a hardened systemd unit, and enables the service.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Server mode
|
||||
|
||||
MikroTik devices connect to this server to run bandwidth tests.
|
||||
|
||||
```bash
|
||||
# Basic server (no auth)
|
||||
# No authentication
|
||||
btest -s
|
||||
|
||||
# With authentication
|
||||
# MD5 authentication (legacy RouterOS)
|
||||
btest -s -a admin -p password
|
||||
|
||||
# Custom port with verbose logging
|
||||
btest -s -P 2000 -v
|
||||
# EC-SRP5 authentication (RouterOS >= 6.43)
|
||||
btest -s -a admin -p password --ecsrp5
|
||||
|
||||
# Custom port, verbose logging
|
||||
btest -s -P 3000 -v
|
||||
|
||||
# With syslog and CSV logging
|
||||
btest -s -a admin -p password --syslog 192.168.1.1:514 --csv /var/log/btest.csv
|
||||
```
|
||||
|
||||
### Client mode
|
||||
@@ -89,24 +103,62 @@ btest -c 192.168.88.1 -r
|
||||
# TCP upload test
|
||||
btest -c 192.168.88.1 -t
|
||||
|
||||
# Bidirectional
|
||||
# Bidirectional TCP
|
||||
btest -c 192.168.88.1 -t -r
|
||||
|
||||
# UDP with bandwidth limit
|
||||
# UDP download 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
|
||||
|
||||
# Timed test (30 seconds), results to CSV
|
||||
btest -c 192.168.88.1 -r -d 30 --csv results.csv
|
||||
|
||||
# Quiet mode (no terminal output)
|
||||
btest -c 192.168.88.1 -r -d 10 --csv results.csv -q
|
||||
|
||||
# UDP through NAT
|
||||
btest -c 192.168.88.1 -r -u -n
|
||||
```
|
||||
|
||||
### Debug logging
|
||||
|
||||
```bash
|
||||
btest -s -v # info + debug
|
||||
btest -s -vv # info + debug + trace (hex dumps of status exchange)
|
||||
btest -s -v # debug messages
|
||||
btest -s -vv # trace messages (hex dumps of status exchange)
|
||||
btest -s -vvv # maximum verbosity
|
||||
```
|
||||
|
||||
## MikroTik Setup
|
||||
## CLI Reference
|
||||
|
||||
```
|
||||
Usage: btest [OPTIONS]
|
||||
|
||||
Options:
|
||||
-s, --server Run in server mode
|
||||
-c, --client <HOST> Run in client mode, connect to HOST
|
||||
-t, --transmit Client transmits data (upload test)
|
||||
-r, --receive Client receives data (download test)
|
||||
-u, --udp Use UDP instead of TCP
|
||||
-b, --bandwidth <BW> Target bandwidth limit (e.g., 100M, 1G, 500K)
|
||||
-P, --port <PORT> Listen/connect port [default: 2000]
|
||||
--listen <ADDR> IPv4 listen address [default: 0.0.0.0] (use "none" to disable)
|
||||
--listen6 [<ADDR>] Enable IPv6 listener [default: ::] (experimental)
|
||||
-a, --authuser <USER> Authentication username
|
||||
-p, --authpass <PASS> Authentication password
|
||||
--ecsrp5 Use EC-SRP5 authentication (RouterOS >= 6.43)
|
||||
-n, --nat NAT traversal mode (send UDP probe packet)
|
||||
-d, --duration <SECS> Test duration in seconds (client mode, 0=unlimited) [default: 0]
|
||||
--csv <FILE> Output results to CSV file (appends if file exists)
|
||||
-q, --quiet Suppress terminal output (use with --csv)
|
||||
--syslog <HOST:PORT> Send logs to remote syslog server (UDP, RFC 3164)
|
||||
-v, --verbose Increase log verbosity (-v, -vv, -vvv)
|
||||
-h, --help Show help
|
||||
-V, --version Show version
|
||||
```
|
||||
|
||||
## MikroTik Configuration
|
||||
|
||||
### Enable btest server on MikroTik (for client mode)
|
||||
|
||||
@@ -116,41 +168,49 @@ btest -s -vv # info + debug + trace (hex dumps of status exchange)
|
||||
|
||||
### 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
|
||||
/tool/bandwidth-test address=<server-ip> direction=both protocol=udp \
|
||||
user=admin password=password
|
||||
```
|
||||
|
||||
## 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)
|
||||
|
||||
- **TCP port 2000** for control (handshake, authentication, status exchange)
|
||||
- **UDP ports 2001+** for data transfer (server side)
|
||||
- **UDP ports 2257+** for data transfer (client side, offset +256)
|
||||
- **MD5 double-hash challenge-response** authentication (RouterOS < 6.43)
|
||||
- **EC-SRP5 Curve25519 Weierstrass** 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.
|
||||
See [docs/protocol.md](docs/protocol.md) for the full wire-format specification.
|
||||
|
||||
## Authentication
|
||||
|
||||
Both MD5 (legacy) and EC-SRP5 (RouterOS >= 6.43) authentication are supported:
|
||||
Both legacy and modern MikroTik authentication schemes are supported:
|
||||
|
||||
```bash
|
||||
# Server with MD5 auth (legacy clients)
|
||||
btest -s -a admin -p password
|
||||
| Scheme | RouterOS Version | Flag |
|
||||
|--------|-----------------|------|
|
||||
| None | Any | (no flags) |
|
||||
| MD5 challenge-response | < 6.43 | `-a USER -p PASS` |
|
||||
| EC-SRP5 (Curve25519) | >= 6.43 | `-a USER -p PASS --ecsrp5` |
|
||||
|
||||
# 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
|
||||
```
|
||||
In server mode, `--ecsrp5` advertises EC-SRP5 to connecting clients. Without it, MD5 is advertised. In client mode, the authentication type is auto-detected from the server's response.
|
||||
|
||||
## 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.
|
||||
- **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 correctly.
|
||||
- **Multi-connection UDP** is supported. MikroTik's multi-connection mode sends from multiple source ports, all accepted by the server.
|
||||
|
||||
## Documentation
|
||||
|
||||
- [User Guide](docs/user-guide.md) -- complete CLI reference with examples for every mode
|
||||
- [Architecture](docs/architecture.md) -- module structure, threading model, design decisions
|
||||
- [Protocol Specification](docs/protocol.md) -- wire format, authentication, status exchange
|
||||
- [Docker & Deployment](docs/docker.md) -- Docker, Docker Compose, systemd, firewall rules
|
||||
- [EC-SRP5 Research](docs/ecsrp5-research.md) -- reverse-engineering notes and cryptographic details
|
||||
- [Man Page](docs/man/btest.1) -- Unix manual page (install to `/usr/share/man/man1/`)
|
||||
|
||||
## Testing
|
||||
|
||||
@@ -163,12 +223,12 @@ 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.
|
||||
- **[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).
|
||||
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.
|
||||
This project is derived from [btest-opensource](https://github.com/samm-git/btest-opensource) (MIT License, Copyright 2016 Alex Samorukov). The EC-SRP5 implementation is based on research by [Margin Research](https://github.com/MarginResearch/mikrotik_authentication) (Apache License 2.0). Original license and copyright notices are preserved as required.
|
||||
|
||||
Reference in New Issue
Block a user