Nabto Edge TCP Tunnel Step-by-Step Guide

This thorough guide will show you how to setup the ready-made Nabto client and device tunnel endpoints to enable TCP remote access to your existing TCP services.

All the scenarios demonstrated through the commandline tunnel client app can be implemented in e.g. a mobile app; the commandline app is a good way to play with the different pairing modes supported by the Nabto IAM module - you can then select the mode (or modes) suitable for your specific scenario.

Nabto Cloud Configuration

To use Nabto Edge, you must first create a free account through the Nabto Cloud Console if not done already.

Once you have created an account, navigate to the Products page and create a new Nabto Edge product. Note down the product ID.

In the “Configured Devices” tab, create a new device. From the device page, note the device ID.

You are now ready to start building the Embedded tunnel device application.

Embedded tunnel application

The embedded tunnel application is available as part of the Nabto Edge Embedded SDK. To build the embedded tunnel application, follow the build instructions for the general SDK build. Or you can download pre-compiled binaries.

After building or downloading binaries, run the device with the --demo-init argument to configure your device with a demonstration configuration. The demonstration configuration gives all paired users the Administrator role so we do not need to worry about IAM permissions in this demo. For production use, you should make your own configuration. This configuration enables Local Open Pairing and Password Open Pairing modes. To learn more about pairing modes and which to enable for your use case see our pairing guide.

When queried, provide the Product ID and Device ID from the previous section. It will then ask which service you want to add. We want ssh which is the default, so just hit <enter> to confirm the default. When asked for the ssh port, confirm the default 22. Finally, it will ask if you want to add an additional service, however, this time continue is the default which we again just confirm.

$ ./tcp_tunnel_device --demo-init
No device configuration found. Creating configuration: /home/user/.nabto/edge/config/device.json.
The device configuration requires a Product ID and a Device ID, created in the Nabto Cloud Console.
Product Id: pr-aaaaaaaa
Device Id: de-bbbbbbbb


Demo initialization will make a simple IAM setup, be aware that this is not what you want in production.
'Local Open Pairing' and 'Password Open Pairing' are enabled. Newly paired users get the 'Administrator' role.

Next step is to add TCP tunnel services.
What type of service do you want to add?
[0]: continue
[1]: ssh
[2]: http
[3]: rtsp
Enter a valid number (default: 1) [0-3]:
Enter your SSH port (default: 22) [0-65535]:
Added ssh service on localhost port 22

What type of service do you want to add?
[0]: continue
[1]: ssh
[2]: http
[3]: rtsp
Enter a valid number (default: 0) [0-3]:

The configuration and state has been initialized
The Fingerprint must be configured for this device in the Nabto Cloud Console before it will be allowed to attach to the Basestation. If you want to reuse an already configured fingerprint, you can copy the corresponding private key to /home/user/.nabto/edge/keys/device.key
The device Fingerprint is: 08c955a5f7505f16f03bc3e3e0db89ff56ce571e0dd6be153c5bae9174d62ac6

This device configuration as well as initial state has now been stored in home dir for the device. The home dir defaults to $HOME/.nabto/edge on Unix and %%APP_DATA%%/nabto/edge on Windows. The home dir can be changed with --home-dir.

With the configuration in place, you are almost ready to start the device: The Nabto Edge Cloud services do not yet know the public key fingerprint of the device, and will reject the device.

To register the fingerprint, go to the device configuration page in the Nabto Cloud console (first click product, then click the device in question). Then enter the fingerprint from the command line output - in the example above the value is 08c955a5f7505f16f03bc3e3e0db89ff56ce571e0dd6be153c5bae9174d62ac6 - copy this value from your own tunnel output to the device fingerprint config on the Nabto Cloud console and save.

Now start the device without any arguments and it should be able to attach (note: on Windows, you may see a firewall popup - if so, you need to allow the tunnel application to listen for incoming connections):

$ ./tcp_tunnel_device
######## Nabto TCP Tunnel Device ########
# Product ID:        pr-aaaaaaaa
# Device ID:         de-bbbbbbbb
# Fingerprint:       08c955a5f7505f16f03bc3e3e0db89ff56ce571e0dd6be153c5bae9174d62ac6
# Version:           5.12.0
# Local UDP Port:    5592
# Friendly Name:     "Tcp Tunnel"
#
# The device offers Local Open Pairing
#
# The device has Password Open Pairing enabled
# Open Pairing Password:  CbAHaqpKKrhK
# Open Pairing SCT:       TUfe3n3hhhM9
# Open Pairing String:    p=pr-aaaaaaaa,d=de-bbbbbbbb,pwd=CbAHaqpKKrhK,sct=TUfe3n3hhhM9
#
######## Configured TCP Services ########
# Id               Type             Host             Port
# ssh              ssh              127.0.0.1        22
########
Attached to the basestation

Client tunnel application

The Nabto Edge TCP tunnel client is available through its own github repo. The client can be downloaded as a release asset binary, or you can build it yourself from source using the guide on the repo.

To use the client with the device, it must first be paired. To understand different pairing modes and role-based user permissions see the IAM guide. For this tutorial, our demo configuration makes all users administrators, so we do not need to worry about IAM permissions for now.

