Getting started with Meshtastic

mk16.de

I recently came across a new project in Fediverse: Meshtastic Meshtastic is a peer-to-peer mesh network based on LoRa, a proprietary wireless technology.

The thing that particularly attracted me to Meshtastic is that it supports IP tunneling. I always enjoy learning about new routing and networking technologies and I saw Meshtastic as a great way to learn something new.

To join the network, you need a LoRa-enabled device with Meshtastic support. If you want to send something to a node, you send it in messages. Each message has a channel on which it is sent, a port, a TTL and a content. The messages are encoded using Protobuf.

Messages

Channel

Meshtastic uses Channels for separation. There is a standard channel, which is public. Any number of additional channels can be added (currently only eight due to hardware). The channels have names and, if desired, a password. The messages are then encrypted using AES256-CTR (some devices also have hardware support for this). Any device that participates in the channel and knows the password can decrypt the message. Furthermore, a distinction is made between a “primary” and several “secondary” channels. The primary channel is used for distributing node information (runtime, location, battery status, etc.) and for IP tunneling. Only messages can be exchanged on the secondary channels.

Port

Each Meshtastic message also contains a port. This provides information about what the message contains (text message, node information, IP packet, …)

TTL

The mesh algorithm is quite simple and implements the principle of “flooding”. Each node sends each packet to its neighboring node. This node then forwards the packet accordingly. When the packet is forwarded, the TTL is reduced by one. The default TTL is 3 - but it can be set up to 7. A packet with a TTL of 0 is not forwarded.

Hardware

Personally, I’m more of a software person than a hardware person. I find hardware can be quite unpredictable and worst of all, it doesn’t even display error messages. So I needed a fairly simple device. Since I wanted to do IP tunneling, I even needed at least two. As I’m currently a student, the two devices also had to be inexpensive. And since I’m a rather messy person, I also need a cover or case for the devices. Meshtastic offers a list of devices on their website. I had a look at the devices and finally decided on the Meshtastic Starter Kit from RAKwireless.

You can see white bags with brown signs on them. The brown signs say "RAK", among other things.

You can see two white bags. They are transparent in front of the side of the photo. In the left bag you can see a blue piece of paper. There is a circuit board on top of it. In the right bag you can see some plastic (battery holder), pads that act as feet, a few plastic parts and screws

Then came the challenge of assembly. Fortunately, RAKwireless offers documentation for this.

You can see one of the plastic parts. Among other things, there is an area marked with "WisBase".

You can see the plastic object with a circuit board with spacers on it. Two cables are attached to the board, which in turn lead to a small board (these are the antennas).

You can see the previous photo from an oblique perspective.

You can see a transparent acrylic housing (the plastic parts from before) in which there is a circuit board. Two cables lead from the circuit board, each of which is attached to a different circuit board. The two circuit boards are glued to the bottom of the acrylic housing. You can see a cable leading from the main board. Two LEDs light up on it - one red, one green.

After I had attached the antennas to the board and screwed them into the housing, I noticed that there were protective films on the housing. None of this was mentioned in the documentation. This meant that I had to unscrew everything again and screw it back together.

Furthermore, not enough screws were included. For the building with all possible add-ons you need 12 screws, my setup without battery holder needs 8 screws - but only 6 screws were supplied.

Another obstacle was attaching the antennas to the housing. The Bluetooth antenna has a small pad with adhesive, but not the LoRa antenna. However, after I had reassembled everything because of the protective film, I could no longer use the adhesive pad for the Bluetooth antenna. I decided to use some hot glue and fix the antennas with it. Since I’m not familiar with hardware, I don’t know how good this idea was - I just know that it didn’t break anything in my case, fortunately.

Setup

Then it was time to set up the devices. Meshtastic offers a command line tool written in Python, a web interface (which didn’t work for me) and an Android app. I opted for the command line tool. However, the device was not recognized correctly by the tool. The Android app was also able to explain the reason to me: The firmware is too old.

I then carried out a “factory reset” and then uploaded the latest firmware. With the factory reset, I wanted to make sure that there were no old configuration snippets from RAKwireless.

IP tunneling

Once I had set everything up, it was time to try out the IP tunneling function:

$ sudo meshtastic --tunnel
Connected to radio
INFO file:tunnel.py __init__ line:83 Starting IP to mesh tunnel (you must be root for this *pre-alpha* feature to work).  Mesh members:
INFO file:tunnel.py __init__ line:95 Node !5687b499 has IP address None.180.153
INFO file:tunnel.py __init__ line:95 Node !148bfdc5 has IP address None.253.197
sh: line 1: ifconfig: command not found
Aborting due to: 

ifconfig was not installed on my computer. ifconfig is an old tool that used to be used for network configuration. Nowadays, however, it is recommended to use ip.

After I had installed ifconfig, I tried the whole thing again:

