National Cyber Warfare Foundation (NCWF)

Off-Grid Communications, Part 6: Internet-over-LoRa with deadmesh


0 user ratings
2026-04-28 13:04:07
milo
Red Team (CNA)
In this article, we will explore how the deadmesh project enables internet access over Meshtastic LoRa networks. We will outline its features and explain how to get started with deadmesh

Welcome back, aspiring cyberwarriors!





As you probably already know, Meshtastic is an open-source project that turns cheap LoRa radios into long-range mesh networking devices. It works great for sending texts and telemetry, such as GPS coordinates and sensor data, but it wasn’t meant for surfing the web or sending emails. If you tried to browse a website or send an email over a Meshtastic network, you’d be out of luck because each protocol would require its own special setup.





Deadmesh comes in to fix this by acting as a bridge. On the mesh side, it uses the native Meshtastic protobuf serialization API. On the Internet side, it “speaks” every protocol your applications already use, such as HTTP/HTTPS, SMTP, IMAP, DNS, FTP, SOCKS4, SOCKS5, and WebSocket. Your apps don’t even need to know that their traffic is split into tiny 220-byte LoRa packets and reassembled on the other end of a radio link. To them, it’s just like a regular proxy.





The project describes itself pretty straightforwardly as “A resilient text-first Internet bridge for mesh radios: Update your blog from a can on a string from the smoldering rubble.” That line pretty much sums up who this is aimed at.





In this article, we will explore how the deadmesh project enables internet access over Meshtastic LoRa networks. We will outline its features and explain how to get started with deadmesh. Let’s get rolling!





Step #2: How deadmesh Works Under the Hood?





Basically, deadmesh acts as a man-in-the-middle between your applications and the Internet, using a LoRa mesh network powered by inexpensive hardware. The gateway machine, whether a Raspberry Pi or Linux, has two primary roles: it communicates with the Meshtastic radio over a USB serial connection and connects to the Internet via your chosen uplink, such as Ethernet. All data flowing between these two facets passes through deadmesh, which manages the necessary translations.









When deadmesh starts, it establishes communication with the Meshtastic radio over the USB serial connection. It opens the port at 115200 baud and sends a want_config message encoded in the Meshtastic Protocol Buffers format. This handshake instructs the radio to send all available information, such as its node ID, current configuration, channel list, and a NodeInfo record for every device previously detected on the mesh. Deadmesh compiles this data into an in-memory node table, creating a live snapshot of present devices along with their hop distances, battery levels, and last communication timestamps. Following this, every packet the radio receives over the air is forwarded to deadmesh via the serial link using a binary framing format that starts with two bytes (0x94 0xC3), followed by a two-byte big-endian length and the Protocol Buffers payload. Deadmesh continuously scans this stream for synchronization bytes. If the stream becomes corrupted, the state machine can recover automatically by scanning forward until it finds the next valid sequence.





When a new connection arrives at the proxy port, deadmesh automatically identifies the traffic type by analyzing the first few bytes. For example, it recognizes GET or POST as plain HTTP, while a connection starting with CONNECT host:443 signals an HTTPS tunnel request. The byte 0x05 indicates a SOCKS5 client, and EHLO or HELO indicates an SMTP session. For HTTPS specifically, deadmesh uses full TLS interception, which means it presents the client with a newly generated certificate signed by the local CA you installed during setup. It terminates the TLS session, inspects the plaintext request, and sets up a new TLS connection to the actual destination server. While this allows the gateway to see plaintext traffic, it also enables responses to be cached and compressed before transmission over the expensive mesh link.





A critical engineering challenge arises when considering that a standard HTTP response for even a modest web page can exceed 50 kilobytes. With a single Meshtastic LoRa packet carrying approximately 220 bytes of payload, a web page must be divided into around 230 individual radio packets, each requiring transmission, reception, and reassembly in the correct order. Deadmesh addresses this with a fragmentation engine that splits outgoing data into chunks of up to 220 bytes, assigns each chunk a sequence number and session identifier, and wraps it in a Meshtastic packet addressed to the destination node on port 100, which is reserved for deadmesh traffic. All other port numbers, such as those for text messages or GPS locations, are processed normally to maintain the node table, while port number 100 packets direct traffic specifically to the proxy session manager. On the receiving end, the reassembly engine buffers incoming chunks, reorders any that arrive out of sequence, and reconstructs the original payload once all fragments are received. If a fragment is lost during transit, which can happen on any radio link, the acknowledgment timeout triggers a retransmission request, allowing the gateway to resend only the missing chunk instead of the entire payload.





