Siavash Sameni 0c14e6cf5b
All checks were successful
CI / test (push) Successful in 1m26s
Build & Release / release (push) Successful in 3m8s
Fix UDP TX-only status: report tx_bytes instead of rx_bytes
In TX-only mode (MikroTik receives), we sent rx_bytes=0 in status
because we weren't receiving anything. But MikroTik client needs
to see non-zero bytes in the status to know data is flowing.
Now report tx_bytes when in TX-only mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 19:39:28 +04:00
2026-03-31 18:28:48 +04:00

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 - 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

# 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.

Description
A high-performance MikroTik Bandwidth Test (btest) server and client written in Rust. Fully compatible with MikroTik RouterOS devices. Supports TCP/UDP, IPv4/IPv6, EC-SRP5 and MD5 authentication, multi-connection mode, syslog logging, CSV output, and CPU monitoring. Single static binary, zero dependencies.
Readme MIT 1.1 MiB
2026-04-18 07:51:46 +00:00
Languages
Rust 80.4%
Shell 13.5%
HTML 4.2%
Python 1.3%
Makefile 0.4%
Other 0.2%