$ sudo meshtastic --tunnel
Connected to radio
INFO file:tunnel.py __init__ line:83 Starting IP to mesh tunnel (you must be root for this *pre-alpha* feature to work).  Mesh members:
INFO file:tunnel.py __init__ line:95 Node !5687b499 has IP address None.180.153
INFO file:tunnel.py __init__ line:95 Node !148bfdc5 has IP address None.253.197
None.180.153: Unknown host
ifconfig: `--help' gives usage information.
Aborting due to: ifconfig command failed.

Apparently ifconfig is prompted to configure the IP address None.180.153. This is because the app is faulty. The background is that the command line argument is used to specify the subnet. However, if no subnet is specified, the argument is None.

A possible workaround is:

$ sudo meshtastic --tunnel --subnet 10.115

The interface could then be started:

$sudo meshtastic --tunnel --subnet 10.115
Connected to radio
INFO file:tunnel.py __init__ line:83 Starting IP to mesh tunnel (you must be root for this *pre-alpha* feature to work).  Mesh members:
INFO file:tunnel.py __init__ line:95 Node !148bfdc5 has IP address 10.115.253.197
INFO file:tunnel.py __init__ line:95 Node !5687b499 has IP address 10.115.180.153
$ ip address show mesh0
22: mesh0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 200 qdisc fq_codel state UNKNOWN group default qlen 500
    link/none 
    inet 10.115.253.197/16 scope global mesh0
       valid_lft forever preferred_lft forever

The subnet 10.115.0.0/16 is in the private area and can therefore actually be used without any problems. However, since the dn42 and the networks connected to it also use networks in this range, I looked for collisions and unfortunately found one. Unfortunately, Freifunk Cuxhaven also uses this network range. However, since they are no longer in the IC-VPN, I created a PR to remove the network. I have instructed my own dn42 network to consider the range 10.115.0.0/16 as invalid and therefore not to route it.

Another obstacle to IP tunneling with Meshtastic is the small MTU of 200 bytes. This automatically prevents IPv6, as IPv6 requires an MTU of at least 1280 bytes. However, it is possible to tunnel IPv6 via IPv4 (GRE, WireGuard, …).

For IP tunneling the primary channel is always used. No change is currently planned. However, this means that encryption will be difficult:

Another problem with IP tunneling via Meshtastic is the high latency and packet loss:

$ time ping 10.115.253.197 -c 20 -W 600
PING 10.115.253.197 (10.115.253.197) 56(84) bytes of data.
64 bytes from 10.115.253.197: icmp_seq=1 ttl=64 time=12612 ms
64 bytes from 10.115.253.197: icmp_seq=2 ttl=64 time=15457 ms
64 bytes from 10.115.253.197: icmp_seq=4 ttl=64 time=14536 ms
64 bytes from 10.115.253.197: icmp_seq=5 ttl=64 time=14669 ms
64 bytes from 10.115.253.197: icmp_seq=6 ttl=64 time=14803 ms
64 bytes from 10.115.253.197: icmp_seq=8 ttl=64 time=17756 ms
64 bytes from 10.115.253.197: icmp_seq=9 ttl=64 time=19245 ms
64 bytes from 10.115.253.197: icmp_seq=10 ttl=64 time=19234 ms
64 bytes from 10.115.253.197: icmp_seq=11 ttl=64 time=19280 ms
64 bytes from 10.115.253.197: icmp_seq=12 ttl=64 time=19564 ms
64 bytes from 10.115.253.197: icmp_seq=14 ttl=64 time=21571 ms
64 bytes from 10.115.253.197: icmp_seq=16 ttl=64 time=21286 ms
64 bytes from 10.115.253.197: icmp_seq=17 ttl=64 time=21525 ms
64 bytes from 10.115.253.197: icmp_seq=20 ttl=64 time=29039 ms

--- 10.115.253.197 ping statistics ---
20 packets transmitted, 14 received, 30% packet loss, time 19209ms
rtt min/avg/max/mdev = 12611.611/18612.706/29038.582/4040.933 ms, pipe 16

real	0m50.196s
user	0m0.007s
sys	0m0.068s

UDP transmission was also possible without any problems:

$ ncat --verbose --wait 10m --udp 10.115.180.153 8886
Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Connected to 10.115.180.153:8886.
Hello World!
^C
$ ncat --listen --verbose --udp --source-port 8886
Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Listening on [::]:8886
Ncat: Listening on 0.0.0.0:8886
Ncat: Connection from 10.115.253.197:47920.
Hello World!
^C

However, a simple TCP connection was not possible. This means that Meshtastic cannot be used for the dn42. However, simple chat applications that are based on UDP and tolerate high latencies should be possible.

$ ncat --verbose --wait 10m 10.115.180.153 8886
Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Connection timed out.

You can see an excerpt from WireShark. It shows some TCP retransmissions between 10.115.180.153 and 10.115.253.197.