|
|
(9 intermediate revisions by one other user not shown) |
Line 1: |
Line 1: |
| The Bondix SANE client is the software that you install on your [[Client/Supported Devices|supported]] router, which establishes a connection to the [[Server|server]] using multiple WAN links. | | The Bondix SANE client is the software that you install on your router, which establishes a connection to the [[Server|server]] using multiple WAN links. The software itself is a linux userspace program, but installation packages for different routers are available, that take care of most of the configuration. |
|
| |
|
| For '''OpenWRT''' based routers, please check [[Client/OpenWRT|this page]].
| | This page covers the barebone linux application. Please check out the [[Teltonika]] page for installation & usage on these routers. |
|
| |
|
| = Installation = | | ==Configuration== |
| Log into your router via SSH and do the following:
| | Configuration is done using [https://www.json.org/ JSON] commands. These can either be sent via a raw TCP socket (localhost:5113), or written to a configuration file (in a json-array) that is parsed on start-up. |
| {| class="wikitable"
| |
| |-
| |
| | Create installation directory || <code>mkdir -p /opt/bondix
| |
| cd /opt/bondix</code>
| |
| |-
| |
| | Download installation package || <code>curl -o sane.tar.gz <DOWNLOAD-URL></code>
| |
| |-
| |
| | Extract package || <code>tar -xvzf sane.tar.gz</code>
| |
| |}
| |
|
| |
|
| You can verify that the correct version has been installed with the command
| | By default, SANE checks for the existence of a configuration file in its installation directory (e.g. <code>/opt/bondix/client/saneclient.json</code>) and at <code>/etc/saneclient.json</code>. If you want SANE to load a configuration from a different location, you can specify it using a command line parameter. |
| <code>/opt/bondix/client/saneclient --version</code> | |
|
| |
|
| If successful, it should print its version string.
| | ===Quick Start=== |
| | |
| = Configuration = | |
| Configuration is done using [https://www.json.org/ JSON] commands. These can either be sent via a raw TCP socket (localhost:5113), or written to a configuration file (in a json-array) that is parsed at start-up. This allows both a fixed configuration as well as adjustments during runtime without the need to restart the service. By default, SANE checks for the existence of a configuration file in its installation directory (e.g. <code>/opt/bondix/client/saneclient.json</code>) and at <code>/etc/saneclient.json</code>. If you want SANE to load a configuration from a different location, you can specify it using a command line parameter.
| |
| | |
| == Quick Start == | |
| This example provides the minimal necessities to get a tunnel up and running: | | This example provides the minimal necessities to get a tunnel up and running: |
| <nowiki>[ | | <nowiki>[ |
| {"action": "create", "target": "tunnel", "name": "TUNNELNAME", "password": "TUNNELPASSWORD"},
| | {"action": "create", "target": "tunnel", "name": "TUNNELNAME", "password": "TUNNELPASSWORD"}, |
| {"action": "add-server", "target": "tunnel", "host": "ENDPOINTSERVER", "port": "443"},
| | {"action": "add-server", "target": "tunnel", "host": "ENDPOINTSERVER", "port": "443"}, |
| {"action": "create-interfaces", "target": "tunnel", "interfaces": {
| | {"action": "create-interfaces", "target": "tunnel", "interfaces": { |
| "eth1": "mobileAggressive",
| | "eth1": "mobileAggressive", |
| "wwan0": "mobileAggressive",
| | "wwan0": "mobileAggressive", |
| "wwan1": "mobileAggressive"
| | "wwan1": "mobileAggressive" |
| }},
| | }}, |
| {"target": "tunnel", "action": "set-preset", "preset": "bonding"}
| | {"target": "tunnel", "action": "set-preset", "preset": "bonding"} |
| ] | | ] |
| </nowiki> | | </nowiki> |
|
| |
|
| For an example using SSL certificate authentication, go to [[Certificates]] | | ===Configuration Commands=== |
| | For a complete reference list of available commands, see [[Client Configuration]]. |
|
| |
|
| == Command Structure == | | ===Tunnel Configuration=== |
| A JSON command has the following structure:
| | Tunnels and channels have many configurable values, that are managed using [[Presets]]. |
| <code>{"target": "<module>", "action": "<command>", [...additional values...]}</code>, where <module> specifies the configuration submodule and <command> specifies what should be done.
| |
|
| |
|
| == System Commands == | | =Running= |
| {| class="wikitable"
| | The software can be run in the shell using <code>/opt/bondix/client/saneclient</code>, where it will run in the foreground. However, it is recommended to start the service automatically on startup, which can be different depending on the platform. |
| |-
| |
| | |
| |
| |
| === shutdown ===
| |
| Shuts down the client and terminates.
| |
| | style="width: 40%"|
| |
| <nowiki>{"target": "system",
| |
| "action": "shutdown"
| |
| }</nowiki>
| |
| |-
| |
| | |
| |
| |
| === set-log ===
| |
| Enables logging to file or changes output file.
| |
| {| class="wikitable"
| |
| |+ Parameters
| |
| |-
| |
| | file || The filename that the log should be written to. Required.
| |
| |-
| |
| | fileMode|| can be <code>append</code> or <code>overwrite</code>. Required.
| |
| |}
| |
| ||
| |
| <nowiki>{"target": "system",
| |
| "action": "set-log",
| |
| "file": "/var/log/saneclient.log",
| |
| "fileMode": "append"
| |
| }</nowiki>
| |
| |-
| |
|
| |
|
| |
| | ===Parameters=== |
| === set-webinterface === | |
| Enables the integrated webserver & debug webinterface.
| |
| {| class="wikitable" | | {| class="wikitable" |
| |+ Parameters
| |
| |- | | |- |
| | host || IP that the service should listen on. Required. | | |<code>--daemon</code>||Runs the software as a daemon. |
| |- | | |- |
| | port || TCP Port that the service should listen on. Required. | | |<code>--nopid</code>|| Does not attempt to create a pid-file at <code>/var/run/saneclient.pid</code> |
| |- | | |- |
| | allowConfig || En- or disables web configuration. Not required, enabled by default. | | |<code>--listflags</code>||Lists available feature flags |
| |- | | |- |
| | allowMonitor || En- or disables web monitor. Not required, enabled by default. | | |<code>--flags <FLAG1> <FLAG2>... </code>||Enables the specified flag(s). Multiple flags are separated using space. |
| |- | | |- |
| | configApiKey || The password required to access configuration & monitor. Not required, "123456" by default. | | |<code></path/to/filename.json></code>||JSON configuration file that should be used |
| |-
| |
| | webroot || Web root directory. Points to the "www" subdirectory in installation directory. Not required, changing not advised.
| |
| |}
| |
| ||
| |
| <nowiki>{"target": "system",
| |
| "action": "set-webinterface",
| |
| "host": "0.0.0.0",
| |
| "port": "80",
| |
| "allowConfig": false,
| |
| "allowMonitor": true,
| |
| "configApiKey": "123456",
| |
| "webroot": "/tmp/"
| |
| }</nowiki>
| |
| |} | | |} |
|
| |
|
| == Tunnel Commands == | | ===Feature Flags=== |
| {| class="wikitable"
| | Feature flags are switches that enable certain features that are otherwise unavailable. These features are usually experimental and should be used with caution. |
| |-
| |
| | |
| |
| |
| === create ===
| |
| Sets up basic tunnel configuration.
| |
| {| class="wikitable"
| |
| |+ Parameters
| |
| |-
| |
| | name || Tunnel Name. Required.
| |
| |-
| |
| | password || Password. Required.
| |
| |-
| |
| | server || Endpoint target IP. Optional.
| |
| |-
| |
| | interfaceName|| Desired name of the virtual tunnel network interface. Optional.
| |
| |-
| |
| | values || A JSON object containing configuration parameters for the tunnel.
| |
| |}
| |
| | style="width: 40%"|
| |
| <nowiki>{"target": "tunnel",
| |
| "action": "create",
| |
| "name": "MyTunnel",
| |
| "password: "1234",
| |
| "server": "10.0.0.1",
| |
| "interfaceName": "bndx0",
| |
| "values": {...}
| |
| }</nowiki>
| |
| |-
| |
| | |
| |
| |
| === add-server ===
| |
| Adds a endpoint server. If multiple servers are added, the client will cycle through
| |
| them until a connection has been established successfully.
| |
| {| class="wikitable"
| |
| |+ Parameters
| |
| |-
| |
| | host|| IP or host of the destination server. Required.
| |
| |-
| |
| | port || Port of the destination server. Optional (Default: "443").
| |
| |}
| |
| ||
| |
| <nowiki>{"target": "tunnel",
| |
| "action": "add-server",
| |
| "host": "10.0.0.1",
| |
| "port": "443"
| |
| }</nowiki>
| |
| |-
| |
| | |
| |
| |
| === create-interfaces ===
| |
| Creates channels for the specified interfaces using [[Client/Presets|presets]].
| |
| {| class="wikitable"
| |
| |+ Parameters
| |
| |-
| |
| | interfaces|| a JSON object where each key is a network interface name, with the corresponding value being a [[Client/Presets|preset]] name. Required.
| |
| |}
| |
| ||
| |
| <nowiki>{"target": "tunnel",
| |
| "action": "create-interfaces",
| |
| "interfaces": {
| |
| "wwan0": "mobile",
| |
| "eth1": "ethernet"
| |
| }
| |
| }</nowiki>
| |
| |-
| |
| | |
| |
| |
| === add-interface ===
| |
| Adds a single interface to the tunnel.
| |
| {| class="wikitable"
| |
| |+ Parameters
| |
| |-
| |
| | interface || Name of the linux network interface. Required.
| |
| |-
| |
| | name || Human-readable name for the interface. Optional.
| |
| |-
| |
| | preset || [[Client/Presets|Preset]] that should be applied to this interface. Optional.
| |
| |-
| |
| | values || Configuration values for this interface. See [[Tunnel Settings]]. Optional.
| |
| |}
| |
| ||
| |
| <nowiki>{"target": "tunnel",
| |
| "action": "add-interface",
| |
| "interface": "wlan0",
| |
| "name": "WiFi",
| |
| "preset": "mobile",
| |
| "values": {"enabled": false}
| |
| }</nowiki>
| |
| |-
| |
| | |
| |
| |
| === set ===
| |
| Sets tunnel properties. See [[Tunnel Settings]].
| |
| {| class="wikitable"
| |
| |+ Parameters
| |
| |-
| |
| | values || JSON object with values to change. Required.
| |
| |}
| |
| ||
| |
| <nowiki>{"target": "tunnel",
| |
| "action": "set",
| |
| "values": {"maxConcurrentChannel": 2}
| |
| }</nowiki>
| |
| |-
| |
| | |
| |
| |
| === set-remote ===
| |
| Sets tunnel properties on the remote end. See [[Tunnel Settings]].
| |
| {| class="wikitable"
| |
| |+ Parameters
| |
| |-
| |
| | values || JSON object with values to change. Required.
| |
| |}
| |
| ||
| |
| <nowiki>{"target": "tunnel",
| |
| "action": "set-remote",
| |
| "values": {"maxConcurrentChannel": 2}
| |
| }</nowiki>
| |
| |-
| |
| | |
| |
| |
| === set-interface ===
| |
| Sets tunnel interface properties. See [[Tunnel Settings]].
| |
| {| class="wikitable"
| |
| |+ Parameters
| |
| |-
| |
| | index || Index of the channel. 0 for first created channel, 1 for second, etc..
| |
| |-
| |
| | values || JSON object with values to change.
| |
| |}
| |
| ||
| |
| <nowiki>{"target": "tunnel",
| |
| "action": "set-interface",
| |
| "index": 0,
| |
| "values": {"enabled": false}
| |
| }</nowiki>
| |
| |-
| |
| | |
| |
| |
| === set-remote-interface ===
| |
| Sets interface properties on the remote end. See [[Tunnel Settings]].
| |
| {| class="wikitable" | | {| class="wikitable" |
| |+ Parameters
| |
| |- | | |- |
| | index || Index of the channel. 0 for first created channel, 1 for second, etc.. | | |useBlake||Switches from SHA256 to the "blake" hashing algorithm. |
| |- | | |- |
| | values || JSON object with values to change. | | |useBlake3||Switches to the "blake3" hashing algorithm. |
| |}
| |
| ||
| |
| <nowiki>{"target": "tunnel",
| |
| "action": "set-remote-interface",
| |
| "index": 0,
| |
| "values": {"enabled": false}
| |
| }</nowiki>
| |
| |- | | |- |
| | | |disableHash||Disables hashing completely |
| | |
| | |
| | | |
| === set-preset ===
| |
| Applies a tunnel preset. See [[Client/Presets|Presets]] for more info.
| |
| {| class="wikitable"
| |
| |+ Parameters
| |
| |- | | |- |
| | name || Name of the tunnel preset. Required. | | |useMMSG||uses useMMSG linux socket API to send & receive multiple UDP packets at once. |
| |}
| |
| ||
| |
| <nowiki>{"target": "tunnel",
| |
| "action": "set-preset",
| |
| "preset": "Bonding"
| |
| }</nowiki>
| |
| |- | | |- |
| | | |channelRoutes||Makes the client create specific routes for each channel. Experimental, do not use. |
| | | |
| === set-ifname ===
| |
| Renames the virtual network tunnel interface.
| |
| {| class="wikitable"
| |
| |+ Parameters
| |
| |- | | |- |
| | name || The name that the interface should be renamed to. Required. | | |bondingProxy||<s>Enables the TCP [[Bonding Proxy]]</s>. Now always enabled |
| |} | | |} |
| ||
| |
| <nowiki>{"target": "tunnel",
| |
| "action": "set-ifname",
| |
| "name": "bondix0"
| |
| }
| |
| }</nowiki>
| |
| |-
| |
|
| |
| |
| |
| === set-cert-check ===
| |
| Enables or disables verification of the server's SSL certificate. ''TODO: Which root cert dir is used when no custom root certificate is provided?''
| |
| {| class="wikitable"
| |
| |+ Parameters
| |
| |-
| |
| | enabled || Enables or disables SSL certificate verification. Required.
| |
| |}
| |
| ||
| |
| <nowiki>{"target": "tunnel",
| |
| "action": "set-cert-check",
| |
| "enabled": true
| |
| }
| |
| }</nowiki>
| |
| |-
| |
|
| |
|
| |
| | ==bndutil== |
| === set-root-ca === | | bndutil is a command line utility that allows to query and modify SANE during runtime. It uses the configuration TCP socket |
| Specifies a root certificate that can be used to verify the authenticity of the remote server. When used, SSL server verification will be automatically enabled.
| | <nowiki>root@Teltonika-RUTX12:/opt/bondix/client# ./bndutil |
| {| class="wikitable"
| | Usage: |
| |+ Parameters
| | bndutil [--json] <command> |
| |-
| | --json switch to JSON output |
| | file || location of the public root certificate file. Required.
| | |
| |}
| | Available commands: |
| ||
| | * bndutil status |
| <nowiki>{"target": "tunnel", | | * bndutil get |
| "action": "set-root-ca", | | * bndutil set <propertyName1> <propertyValue1> [propertyName2] [propertyValue2] ... |
| "file": "/etc/ssl/foobar.pub" | | * bndutil get-interface <index> |
| } | | * bndutil set-interface <index> <propertyName1> <propertyValue1> [propertyName2] [propertyValue2] ... |
| }</nowiki>
| | * bndutil shutdown |
| |-
| | * bndutil restart |
| | (tunnel reset & reconnect) |
| | </nowiki> |
|
| |
|
| |
| | ==speedtest== |
| === set-certificate ===
| | Speedtest is a small utility that downloads (and discards) data via HTTP(s) using one or more WAN interfaces. It is useful to compare performance of each individual interface and the combined bandwidth over SANE's virtual tunnel interface. |
| Loads a tunnel client certificate. See [[Certificates]] for further information.
| | <nowiki>root@Teltonika-RUTX12:/opt/bondix/client# ./speedtest |
| {| class="wikitable"
| | Usage: speedtest [--json] <download-url> <intf1> [intf2] ...</nowiki> |
| |+ Parameters
| |
| |-
| |
| | cert || location of the public certificate file. Required.
| |
| |-
| |
| | key || location of the private certificate key file. Required.
| |
| |}
| |
| ||
| |
| <nowiki>{"target": "tunnel", | |
| "action": "set-certificate",
| |
| "cert": "/etc/ssl/foobar.pem"
| |
| "key": "/etc/ssl/foobar.key" | |
| }</nowiki>
| |
| |-
| |
|
| |
|
| |
| | E.g., to test performance of each WAN interface directly: |
| === embed-certs ===
| | <nowiki>./speedtest http://speed.hetzner.de/100MB.bin wwan0 wwan1 wwan2</nowiki> |
| A helper functions to embed tunnel & root certificate inside the configuration instead of an external file. Performs the same actions as set-certificate and set-root-ca combined.
| |
| {| class="wikitable"
| |
| |+ Parameters
| |
| |-
| |
| | cert || The tunnel public certificate as string. Required.
| |
| |-
| |
| | key || The tunnel private certificate key as string. Required.
| |
| |-
| |
| | root || The public root certificate for server verification. Required.
| |
| |}
| |
| ||
| |
| <nowiki>{"target": "tunnel", | |
| "action": "embed-certs",
| |
| "cert": "...",
| |
| "key": "...",
| |
| "root": "..."
| |
| }</nowiki>
| |
| |-
| |
|
| |
|
| |
| | Testing performance of the tunnel: |
| === set-root-ca ===
| | <nowiki>./speedtest http://speed.hetzner.de/100MB.bin tun0</nowiki> |
| Specifies a root certificate that can be used to verify the authenticity of the remote server. When used, SSL server verification will be automatically enabled.
| |
| {| class="wikitable"
| |
| |+ Parameters
| |
| |-
| |
| | file || location of the public root certificate file. Required.
| |
| |}
| |
| ||
| |
| <nowiki>{"target": "tunnel",
| |
| "action": "set-root-ca",
| |
| "file": "/etc/ssl/foobar.pub"
| |
| }
| |
| }</nowiki>
| |
| |-
| |
| | |
| |
| |
| === delete ===
| |
| Resets the complete tunnel configuration, including interfaces.
| |
| ||
| |
| <nowiki>{"target": "tunnel", | |
| "action": "delete"
| |
| }</nowiki>
| |
| |}
| |
| | |
| == Interactive Commands ==
| |
| Interactive commands can be used to retrieve various information via the CLI socket.
| |
| ''TODO: Add JSON responses''
| |
| {| class="wikitable" style="width: 100%"
| |
| |-
| |
| | |
| |
| |
| === get ===
| |
| Returns all [[Tunnel Settings|tunnel settings]].
| |
| | style="width: 40%"|
| |
| <nowiki>{"target": "tunnel",
| |
| "action": "get"
| |
| }</nowiki>
| |
| |-
| |
| | |
| |
| |
| === get-interface ===
| |
| Returns [[Tunnel Settings|settings]] for a specific interface.
| |
| {| class="wikitable"
| |
| |+ Parameters
| |
| |-
| |
| | index || Index of the interface to fetch information from.
| |
| |}
| |
| ||
| |
| <nowiki>{"target": "tunnel",
| |
| "action": "get-interface",
| |
| "index": 0
| |
| }</nowiki>
| |
| |-
| |
| | |
| |
| |
| === status ===
| |
| Returns various tunnel information.
| |
| ||
| |
| <nowiki>{"target": "tunnel",
| |
| "action": "status"
| |
| }</nowiki>
| |
| |-
| |
| | |
| |
| |
| === reset===
| |
| Performs a disconnect & reconnect.
| |
| ||
| |
| <nowiki>{"target": "tunnel",
| |
| "action": "reset"
| |
| }</nowiki>
| |
| |}
| |
| | |
| = Running =
| |
| The software can be run in the shell using <code>/opt/bondix/client/saneclient</code>, where it will run in the foreground. However, it is recommended to start the service automatically on startup, which can be different depending on the platform.
| |
| == Parameters ==
| |
| {| class="wikitable"
| |
| |-
| |
| | <code>--daemon</code> || Runs the software as a daemon.
| |
| |-
| |
| | <code>--nopid</code> || Does not attempt to create a pid-file at <code>/var/run/saneclient.pid</code>
| |
| |-
| |
| | <code>--listflags</code> || Lists available feature flags
| |
| |-
| |
| | <code>--flags <FLAG1> <FLAG2>... </code> || Enables the specified flag(s). Multiple flags are separated using space.
| |
| |-
| |
| | <code></path/to/filename.json></code> || JSON configuration file that should be used
| |
| |}
| |
| == Feature Flags ==
| |
| Feature flags are switches that enable certain features that are otherwise unavailable. These features are usually experimental and should be used with caution.
| |
| {| class="wikitable"
| |
| |-
| |
| | useBlake || Switches from SHA256 to the "blake" hashing algorithm. Depending on architecture, this can slightly improve performance.
| |
| |-
| |
| | useBlake3 || Switches to the "blake3" hashing algorithm. Depending on architecture, this can slightly improve performance.
| |
| |-
| |
| | disableHash || Disables hashing completely, allowing potential MitM, with a vast speed improvement.
| |
| |-
| |
| | useMMSG || uses useMMSG linux socket API to send & receive multiple UDP packets at once. This improves performance under load, while stable there are some corner cases which can trigger error messages in the log.
| |
| |-
| |
| | channelRoutes || Makes the client create specific routes for each channel. Experimental, do not use.
| |
| |-
| |
| | bondingProxy || Enables the TCP [[Bonding Proxy]].
| |
| |}
| |
The Bondix SANE client is the software that you install on your router, which establishes a connection to the server using multiple WAN links. The software itself is a linux userspace program, but installation packages for different routers are available, that take care of most of the configuration.
This page covers the barebone linux application. Please check out the Teltonika page for installation & usage on these routers.
Configuration
Configuration is done using JSON commands. These can either be sent via a raw TCP socket (localhost:5113), or written to a configuration file (in a json-array) that is parsed on start-up.
By default, SANE checks for the existence of a configuration file in its installation directory (e.g. /opt/bondix/client/saneclient.json
) and at /etc/saneclient.json
. If you want SANE to load a configuration from a different location, you can specify it using a command line parameter.
Quick Start
This example provides the minimal necessities to get a tunnel up and running:
[
{"action": "create", "target": "tunnel", "name": "TUNNELNAME", "password": "TUNNELPASSWORD"},
{"action": "add-server", "target": "tunnel", "host": "ENDPOINTSERVER", "port": "443"},
{"action": "create-interfaces", "target": "tunnel", "interfaces": {
"eth1": "mobileAggressive",
"wwan0": "mobileAggressive",
"wwan1": "mobileAggressive"
}},
{"target": "tunnel", "action": "set-preset", "preset": "bonding"}
]
Configuration Commands
For a complete reference list of available commands, see Client Configuration.
Tunnel Configuration
Tunnels and channels have many configurable values, that are managed using Presets.
Running
The software can be run in the shell using /opt/bondix/client/saneclient
, where it will run in the foreground. However, it is recommended to start the service automatically on startup, which can be different depending on the platform.
Parameters
--daemon |
Runs the software as a daemon.
|
--nopid |
Does not attempt to create a pid-file at /var/run/saneclient.pid
|
--listflags |
Lists available feature flags
|
--flags <FLAG1> <FLAG2>... |
Enables the specified flag(s). Multiple flags are separated using space.
|
</path/to/filename.json> |
JSON configuration file that should be used
|
Feature Flags
Feature flags are switches that enable certain features that are otherwise unavailable. These features are usually experimental and should be used with caution.
useBlake |
Switches from SHA256 to the "blake" hashing algorithm.
|
useBlake3 |
Switches to the "blake3" hashing algorithm.
|
disableHash |
Disables hashing completely
|
useMMSG |
uses useMMSG linux socket API to send & receive multiple UDP packets at once.
|
channelRoutes |
Makes the client create specific routes for each channel. Experimental, do not use.
|
bondingProxy |
Enables the TCP Bonding Proxy. Now always enabled
|
bndutil
bndutil is a command line utility that allows to query and modify SANE during runtime. It uses the configuration TCP socket
root@Teltonika-RUTX12:/opt/bondix/client# ./bndutil
Usage:
bndutil [--json] <command>
--json switch to JSON output
Available commands:
* bndutil status
* bndutil get
* bndutil set <propertyName1> <propertyValue1> [propertyName2] [propertyValue2] ...
* bndutil get-interface <index>
* bndutil set-interface <index> <propertyName1> <propertyValue1> [propertyName2] [propertyValue2] ...
* bndutil shutdown
* bndutil restart
(tunnel reset & reconnect)
speedtest
Speedtest is a small utility that downloads (and discards) data via HTTP(s) using one or more WAN interfaces. It is useful to compare performance of each individual interface and the combined bandwidth over SANE's virtual tunnel interface.
root@Teltonika-RUTX12:/opt/bondix/client# ./speedtest
Usage: speedtest [--json] <download-url> <intf1> [intf2] ...
E.g., to test performance of each WAN interface directly:
./speedtest http://speed.hetzner.de/100MB.bin wwan0 wwan1 wwan2
Testing performance of the tunnel:
./speedtest http://speed.hetzner.de/100MB.bin tun0