We can now connect to the device and pair the client with the device using one of the two pairing modes enabled by our demo configuration.

After pairing is complete, the tunnel client app adds a bookmark to allow quickly connecting later. The bookmark contains device identification info, the device’s public key fingerprint for authenticating it and a token that allows remote connections through the Nabto servers.

Local Open Pairing

If the client is located on the same subnet as the device, we can discover and pair with the device locally.

Running the client with the --pair-local option starts local discovery of the device using mDNS. When discovery is completed, the client will show a list of discovered devices. Pick your device from the list and press enter. The client then connects to the device and queries which pairing modes are available and list both enabled pairing modes. Pick Local Open. When asked, type a username for the client:

$ ./edge_tunnel_client --pair-local
Scanning for local devices for 2 seconds.
Found 1 local devices.
Choose a device for pairing:
[q]: Quit without pairing
[0]: ProductId: pr-aaaaaaaa DeviceId: de-bbbbbbbb
Choose a device: 0
Connected to the device. ProductId: pr-aaaaaaaa DeviceId: de-bbbbbbbb
Several pairing modes exists choose one of the following.
[0]: Password Open
[1]: Local Open
Choose a pairing mode: 1
The pairing needs a username, the username needs to be unique among the users registered in the device.
Username: john
The device [0] pr-aaaaaaaa.de-bbbbbbbb has been set into the bookmarks as index 0

If your device is not available locally, you can use password open pairing below. Otherwise, you are now ready to start using your tunnel.

Password Open Pairing

If the device cannot be discovered locally, you can use Password Open. The client needs four pieces of information: the Product ID, the Device ID, the password, and a server connect token (SCT). With this information, the client is able to connect to and pair with the device either remotely through the Nabto servers (or locally if it was discoverable).

The password and SCT is generated by the device during initialization. Fortunately, the device prints all this information in an Open Pairing String. This string can the be copied from the device output and supplied to the client application using its --pair-string option. For production scenarios, see this guide on how you can pass the string from the device to the end-user who can in turn supply it to the client application.

$ ./edge_tunnel_client --pair-string \
    p=pr-aaaaaaaa,d=de-bbbbbbbb,pwd=CbAHaqpKKrhK,sct=TUfe3n3hhhM9
Connected to device ProductId: pr-aaaaaaaa DeviceId: de-bbbbbbbb
Open Password Pairing requires a username. The username is a name you choose for the new user, the username has to be unique among the registered users on the device.
New Username: john
The device [0] pr-aaaaaaaa.de-bbbbbbbb has been set into the bookmarks as index 0

Your client is now paired with the device and can be used for TCP tunneling.

Using the tunnel

You are now ready to start using the tunnel. You can list the available services as provided by the device:

$ ./edge_tunnel_client --services
Connected to the device [0] pr-aaaaaaa.de-bbbbbbbb
Available services ...
Service: ssh        Type: ssh        Host: 127.0.0.1  Port: 22

We only configured the ssh service during initialization of the device. See below on how to add services after initialization.

You can now start the service as follows:

$ ./edge_tunnel_client --service ssh
Connected to the device [0] pr-aaaaaaaa.de-bbbbbbbb
TCP Tunnel opened for the service ssh listening on the local port 52530

Now you can connect an SSH client to localhost port 52530 to access the SSH service running on the same host as the embedded device application.

Note: The Nabto TCP server running locally on the client cannot distinguish TCP connections from your existing application and any other applications running on the localhost. If the host running the client cannot be trusted, application level authentication on top of your TCP connection is needed (e.g., RTSP or HTTP basic auth). Or integration through low level Nabto Edge Streams can be used instead (much more complex integration).

Configuring additional services after initial setup

The available services to be tunnelled by the device are defined in the configuration file ~/.nabto/edge/config/tcp_tunnel_device_services.json. To add e.g. a tunnel for an HTTP server running on port 8081, add an entry to this file (note the JSON array syntax), then restart the device.

[
  {"Id":"ssh","Type":"ssh","Host":"127.0.0.1","Port":22},
  {"Id":"nginx","Type":"http","Host":"127.0.0.1","Port":8081}
]
$ ./edge_tunnel_client  --services
Connected to the device [0] pr-aaaaaaaa.de-bbbbbbbb
Available services ...
Service: ssh        Type: ssh        Host: 127.0.0.1  Port: 22
Service: nginx      Type: http       Host: 127.0.0.1  Port: 8081

So now you can start an HTTP tunnel:

$ ./edge_tunnel_client  --service nginx
TCP Tunnel opened for the service nginx listening on the local port 52716

And then in another terminal, you can access the HTTP service:

$ curl localhost:52716
<html>
  <body>
     <h1>Hello, world!</h1>
  </body>
</html>

More Pairing modes

Pairing additional clients are done with the two enabled pairing modes just as described previously.

Two additional pairing modes exists: Local Initial Pairing and Password Invite Pairing. If enabled, these can be used to pair with an initial admin user. This requires such a user to be pre-configured in the device.

Moreover, Password Invite can be used to pair a specific new user created by an existing admin user at runtime. See the pairing guide for a description of all 4 pairing modes and how they compare.