Giter Club home page Giter Club logo

btest-opensource's Introduction

Mikrotik bandwith test protocol description

about

This is attempt to create opensource version of the btest tool. Currently it is possible to run bandwith-test only from another mikrotik devices or from the windows closed source client.

Protocol itsef seems to be not complicated, so it should not be easy to create 3rd party client for it.

Protocol description

There is no official protocol description, so everything was obtained using WireShark tool and RouterOS 6 running in the virtualbox, which was connecting to the real device. For now i am inspecting only TCP, later will try to do UDP if TCP works. Please keep in mind that this data is guessed on the captures, so possibly is not accurate or wrong.

> bserver: hello
01:00:00:00 
> client: Start test cmd, depending on the client settings:
01:01:01:00:00:80:00:00:00:00:00:00:00:00:00:00 (transmit)
01:01:00:00:00:80:00:00:00:00:00:00:00:00:00:00 (transmit, random data)
00:01:01:00:dc:05:00:00:00:00:00:00:00:00:00:00 (transmit, UDP)
01:02:01:00:00:80:00:00:00:00:00:00:00:00:00:00 (receive)
01:02:00:00:00:80:00:00:00:00:00:00:00:00:00:00 (receive, random data)
00:02:01:00:dc:05:00:00:00:00:00:00:00:00:00:00 (receive, UDP, remote-udp-tx-size: default (1500))
00:02:01:00:d0:07:00:00:00:00:00:00:00:00:00:00 (receive, UDP, remote-udp-tx-size: 2000)
00:02:01:00:00:fa:00:00:00:00:00:00:00:00:00:00 (receive, UDP, remote-udp-tx-size: 64000)
01:02:01:00:00:80:00:00:01:00:00:00:00:00:00:00 (receive, remote-tx-speed=1)
01:02:01:00:00:80:00:00:ff:ff:ff:ff:00:00:00:00 (receive, remote-tx-speed=4294967295)
01:02:01:00:00:80:00:00:00:00:00:00:01:00:00:00 (receive, local-tx-speed=1)
01:02:01:00:00:80:00:00:00:00:00:00:ff:ff:ff:ff (receive, local-tx-speed=4294967295)
01:02:01:0a:00:80:00:00:00:00:00:00:00:00:00:00 (receive, tcp-connection-count=10)
01:03:01:00:00:80:00:00:00:00:00:00:00:00:00:00 (both)
01:03:00:00:00:80:00:00:00:00:00:00:00:00:00:00 (both, random data)
00:03:01:00:dc:05:00:00:00:00:00:00:00:00:00:00 (both, UDP)
> bserver: Start test confirm (auth is disabled on server):
01:00:00:00 (tcp-connection-count=1 on a client)
01:bc:04:00 (tcp-connection-count>1 on a client)
> bserver: auth requested, with 16 challenge bytes (3 random packets provided)
02:00:00:00:90:67:3f:0f:5c:c7:4e:17:a0:e0:9e:1c:b9:ee:3b:0c
02:00:00:00:17:e7:ee:84:83:cc:15:53:e8:fa:9c:0d:ad:ac:b8:e1
02:00:00:00:ee:d1:19:b9:d3:f2:df:6d:04:46:da:25:55:44:49:81
> client: auth reply (3 random packets, userid test)
90:75:1f:b0:2a:f7:25:51:46:25:71:c3:16:ce:cc:2b:74:65:73:74:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
a0:1b:fa:27:78:55:08:71:93:09:70:86:15:30:84:ac:74:65:73:74:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
b4:f2:9e:06:5e:74:da:89:65:c9:be:94:4d:bf:8f:20:74:65:73:74:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
> bserver: packet data follows
00:00:00:00........
  1. Server always starts with "hello" (01:00:00:00) command after establishing TCP connection to port 2000. If UDP protocl is specified in the client TCP connection is still established.
  2. Client sends 16 bytes command started with 01 (TCP) or 00 (UDP) command to the server. Some of the bytes guess:
  • cmd[0]: protocol, 01: TCP, 00: UDP
  • cmd[1]: direction, 01 - transmit, 02 - receive, 03 - both
  • cmd[2]: use random data, 00 - use random, 01: use \00 character
  • cmd[3]: tcp-connection-count, 0 if tcp-connection-count=1, number if more
  • cmd[4:5]: remote-udp-tx-size (dc:05) on UDP, 00:80 on TCP, UINT16 - Little Endian
  • cmd[6:7]: client buffer size. Maximum value for TCP is 65535 (FF:FF).
  • cmd[8:11]: remote-tx-speed, 0: unlimimted, 1-4294967295: value, UINT32 - Little Endian
  • cmd[12:15]: local-tx-speed, 0: unlimimted, 1-4294967295: value, UINT32 - Little Endian
  1. If server authentication is disabled it sends 01:00:00:00 and starts to transmit/recieve data. If auth is enabled and btest server versions is < 6.43 server sends 20bytes reply started with 02:00:00:00 in the beginning and random bytes (challenge) in the [4:15] range. Customer sends back 48 bytes reply containing user name (unencrypted) and 16 bytes hash of the password with challenge. Hashing alghoritm is double md5, hashed by challenge, see "authentication" section. If btest server versions is >= 6.43 server sends 03:00:00:00 reply and new authentication method is used, based on the EC-SRP5. Exact implementation details are not yet known and method is not yet supported in the OSS software. See haakonnessjoen/MAC-Telnet#42 for the related discussion.
  2. If auth failed server sends back 00000000 (client shows "authentication failed"), if succeed - 01000000 packet and test is starting.
  3. If tcp-connection-count > 1 server should reply with 01:xx:xx:00 where xx seems to be some kind of authentification data to start other connections. This number is used in other threads.
  4. From time to time (~1 per second) server or client sends 12 bytes messages started with 07, e.g. 07:00:00:00:01:00:00:00:36:6e:03:00. Btest client relies on this information to show "transmit" speed. It is server-level statistic, where values are:
  • stat[0] is 07 (message id)
  • stat[4-7] number or time from start in seconds, sends one per second, UINT32 - Little Endian
  • stat[8-11] number of bytes transferred per sequence, UINT32 - Little Endian