It’s important to clarify what “mesh” means in this context, as it may seem more complex than it actually is. A Meshtastic mesh operates as a flooding network. When a node transmits a packet, every other node within radio range that hears it will rebroadcast it up to a configurable hop limit, typically three. This means that a packet can travel from a client device to a gateway via multiple intermediate nodes, each acting as a simple relay, without needing to be aware of the full network topology. The hop limit in each packet decreases by one at each relay, and when it reaches zero, the packet is no longer forwarded. This mechanism allows for multi-kilometer coverage using hardware that has a line-of-sight range of approximately two to five kilometers per hop. However, this setup comes with trade-offs in terms of latency and airtime. Each hop introduces a delay of between 500 milliseconds and 5 seconds, and every retransmission by an intermediate relay consumes airtime, which is subject to regulatory duty-cycle limits. In the EU, radios in the 868 MHz ISM band are restricted to around one percent airtime, equating to 36 seconds of transmission per hour. This serves as a hard ceiling on throughput that no software optimization can surpass.





Since each byte transmitted over the mesh consumes valuable airtime, the deadmesh system includes a compression plugin that applies gzip or Brotli compression to HTTP responses before fragmenting them. For typical web content, such as HTML, CSS, and JSON, compression ratios of 3 to 10 times are achievable. For instance, a 50KB web page that would require 230 fragments might compress to 8KB and need only 37 fragments, thus reducing both latency and airtime costs. The caching plugin further enhances this process. If a response is marked as cacheable by its HTTP headers, deadmesh saves it locally on the gateway. The next time any mesh client requests the same resource, deadmesh can serve it directly from the cache without using the LoRa link. For DNS lookups, static assets, and content that doesn’t change often, this can effectively reduce airtime consumption to nearly zero for repeat requests, offering a significant advantage in a duty-cycle-constrained environment.





To illustrate how this works, consider what happens when you run curl -x http://localhost:8080 http://example.com on a mesh client device. The curl command connects to the local deadmesh client process, which detects the HTTP request from the opening bytes. The request is serialized, compressed if it exceeds a minimum threshold, and fragmented into 220-byte chunks. Each chunk is wrapped in a Meshtastic protobuf packet addressed to the gateway node on port 100 and handed to the local Meshtastic radio over serial. The radio transmits these packets over the LoRa channel. Intermediate mesh nodes receive each packet, rebroadcast it, and decrement the hop counter. The gateway’s radio receives the fragments and forwards them to the deadmesh gateway process via its serial connection. The gateway reassembles the fragments, decompresses the payload, and opens a TCP connection to example.com on port 80. The response from example.com then travels back through the same pipeline in reverse, compressed, fragmented, transmitted hop by hop across the mesh, reassembled by the client, and finally delivered to your curl process as if nothing unusual had occurred. Overall, the round-trip time for a typical web page on a two-hop mesh with compression enabled ranges from 10 to 30 seconds. While this speed is slow by modern standards, it operates effectively in challenging environments such as mountainsides, disaster zones, or protests, using hardware that fits in a pocket.





Step #3: Features





One of its standout capabilities is universal protocol support, allowing it to handle any TCP/IP protocol, including HTTPS with TLS interception. Besides that, it fragments larger packets into 220-byte chunks for transmission over LoRa, tagging them with session IDs and sequence numbers for seamless reassembly. Another key feature is the embedded real-time dashboard, accessible on port 8081, which displays live data for each mesh node.





The system also automatically detects Meshtastic devices on the serial port and performs handshakes to process live packets. Through its plugin system, deadmesh can extend functionality with features like ad blocking, rate limiting, and compression, resulting in significant throughput improvements for text content. Additionally, its store-and-forward capability allows traffic to be queued during intermittent connections. Finally, multiple deadmesh instances can run on the same channel.





