Securely Manage Your WisGate Connect Remotely with SSH No Ports
Gateway Management Options
LoRaWAN® (and LoRa) is the LPWA network of choice for many people these days. There are several reasons for this, but a key one is the ability to deploy your own private network with LoRa, eliminating dependencies on external operators. You can deploy your sensors, your gateways, and even host your own LoRaWAN® Network Server using any of the different open-source options available, or use a third-party SaaS solution. Regardless of the option you choose, whether you're an individual or a large company, gateway management is a topic in its own right. Mainly because there is no standard. Yet.
There are already several non-standard options available. Some gateway manufacturers offer their own solution, compatible with their gateways, like we do at RAKwireless. You can use WisDM to manage all WisGate Edge gateways (indoors and outdoors).
Some platforms offer an "agent" that you need to install on the gateway to connect to their management solutions. These solutions are usually poorly maintained, focusing on specific brands and even specific firmware versions (sometimes you have to downgrade the firmware to install the agent!).
Then there are some third-party generic options, but they require a specific OS installed on the gateway. This is only possible with a small subset of gateways and almost never with "commercial" gateways. Keep in mind that the "job" of a LoRaWAN® gateway is very simple, so they are usually very resource-limited and, besides legal or warranty considerations, replacing the OS is not even technically feasible most of the time. Our WisGate Connect is one of these platforms where you have considerable flexibility: VPN, custom OS, or simply good old SSH.
Of course, you can always manage the gateways individually, usually by providing SSH access to it. And the first thing that should come to your mind now is "security." Indeed, all fleet management solutions I know use some kind of VPN tunnel between the gateway and the server to secure communications. You don't need any special port open on the gateway to manage it since the tunnel is opened from the gateway outwards. You might need to have other ports open for the LNS, but that's not related to gateway management.
Unlike with SSH, VPN connections are "alive" at all times, meaning there is a cost in bandwidth even when you're not actively using the gateway. On the other hand, to SSH into the gateway, you need to have an open port on the device and probably forwarded on any router along its path. This presents a security risk and a maintenance cost.
Unless the gateway initiates the communication itself, but then the question is: where should it connect to? And when?
A Tunnel Inside a Tunnel
A reverse SSH tunnel is a well-known method for connecting two machines when NAT or firewall limitations exist. This process often involves a third server, typically located in the DMZ, serving as a stepping stone to jump from the client to the target device.
On the destination device (let's call it "device"), you open an SSH connection to the rendezvous server, forwarding a remote port to the local port 22/tcp (or wherever the sshd daemon is listening). Then, on the second machine (let's refer to this as "client"), you SSH into the rendezvous server and, from there, you SSH into the "device" using the same tunnel initially opened from the device to the rendezvous server.
Or from the terminal (port 58022/tcp on the rendezvous server forwards traffic to 22/tcp on the device):
xose@device > ssh rendezvous -R 58022:localhost:22
Now from the client machine (connect to the remote device using the rendezvous as a stepping stone):
xose@client > ssh -J rendezvous localhost -p 58022
While this is advantageous, it's also complex for many people and requires several hidden steps:
- Shared keys exist between all three servers, so passwords aren't required (SSHing to a server with a password is generally considered poor security practice).
- The connection must be initiated from both sides: first from the device to the rendezvous server, and second from the client to the device via the rendezvous server.
- You need to know the IP of the rendezvous server and the port it uses to forward traffic to the device.
- The initial connection with the reverse forward must remain active at all times, so you can always SSH into the device from outside.
Even though this method is useful for some use cases, it's hard to automate, and the initial connection still requires someone inside. Additionally, anyone with access to your rendezvous server will also have access to your gateway.
So, does this lead to a dead-end road?
SSH No Ports
After all this complexity, there's good news: there is indeed a secure, remote, and straightforward way to achieve this!
Atsign is a globally distributed company offering networking tools. One of its projects is SSH No Ports, a connectivity solution with some unique features:
- A directory server (atDirectory) replaces ever-changing IPs with simple, unique device names known as atSigns.
- The tunnels are only active as needed, with the device primarily waiting for a request that the directory server has previously validated.
- A rendezvous server (Socket Rendezvous or SR) opens two single-use sockets, creating isolated secure tunnels from the client to the device.
- Two initial tunnels connect both machines to the rendezvous server upon request. The keys used for these tunnels are single-use and generated on-the-fly.
This entire process adheres to a Zero Trust Policy, securing your data end-to-end with keys stored only on your device and your client.
Atsign offers this service as SaaS with an annual fee covering one person and unlimited devices. For those who prefer a hands-on approach, they also provide all the components as Open Source code under the BSD-3-Clause license on the Atsign Foundation GitHub account. This allows you to host your own rendezvous server or atDirectory server, or both!
Deploying the Service
The procedure isn't complex but does require a few steps, only the first time around. You can find instructions directly in Atsign's Installation Guide. The guide covers the following steps:
- Dependencies (primarily curl and sshd on both the device and client)
- Obtaining the addresses (atSigns) for your device and client
- Setting up both the device and client
- Activating the addresses (a manual email validation is required for security)
- Connecting!
Since I'm a fan of Docker, I'm going to execute steps 3 to 5 on the device using Docker for easier deployment. Atsign also provides a Docker image, and the latest 4.0 version (still in RC at the time of this writing) simplifies configuration using a docker-compose.yml file, an .envfile for configuration variables, and key files for each device. The client side follows the same procedure as described above. On the device side (your gateway), you will have these files:
workspace
|-- .keys | |-- @client_key.atKeys | |-- @device_key.atKeys |-- .env |-- docker-compose.yml
The *.atKeys files in the .keys folder hold the keys for the client and the device. You can obtain these from the noport site. The .env file contains the common configuration: the addresses of the client and device on the Atsign ecosystem, the device name, and the CRAM key for atSign activation. You can also get this from the noport site.
TO='@device' TO_CRAM=09a....39a0 DEVICE='mygateway' FROM='@client'
The docker-compose.yml file starts the activation service first and later the sshnpd service, which connects to the atDirectory, waiting for incoming connection requests.
version: '3.7' services: activate: image: atsigncompany/activate_sshnpd:latest volumes: - ./.keys/:/atsign/.atsign/keys command: -a "${TO}" -c "${TO_CRAM}" sshnpd: image: atsigncompany/sshnpd container_name: sshnpd restart: unless-stopped volumes: - ./.keys/:/atsign/.atsign/keys command: -a "${TO}" -m "${FROM}" -d "${DEVICE}" -s -u -v depends_on: activate: condition: service_completed_successfully
As you can see, both the activate and sshnpd services share the same configuration variables, loaded by default from the .env file. The activate service will first attempt to activate the device key using the CRAM key (this bypasses manual validation, so use with caution), and the sshnpd service stays in the background waiting for requests. Since the service is set to restart unless stopped, it will automatically start with Docker after a reboot.
Finally, you just have to enter:
xose@device > docker compose up -d
and you're done. Now, provided you've set up your client machine, you can connect to the device from your workstation (client) with a simple:
$(sshnp@device mygateway)
I recommend manually activating the atSign and removing the activate service in the docker-compose.yml file, along with the dependency on the sshnpd service.
If you're not comfortable with the terminal, you can run the same Docker compose configuration using Portainer (remember, just type `portainer up` on your RAKPiOS system to install the latest version).
When using Docker, the connection is established to the Docker container. You'll still need to jump to the host from there.
Zero Trust Policy
You might be thinking, "I see, so I'm securing my gateway by trusting a third party. That doesn't sound like security to me." That's a valid concern. However, let's take a closer look into the various components of this solution.
Your gateway (the device) and your workstation (the client) are under your control, and the software you run on them is open source. You can review it, and even build it yourself. This software connects to the directory server to retrieve the addresses of the rendezvous machine, the port it needs to connect to for the tunnel, and the keys to create the tunnels to the rendezvous server. Your workstation initiates the encrypted communication using your own keys, which aren't shared.
Next, there's the rendezvous server. Think of it as a modern version of a telecommunications switchboard, responsible for correctly wiring the different connections. It doesn't know who is calling; it merely knows which ports need to be connected. The communication itself is encrypted with keys unknown to the rendezvous server. If you prefer, you can host your own rendezvous server.
Lastly, there's the Directory server. This component stores the atSigns of all the machines in the system and validates requests. When a request is validated (meaning machine A has permission to connect to machine B), it informs both parties about the rendezvous server address and the ports they need to connect to. And guess what? You can host this service yourself, too.
So, depending on your security requirements, you have several options to consider.
Fleet Management
One final note: managing a single gateway is not the same as fleet management. When you have more than a few gateways, managing them individually can become a significant challenge. I've been informed that a "configuration management" feature is on the roadmap, which could help manage gateways in sets. However, even without this feature, there are other options available, such as Ansible. Perhaps it's worth exploring? Any takers?