Old authentication methoud

Sample of the challenge-response for the "test" password:

ad32d6f94d28161625f2f390bb895637
3c968565bc0314f281a6da1571cf7255

Hashing alghoritm was found with implementation of the testing server and help from the Chupaka on a Mikrotik forum. It is md5('password' + md5('password' + hash)). This is an example on the Perl language, which using challenge from the example and returns same hash:

use Digest::MD5 qw(md5 md5_hex);

my $salt='ad32d6f94d28161625f2f390bb895637';
my $pass='test';
print md5_hex($pass.md5($pass.pack( 'H*', $salt)))."\n";

Script should return 3c968565bc0314f281a6da1571cf7255 and its matching captured traffic.

btest-opensource's People

Contributors

divereigh avatar jplitza avatar kmoz000 avatar m0sia avatar samm-git avatar scream85 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

btest-opensource's Issues

Not compiling in CentOS

Hi, i am having problems compiling BTest in CentOS
Here is my output.

[root@localhost btest-opensource]# gcc -o btest *.c -lpthread
/tmp/ccL6QCDF.o: In function test_udp_tx': btest.c:(.text+0x1455): undefined reference to clock_gettime'
btest.c:(.text+0x15dc): undefined reference to clock_nanosleep' /tmp/ccL6QCDF.o: In function test_udp_rx':
btest.c:(.text+0x16f2): undefined reference to clock_gettime' /tmp/ccL6QCDF.o: In function test_udp':
btest.c:(.text+0x1b7f): undefined reference to clock_gettime' btest.c:(.text+0x1bba): undefined reference to clock_gettime'
btest.c:(.text+0x1e92): undefined reference to clock_gettime' /tmp/ccu5j117.o: In function itimer_start':
timing_mach.c:(.text+0x20e): undefined reference to clock_gettime' /tmp/ccu5j117.o: In function itimer_step':
timing_mach.c:(.text+0x25f): undefined reference to `clock_nanosleep'
collect2: ld returned 1 exit status

What is wrong?

Thanks

Have you finished this yet?

I see most commits are a very long time ago, did you ever get this finished? Did you get it working? Having a btest server running on a headless linux system would be awesome! Since for some reason MikroTik does not seem to want to actually make this... (Pretty stupid if you ask me)

Client command [6:7]

cmd[6:7] is a client buffer size. Maximum value for TCP is 65535 (FF:FF).
I'm currently writing a custom btest client and this value greatly affects single connection performance.

Flapping bitrates on 32-bit systems, possible overflow?

Hi, and thanks for taking the time to create this. Its saved me a bunch of time while working on some validation of a new homelab setup with a bunch of Mikrotik gear today!

While testing I ran into some weird behavior with bitrates greater than ~4.2 Gbps on a 32-bit arm7l system - a QNAP TS-431KX NAS running an Anapurna Labs AL214 quad Cortex-A15 @ 1.7 GHz CPU. However, I was able to work around this by manually setting the bandwidth to less than 4295M.

[~/btest-opensource] # ./btest -c 192.168.88.1 -t -b 4295M
Tx speed: 32704
Interval:  1:0
gettime:  13511:660314092
Remote: Seq: 2550136833, Rate: 1551.6Mb/s
Remote: Seq: 2399141890, Rate: 0.0kb/s
Remote: Seq: 2382364675, Rate: 0.0kb/s
Remote: Seq: 2399141892, Rate: 0.0kb/s
^C
[~/btest-opensource] # ./btest -c 192.168.88.1 -t -b 4294M
Tx speed: 4294000000
Interval:  0:16767
gettime:  13541:760491272
Remote: Seq: 2583691265, Rate: 4288.0Mb/s
Remote: Seq: 2684354562, Rate: 4291.9Mb/s
Remote: Seq: 2667577347, Rate: 4294.1Mb/s
Remote: Seq: 2684354564, Rate: 4294.2Mb/s
^C

Its been a long time since I've worked in C so I'm not sure I'll be able to cook up a proper PR for a fix (sorry!) but it feels like an overflow. I did take a few runs at a fix (tried moving a few things from 'lu' to 'llu', for instance) but had no success in the time I've got available today. Probably not a huge deal given that there can't be many 32-bit platforms with 5G/10G network support out there anyway.

At the very least I hope the workaround here is helpful for anyone else that's crazy enough to try using btest on a 10G-equipped 32-bit ARM platform. ๐Ÿ˜‚

p.s. - To get btest working with higher bitrates I had to change the hard-coded tx_size of 1500 to match my jumbo frame MTU of 9000 to avoid choking the tx system with packet generation overhead. At 1500 the QNAP system could do about Might be worth making that a command-line option but its easy enough to just edit btest.c and recompile I guess. :)

TCP test unsupported

I'm running btest -s on the server, and /tool bandwidth-test 192.0.2.1 protocol=tcp on RouterOS 6.45.8.

It connects successfully, in a packet trace I can see the client sending all the options, the server acknowleding with 01:00:00:00 - and then the client terminates the connection and prints

                status: test unsupported

A packet trace from a RouterOS bandwidth-server shows that it sends 01:XX:YY:00 instead, where XX:YY is somehow reused by the client in the newly established connections. Other than that, I was unable to see any difference.

Having a crack at UDP

Hi, been digging around with the bserver.pl code and decided to have a crack at UDP. I'm wondering if you have run into/got past a wierd issue. From what I can tell the UDP protocol is quite similar, however unlike TCP where the server just starts sending data down the existing connection, for UDP the server is supposed to respond with another 'hello' and then the server port number that it will send or receive the data on. This is from looking at the data traffic from a Mikrotik btest server.

However what is wierd is that the standard server then just starts sending UDP data back to the client to what appears to be just a random port around 2200. At no point from what I can see does the client tell the server what port to use. I am beginning to wonder if the only way to do this is to use pcap and filter on the source port.

Any ideas?

Damian

Unable to run btest against RouterOS 6.48

Hi, this was a great contribution however I couldn't get it to work:

  1. Installed on Ubuntu 20.04 using
    git clone https://github.com/samm-git/btest-opensource
    cd btest-opensource
    gcc -o btest *.c -lpthread

  2. ran: ./btest -s -a admin -p password

  3. On the router, ran:
    /tool bandwidth-test dur=5s dir=both user=admin pass=password prot=tcp addr=10.1.0.1
    status: test unsupported
    tx-current: 0bps
    tx-10-second-average: 0bps
    tx-total-average: 0bps
    rx-current: 0bps
    rx-10-second-average: 0bps
    rx-total-average: 0bps
    random-data: no
    direction: both
    connection-count: 20
    On the linux side, the output is:
    Running in server mode
    Listening
    Cmd buffer: 01030114008000000000000000000000
    proto=1
    direction=3
    random=1
    tcp_conn_count=20
    tx_size=32768
    client_buf_size=0
    remote_tx_speed=0
    local_tx_speed=0
    remoteIP=10.1.10.33
    Listening on TCP cmdsock
    Complete

  4. same results with no username/password on either end, and same results with dir=transmit or dir=receive

  5. Other direction: ran ./btest -c 10.1.10.33 -r -t -a admin -p password
    Remote did not return correct hello response
    Response: 03000000
    Same result with only -r or only -t

  6. Installed on a different Ubuntu 20.04 system and ran the server there (with user/password) and the client on the first Ubuntu system as: ./btest -c 10.1.13.248 -r -t -a admin -p password - that produced results as expected.
    The first time I tried with -r only I got a series of 0.00kbps. However running it later with -r -t and then -t and then -r, all three cases produced realistic bandwidths.

No traffic during the test

I am trying to test my LHG-LTE6 (RouterOS v6.46.4) against server build from latest sources (under Ubuntu 16.04.6 LTS with 'cc -o btest -pthread btest.c md5.c')

Server says
user@server:~/src/btest$ ./btest -s -u -b 0 -a btest -p btest
Running in server mode
Listening
Cmd buffer: 00030100e80300002c0100002c010000
proto=0
direction=3
random=1
tcp_conn_count=0
tx_size=1000
client_buf_size=2883584
remote_tx_speed=300
local_tx_speed=300
remoteIP=1.2.3.4
Tx speed: 300
Interval: 1:0
gettime: 1586199784:139478028
Local : Seq: 1, Rate: 0.0kb/s
Remote: Seq: 3825205249, Rate: 0.0kb/s
Local : Seq: 2, Rate: 0.0kb/s
Remote: Seq: 2852126722, Rate: 0.0kb/s
Local : Seq: 3, Rate: 0.0kb/s
Remote: Seq: 2231369731, Rate: 0.0kb/s
...
and so on, until client finishes testing

client says
[admin@MikroTik] > /tool bandwidth-test 4.3.2.1 duration=15s direction=both local-udp-tx-size=1000 protocol=udp remote-udp-tx-size=1000 user=btest password=btest local-tx-speed
=300 remote-tx-speed=300
status: done testing
duration: 15s
tx-current: 0bps
tx-10-second-average: 0bps
tx-total-average: 0bps
rx-current: 0bps
rx-10-second-average: 0bps
rx-total-average: 0bps
lost-packets: 0
random-data: no
direction: both
tx-size: 1000
rx-size: 1000
connection-count: 1
local-cpu-load: 8%

Could Mikrotik change something in testing protocols?

P.S. LHG has no fw (but I am not shure about LTE ISP), and ubuntu box was updated with 'ufw allow 2000' and 'ufw allow 2256'

Max 300 Mbps

Running btest for transmitting seems to max out at ~300 Mbps.

If I comment out this clock_nanosleep() call, it can get higher:

if (clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &nextPacketTime, NULL) < 0) {

Not yet sure why it doesn't work with that, though. Doesn't depend on the Tx Speed either.

Does not compile under osx

bash-3.2$ clang -Wall btest.c
btest.c:83:6: warning: unused variable 'flags' [-Wunused-variable]
        int flags, opt;
            ^
btest.c:215:7: warning: unused variable 'buffer' [-Wunused-variable]
        char buffer[1024];
             ^
btest.c:297:2: warning: '/*' within block comment [-Wcomment]
        /*loop while connection is live*/
        ^
btest.c:259:6: warning: unused variable 'i' [-Wunused-variable]
        int i;
            ^
btest.c:298:1: warning: control may reach end of non-void function [-Wreturn-type]
}
^
btest.c:362:28: warning: passing 'int *' to parameter of type 'unsigned int *' converts between pointers to integer types with different sign [-Wpointer-sign]
        unpackShortLE(&cmdStr[4], &cmd.tx_size);
                                  ^~~~~~~~~~~~
btest.c:324:55: note: passing argument to parameter 'pres' here
void unpackShortLE (unsigned char *buf, unsigned int *pres) {
                                                      ^
btest.c:365:28: warning: passing 'int *' to parameter of type 'unsigned int *' converts between pointers to integer types with different sign [-Wpointer-sign]
        unpackShortLE(&cmdStr[6], &cmd.client_buf_size);
                                  ^~~~~~~~~~~~~~~~~~~~
btest.c:324:55: note: passing argument to parameter 'pres' here
void unpackShortLE (unsigned char *buf, unsigned int *pres) {
                                                      ^
btest.c:353:6: warning: unused variable 'i' [-Wunused-variable]
        int i;
            ^
btest.c:460:2: error: unknown type name 'clockid_t'; did you mean 'clock_t'?
        clockid_t clock_id;
        ^~~~~~~~~
        clock_t
/usr/include/sys/_types/_clock_t.h:30:33: note: 'clock_t' declared here
typedef __darwin_clock_t        clock_t;
                                ^
btest.c:494:2: warning: implicit declaration of function 'clock_gettime' is invalid in C99 [-Wimplicit-function-declaration]
        clock_gettime(CLOCK_REALTIME, &nextPacketTime);
        ^
btest.c:494:16: error: use of undeclared identifier 'CLOCK_REALTIME'
        clock_gettime(CLOCK_REALTIME, &nextPacketTime);
                      ^
btest.c:514:7: warning: implicit declaration of function 'clock_nanosleep' is invalid in C99 [-Wimplicit-function-declaration]
                if (clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &nextPacketTime, NULL) < 0) {
                    ^
btest.c:514:23: error: use of undeclared identifier 'CLOCK_REALTIME'
                if (clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &nextPacketTime, NULL) < 0) {
                                    ^
btest.c:514:39: error: use of undeclared identifier 'TIMER_ABSTIME'
                if (clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &nextPacketTime, NULL) < 0) {
                                                    ^
btest.c:558:18: error: use of undeclared identifier 'CLOCK_REALTIME'
                        clock_gettime(CLOCK_REALTIME, &now);
                                      ^
btest.c:678:16: error: use of undeclared identifier 'CLOCK_REALTIME'
        clock_gettime(CLOCK_REALTIME, &nextStatusTime);
                      ^
btest.c:685:17: error: use of undeclared identifier 'CLOCK_REALTIME'
                clock_gettime(CLOCK_REALTIME, &now);
                              ^
btest.c:703:17: error: use of undeclared identifier 'CLOCK_REALTIME'
                clock_gettime(CLOCK_REALTIME, &now);
                              ^
btest.c:727:6: warning: unused variable 'ret' [-Wunused-variable]
        int ret;
            ^
btest.c:754:14: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
        while(nBytes=recv(cmdsock,buffer,1024,0)){
              ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
btest.c:754:14: note: place parentheses around the assignment to silence this warning
        while(nBytes=recv(cmdsock,buffer,1024,0)){
                    ^
              (                                 )
btest.c:754:14: note: use '==' to turn this assignment into an equality comparison
        while(nBytes=recv(cmdsock,buffer,1024,0)){
                    ^
                    ==
btest.c:743:12: warning: unused variable 'pth_rx' [-Wunused-variable]
        pthread_t pth_rx;
                  ^
13 warnings and 8 errors generated.

Doc update

Please update readme.md with instructions how to install and run server and client

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.