Step 4: Installation on Linux





Start by installing the build tools and libraries that deadmesh requires:





> sudo apt-get install build-essential pkg-config libglib2.0-dev libssl-dev libjson-glib-dev python3 python3-pip libmicrohttpd-dev protobuf-compiler





> python3 -m venv venv





> source venv/bin/activate





> pip3 install protobuf grpcio-tools









The next step is to clone the repository and build it with dashboard support enabled.





> git clone https://github.com/gnarzilla/deadmesh.git





> cd deadmesh





> make clean && make UI=1









Once the build completes, your compiled binary will be at bin/deadmesh, and the plugin shared libraries will be in bin/plugins/. After that, we can exit the venv.





> deactivate





Next, plug your Meshtastic radio into your computer via USB. Most devices will appear as either /dev/ttyACM0 or /dev/ttyUSB0. Verify with:





> ls -l /dev/ttyACM0 /dev/ttyUSB0 2>/dev/null









You need to add your user to the dialout group so deadmesh can access the serial port without root:





> sudo usermod -a -G dialout $USER





Log out and back in for the group change to take effect.





Deadmesh needs a local CA certificate to intercept HTTPS traffic. Generate one with OpenSSL:





> mkdir -p ~/.deadlight





> openssl genrsa -out ~/.deadlight/ca.key 2048





> openssl req -new -x509 -days 1825 -key ~/.deadlight/ca.key \





-out ~/.deadlight/ca.crt \





-subj “/CN=Deadmesh Local CA/O=Deadlight/C=US”









Install it as a trusted CA on your system:





> sudo cp ~/.deadlight/ca.crt /usr/local/share/ca-certificates/deadmesh.crt





> sudo update-ca-certificates










The next step is to edit a deadmesh.conf file in the project directory. Use absolute paths for the certificate files; the tilde shortcut will expand to /root/ if you run with sudo, which is almost certainly wrong:









Finally, we can run the gateway:





./bin/deadmesh -c deadmesh.conf -v









Your dashboard is now live at http://localhost:8081





Step 5: Preparing the Client Device





The client radio that isn’t connected to the Linux machine needs extra configuration for routing traffic through the deadmesh gateway. If you’re using a smartphone with the Meshtastic app, set the HTTP proxy address in the app settings to the IP of your Linux gateway on port 8080. This will ensure that any browser or app on the phone that respects the system proxy routes its traffic through the mesh. For laptops or other Linux machines with their own LoRa radio, make sure to set the proxy environment variables in the terminal or use alternative proxy applications.





If your client is a T-Echo operating as a standalone device, it communicates with the gateway radio wirelessly, while the proxy configuration occurs on the device connected to the T-Echo, usually a Bluetooth-paired phone running the Meshtastic app. Once your gateway is up and running on the Linux machine with the radio connected and operational, confirm that the client radio is powered on and in range to send traffic over the mesh. To verify the connection, access the dashboard at http://localhost:8081 on your gateway machine and check for active links, packets relayed, and gateway uptime.









The dashboard will also display mesh nodes and messages sent over the network.









Summary





Deadmesh is a genuinely useful and technically impressive software solution for anyone working in environments where reliable connectivity is not guaranteed. It addresses a significant issue related to the lack of general Internet access over Meshtastic mesh networks and does so without requiring any modifications to client applications.





However, there are important caveats to consider. LoRa technology is inherently slow, and duty cycle regulations impose strict limits on throughput. Additionally, this project is still in its early stages and currently has only one maintainer. Therefore, it is best suited for operators who understand its limitations and are prepared to fine-tune and troubleshoot it in the field.





If you want to delve deeper, consider exploring Network Basics training. This will enable you to experiment with mesh networks and ultimately develop skills to attack and secure them.



Source: HackersArise
Source Link: https://hackers-arise.com/off-grid-communications-part-6-internet-over-lora-with-deadmesh/


Comments
new comment
Nobody has commented yet. Will you be the first?
 
Forum
Red Team (CNA)



Copyright 2012 through 2026 - National Cyber Warfare Foundation - All rights reserved worldwide.