<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Mqtt on Philly Mesh</title><link>https://prm.boda.dev/tags/mqtt/</link><description>Philly Mesh (Mqtt)</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Sat, 10 Jan 2026 21:19:45 -0500</lastBuildDate><atom:link href="https://prm.boda.dev/tags/mqtt/index.xml" rel="self" type="application/rss+xml"/><item><title>Real-Time Meshtastic Decoding with Scapy and Wireshark</title><link>https://prm.boda.dev/2026/01/10/scapy-meshtastic-decoder/</link><pubDate>Sat, 10 Jan 2026 21:19:45 -0500</pubDate><author>Caleb Frey</author><guid>https://prm.boda.dev/2026/01/10/scapy-meshtastic-decoder/</guid><description>&lt;h1 id="the-goal" >The Goal
&lt;span>
&lt;a href="#the-goal" title="Direct Link to The Goal">
&lt;svg viewBox="0 0 28 23" height="100%" width="19" alt="" xmlns="http://www.w3.org/2000/svg">&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;/svg>
&lt;/a>
&lt;/span>
&lt;/h1>
&lt;p>When I powered on my first Meshtastic node, I was blown away at the ability to exchange messages with people over multiple hops without even needing a license.
That awe lasted about a week before I noticed that sometimes the intended recipient never saw it.
Or the messages would often go unacknowledged, leaving me to wonder whether anyone saw it at all.
So I decided to do some digging to figure out why the message delivery was so inconsistent.&lt;/p>
&lt;p>I dug into the Meshtastic &lt;a href="https://meshtastic.org/docs/introduction/">documentation&lt;/a> to learn about the &amp;ldquo;managed flooding&amp;rdquo; broadcase approach to understand how a packet gets transmitted.
In summary, the stronger a signal is for a given packet, the longer a node will wait before transmitting it, and it won&amp;rsquo;t transmit if it already heard others rebroadcast it.
Theoretically this helps a signal travel as far as possible, with the assumption that weaker signal corresponds to a further distance.
But since we don&amp;rsquo;t live in a perfect spherical vacuum, you end up with strange routes like a node in someone&amp;rsquo;s basement becoming the preferred hop when it&amp;rsquo;s the least useful.
It seems chaotic and strange but it makes sense when the system is designed for a group of nodes in constantly changing conditions and locations (and outdoor usage).
However, I wasn&amp;rsquo;t content to just read about the broadcast approach, I wanted to see it in real time, from the perspective of my node here in Philly.&lt;/p>
&lt;p>The Meshtastic client apps (at least for web and android) are designed first and foremost for usability, and as a result hide away a lot of the underlying networking.
I wanted to be able to see all the Meshtastic packets in the air, shown live in a tool like Wireshark for dissection and analysis.
It&amp;rsquo;s possible to enable debugging mode in the app, but that requires a consistent connection to the phone app, where the data isn&amp;rsquo;t particularly easy to parse.
There is also the option to enable serial debugging, but it wouldn&amp;rsquo;t use the existing usb c link and I didn&amp;rsquo;t love the idea of running flying leads to a USB serial converter.
Thankfully, since the Meshtastic protocol is open source, there wasn&amp;rsquo;t any requirement that I even use a Meshtastic node.
I&amp;rsquo;ll write my own receive-only client! How hard could it be?&lt;/p>
&lt;h1 id="hardware-pulling-lora-from-the-airwaves" >Hardware: Pulling LoRa from the Airwaves
&lt;span>
&lt;a href="#hardware-pulling-lora-from-the-airwaves" title="Direct Link to Hardware: Pulling LoRa from the Airwaves">
&lt;svg viewBox="0 0 28 23" height="100%" width="19" alt="" xmlns="http://www.w3.org/2000/svg">&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;/svg>
&lt;/a>
&lt;/span>
&lt;/h1>
&lt;p>All Meshtastic Devices amount to a LoRa modem and something to run the meshtastic device code, usually a microcontroller.
So if I wanted to decode Meshtastic, I needed some form of LoRa modem that could be plugged into my PC.
Thankfully, someone in the PhillyMesh Community had already purchased a &lt;a href="https://electroniccats.com/store/catwan-usb-stick/">CatWaN USB Stick&lt;/a> with similar intentions and let me borrow it.
This USB device consists of an RP2040 microcontroller, a RFM95W Modem and not much else, which is exactly what I wanted.&lt;/p>
&lt;p>To get the data from USB Stick to the computer, I wrote some simple firmware as for the CatWAN as if it were a Raspberry Pi Pico, since it&amp;rsquo;s the same underlying chip.
I configured the LoRa module with the parameters to match the &lt;a href="https://meshtastic.org/docs/overview/radio-settings/#presets">LongFast Radio Preset&lt;/a>, along with the default frequency (906.875MHz) and sync word (&lt;code>0x2B&lt;/code>).
Every time a new LoRa signal with those parameters arrived, it was encapsulated with &lt;a href="https://github.com/eriknl/LoRaTap/">LoRaTap&lt;/a>, which is mostly a header with some radio information, and written to USB Serial.
To distinguish the end of one transmission from the start of another (and avoid the &lt;code>\n&lt;/code> vs &lt;code>\r\n&lt;/code> conflict) I terminated each packet with a special byte sequence unlikely to be in the real data.&lt;/p>
&lt;h1 id="software" >Software
&lt;span>
&lt;a href="#software" title="Direct Link to Software">
&lt;svg viewBox="0 0 28 23" height="100%" width="19" alt="" xmlns="http://www.w3.org/2000/svg">&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;/svg>
&lt;/a>
&lt;/span>
&lt;/h1>
&lt;p>Now that I had an incoming stream of LoRa packets I had to learn how to decode them.
The wonderful folks selling the &lt;a href="https://www.hackerpager.net/">HackerPager&lt;/a> had already written a Meshtastic decoder plugin for Wireshark to be used on captured .pcap files, but I didn&amp;rsquo;t have pcap files.
After reading the &lt;a href="https://ietf-opsawg-wg.github.io/draft-ietf-opsawg-pcap/draft-ietf-opsawg-pcap.html">specifications for a pcap file&lt;/a> I wrote a script that encapsulated the incoming LoRaTap stream into a valid stream of pcap data.
Each pcap data stream must begin with a pcap header that includes the correct &lt;a href="https://datatracker.ietf.org/doc/html/draft-ietf-opsawg-pcaplinktype-16">link type&lt;/a> (270 for LoRaTap),
followed by the individual packets, each of which had to be wrapped with timestamp and other capture information.&lt;/p>
&lt;p>Once I was generating valid pcap files and followed the guide to install the HackerPager plugin, I was finally able to see all the Meshtastic traffic happening around me during that capture.
Wireshark supports pcap streams via stdin, so after a few tweaks (and discovering that powershell doesn&amp;rsquo;t do normal byte-friendly piping) I had a live view of all the meshtastic traffic around me.
This was an amazing sight, being able to see &amp;ldquo;hello world&amp;rdquo; messages pinging back and forth between nodes, but I didn&amp;rsquo;t plan to stop at Wireshark.
I wanted data collection and analytics, and I wasn&amp;rsquo;t planning to do it all using Wireshark and Lua.&lt;/p>
&lt;p>Enter: &lt;a href="https://scapy.net/">Scapy&lt;/a> - a packet manipulation library for Python. Think of it like Wireshark but with the ability to assemble and modify packets, not just read them.
Scapy decodes packets into individual layers, and includes many built-in layers, from HTTP and the OSI model to CAN bus protocols.
Unsurprisingly, it doesn&amp;rsquo;t include anything for Meshtastic, so I had to add those layers myself.&lt;/p>
&lt;h2 id="dissecting-a-meshtastic-packet" >Dissecting a Meshtastic Packet
&lt;span>
&lt;a href="#dissecting-a-meshtastic-packet" title="Direct Link to Dissecting a Meshtastic Packet">
&lt;svg viewBox="0 0 28 23" height="100%" width="19" alt="" xmlns="http://www.w3.org/2000/svg">&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;/svg>
&lt;/a>
&lt;/span>
&lt;/h2>
&lt;p>Using the Meshtastic documentation to understand the protocol, the HackerPager Wireshark plugin as a reference implementation,
and many many tabs of Scapy documentation, I was able to identify and decode the contents of each layer in the meshtastic packet.
I&amp;rsquo;ll walk you through them.&lt;/p>
&lt;h3 id="layer-1-loratap" >Layer 1: LoRaTap
&lt;span>
&lt;a href="#layer-1-loratap" title="Direct Link to Layer 1: LoRaTap">
&lt;svg viewBox="0 0 28 23" height="100%" width="19" alt="" xmlns="http://www.w3.org/2000/svg">&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;/svg>
&lt;/a>
&lt;/span>
&lt;/h3>
&lt;ul>
&lt;li>Mostly just an encapsulation format that Wireshark and other tools can decode&lt;/li>
&lt;li>Includes received radio information including LoRa config and SNR/RSSI&lt;/li>
&lt;li>Sync Word - byte that can be used to set a protocol
&lt;ul>
&lt;li>Need all your LoRa devices to have the same sync word&lt;/li>
&lt;li>Meshtastic = 0x2B, LoRaWan uses 0x34&lt;/li>
&lt;li>Think of this like a VLAN ID&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Message size&lt;/li>
&lt;/ul>
&lt;h3 id="layer-2-meshpacket" >Layer 2: MeshPacket
&lt;span>
&lt;a href="#layer-2-meshpacket" title="Direct Link to Layer 2: MeshPacket">
&lt;svg viewBox="0 0 28 23" height="100%" width="19" alt="" xmlns="http://www.w3.org/2000/svg">&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;/svg>
&lt;/a>
&lt;/span>
&lt;/h3>
&lt;ul>
&lt;li>Unencrypted protobuf that all nodes can read&lt;/li>
&lt;li>Routing information so other nodes can relay the packet
&lt;ul>
&lt;li>Source and destination radio IDs&lt;/li>
&lt;li>Packet ID (used for deduplication and encryption)&lt;/li>
&lt;li>Hop information
&lt;ul>
&lt;li>Hop limit is how many hops are &amp;ldquo;left&amp;rdquo;&lt;/li>
&lt;li>Hop start is how many hops it started with&lt;/li>
&lt;li>Last hop data to do some intelligent routing&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Channel hash to speed up decryption&lt;/li>
&lt;/ul>
&lt;h3 id="layer-3-meshpayload" >Layer 3: MeshPayload
&lt;span>
&lt;a href="#layer-3-meshpayload" title="Direct Link to Layer 3: MeshPayload">
&lt;svg viewBox="0 0 28 23" height="100%" width="19" alt="" xmlns="http://www.w3.org/2000/svg">&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;/svg>
&lt;/a>
&lt;/span>
&lt;/h3>
&lt;ul>
&lt;li>Encrypted protobuf containing the actual data&lt;/li>
&lt;li>Encrypted with AES256-CTR stream cipher
&lt;ul>
&lt;li>Uses the channel key and packet ID to encrypt/decrypt&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&amp;ldquo;Port Number&amp;rdquo; determines what app protocol is being used&lt;/li>
&lt;li>Additional metadata like request/reply IDs and the source/dest ID&lt;/li>
&lt;/ul>
&lt;h3 id="layer-4-meshapp-or-meshtext" >Layer 4: MeshApp or MeshText
&lt;span>
&lt;a href="#layer-4-meshapp-or-meshtext" title="Direct Link to Layer 4: MeshApp or MeshText">
&lt;svg viewBox="0 0 28 23" height="100%" width="19" alt="" xmlns="http://www.w3.org/2000/svg">&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;/svg>
&lt;/a>
&lt;/span>
&lt;/h3>
&lt;ul>
&lt;li>This is the end-user functionality of the device&lt;/li>
&lt;li>Remaining data in the LoRa packet is decoded as a protobuf according to the port number&lt;/li>
&lt;li>Applications include:
&lt;ul>
&lt;li>Node info&lt;/li>
&lt;li>Position&lt;/li>
&lt;li>Telemetry&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Text messages (port number = 1) contain the message as a binary string&lt;/li>
&lt;/ul>
&lt;p>For each layer I had to define all the fields to be extracted and write the dissection logic to set the values of those fields, including decryption and protobuf decoding.
After I had created each layer I had to &amp;ldquo;register&amp;rdquo; them with the scapy interpreter so it knew to associate the incoming data and subsequent payloads with the correct dissector.&lt;/p>
&lt;p>Once Scapy fully dissected a packet I was able to access the individual fields in each packet as if it were a typical Python object.
Every packet that was processed (if it could be decoded) was added to an SQLite database to record network traffic and create a collection of known nodes based on their periodic NodeInfo broadcasts.
This let me take a look at stats such as airtime utilization by different nodes, protocols, and in general perform long-term trend observation.
I could even grow beyond my single data source with volunteers hosting another instance and sending the results to a central database
in an to get a holistic view of all the Meshtastic traffic in the city.&lt;/p>
&lt;h1 id="the-results" >The Results
&lt;span>
&lt;a href="#the-results" title="Direct Link to The Results">
&lt;svg viewBox="0 0 28 23" height="100%" width="19" alt="" xmlns="http://www.w3.org/2000/svg">&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;/svg>
&lt;/a>
&lt;/span>
&lt;/h1>
&lt;p>Now that I had a process to collect and record all Meshtastic traffic happening around me, without the limits of using a proper Meshtastic node,
I could determine the cause of the inconsistent connectivity if I knew where to look.&lt;/p>
&lt;p>Unfortunately, I didn&amp;rsquo;t see anything obviously symptomatic of an unreliable network and adding advanced analytics, a webUI, and distributed data collection was beyond my skills and interest.
Lucky I was introduced to a tool called &lt;a href="https://github.com/zenitraM/malla">Malla&lt;/a>,
which can collect data from multiple sources using MQTT and display them all in a much slicker WebUI than I would have been able to make.
So rather than reinvent the wheel I started a &lt;a href="https://api.phillymesh.net/">PhillyMesh Malla Instance&lt;/a> with a number of gateways feeding data into the platform.
The one limitation of Malla over the raw LoRa decoding is that by default, nodes don&amp;rsquo;t have &amp;ldquo;Ok to MQTT&amp;rdquo; enabled so we don&amp;rsquo;t have a complete picture,
but I doubt I could convince multiple people to setup a whole mini PC for raw LoRa sniffing, so I think the trade-off is worth it.&lt;/p>
&lt;p>While I didn&amp;rsquo;t end up using this project long-term to learn about our Mesh, I did learn plenty of new things along the way:&lt;/p>
&lt;ul>
&lt;li>I hadn&amp;rsquo;t done embedded development in a very long time and learned about platform.io&lt;/li>
&lt;li>This was my first time dealing with binary data, bitmasking, and endianness&lt;/li>
&lt;li>I had never dealt with protobufs before but now understand why they&amp;rsquo;re used everywhere&lt;/li>
&lt;li>I finally used a proper database, and I&amp;rsquo;m coming around to tolerating SQL after resisting for so long&lt;/li>
&lt;li>I learned that I should continue avoiding low-level cryptography
&lt;ul>
&lt;li>It&amp;rsquo;s a bad sign when you start calling functions with &amp;ldquo;hazmat&amp;rdquo; in the name&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>I also got to show off my project at Jawncon 0x2 and it was so cool to see people interested in something I worked on,
especially those working on the &lt;a href="https://www.kismetwireless.net/">Kismet&lt;/a> RF analysis suite.
The idea that something I wrote as a side project could get integrated into a larger project is very exciting.&lt;/p>
&lt;p>For now it&amp;rsquo;s a mostly-stanalone set of scripts that are tedious to get working, but it&amp;rsquo;s as feature-complete as I plan to make it.
All the source code for this project, including the firmware, build instructions, and sample SQL queries,
are available at &lt;a href="https://github.com/calefrey/scapy-meshtastic">https://github.com/calefrey/scapy-meshtastic&lt;/a>.&lt;/p></description></item><item><title>MQTT Bridge Setup</title><link>https://prm.boda.dev/2025/03/24/mqtt-bridge-setup/</link><pubDate>Mon, 24 Mar 2025 00:00:02 +0000</pubDate><author>Mike Dank (Famicoman)</author><guid>https://prm.boda.dev/2025/03/24/mqtt-bridge-setup/</guid><description>&lt;p>In August 2024 Meshtastic made changes to their official MQTT server due to potential safety issues of third parties tracking and storing user location data. While one of the main Meshtastic node mapping websites &lt;a href="https://meshmap.net/">meshmap.net&lt;/a> continues to rely on the official MQTT server, another popular site &lt;a href="https://meshtastic.liamcottle.net/">meshtastic.liamcottle.net&lt;/a> now runs their own separate MQTT server.&lt;/p>
&lt;p>While MQTT can be leveraged to connect Meshtastic nodes to one another over-the-Internet to bridge separated networks or isolated nodes, many people instead use this feature specifically for contributing to node maps so others can see what nodes may be operating in their area. As already outlined, there are now two separate MQTT servers for node maps. However, the Meshtastic application only allows one MQTT server to be configured per node, which requires the user to make a choice of which one they will use and ultimately which site they will not contribute to.&lt;/p>
&lt;p>Luckily, there is another approach that can be used to reliably send data to multiple MQTT servers: creating an MQTT bridge. This bridge can act as an intermediary, allowing Meshtastic nodes to send it data which is then forwarded to other servers.&lt;/p>
&lt;p>Here we can see how to set up a server that feeds to both &lt;code>mqtt.meshtastic.org&lt;/code> and &lt;code>mqtt.meshtastic.liamcottle.net&lt;/code>.&lt;/p>
&lt;h2 id="installation--base-config" >Installation &amp;amp; Base Config
&lt;span>
&lt;a href="#installation--base-config" title="Direct Link to Installation &amp;amp; Base Config">
&lt;svg viewBox="0 0 28 23" height="100%" width="19" alt="" xmlns="http://www.w3.org/2000/svg">&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;/svg>
&lt;/a>
&lt;/span>
&lt;/h2>
&lt;p>This guide assumes a Debian Linux system with a non-root, &lt;code>sudo&lt;/code> user.&lt;/p>
&lt;p>First, we will install &lt;code>mosquitto&lt;/code> as our MQTT server of choice:&lt;/p>
&lt;pre tabindex="0">&lt;code>$ sudo apt install mosquitto
&lt;/code>&lt;/pre>&lt;p>Now we will add the initial configuration:&lt;/p>
&lt;pre tabindex="0">&lt;code>$ sudo cat /etc/mosquitto.conf
# Place your local configuration in /etc/mosquitto/conf.d/
#
# A full description of the configuration file is at
# /usr/share/doc/mosquitto/examples/mosquitto.conf.example
allow_anonymous false
listener 1883 0.0.0.0
pid_file /run/mosquitto/mosquitto.pid
persistence true
persistence_file mosquitto.db
persistence_location /var/lib/mosquitto/
# Uncomment for logging
# log_dest file /var/log/mosquitto/mosquitto.log
# log_type all
include_dir /etc/mosquitto/conf.d
password_file /etc/mosquitto/pwfile
&lt;/code>&lt;/pre>&lt;p>Now we will generate a password for the &lt;code>phillymesh&lt;/code> user to authenticate with:&lt;/p>
&lt;pre tabindex="0">&lt;code>$ sudo touch /etc/mosquitto/pwfile
$ sudo mosquitto_passwd -c /etc/mosquitto/pwfile phillymesh
&lt;/code>&lt;/pre>&lt;h2 id="adding-bridges" >Adding Bridges
&lt;span>
&lt;a href="#adding-bridges" title="Direct Link to Adding Bridges">
&lt;svg viewBox="0 0 28 23" height="100%" width="19" alt="" xmlns="http://www.w3.org/2000/svg">&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;/svg>
&lt;/a>
&lt;/span>
&lt;/h2>
&lt;p>Additional configuration can be added to &lt;code>/etc/mosquitto/conf.d/&lt;/code>, so let&amp;rsquo;s create a file for each of our bridges:&lt;/p>
&lt;pre tabindex="0">&lt;code>$ sudo cat /etc/mosquitto/conf.d/mqtt.meshtastic.org.conf
connection mqtt_meshtastic.org
address mqtt.meshtastic.org:1883
# Username and password for the upstream server
remote_username meshdev
remote_password large4cats
# MQTT version to use
bridge_protocol_version mqttv311
# Forward all traffic from msh/*/2/map/ to the remote server
topic msh/+/2/map/# out 0
topic msh/# out 0
# Enable encryption
use_identity_as_username false
bridge_insecure true
# Bridge settings to manage the connection
cleansession true
notifications false
start_type automatic
try_private true
restart_timeout 10
&lt;/code>&lt;/pre>&lt;pre tabindex="0">&lt;code>$ sudo cat /etc/mosquitto/conf.d/mqtt.meshtastic.liamcottle.net.conf
connection mqtt_meshtastic_liamcottle_net
address mqtt.meshtastic.liamcottle.net:1883
# Username and password for the upstream server
remote_username uplink
remote_password uplink
# MQTT version to use
bridge_protocol_version mqttv311
# Forward all traffic from msh/*/2/map/ to the remote server
topic msh/+/2/map/# out 0
topic msh/# out 0
# Enable encryption
use_identity_as_username false
bridge_insecure true
# Bridge settings to manage the connection
cleansession true
notifications false
start_type automatic
try_private true
restart_timeout 10
&lt;/code>&lt;/pre>&lt;h2 id="finishing-touches" >Finishing Touches
&lt;span>
&lt;a href="#finishing-touches" title="Direct Link to Finishing Touches">
&lt;svg viewBox="0 0 28 23" height="100%" width="19" alt="" xmlns="http://www.w3.org/2000/svg">&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;/svg>
&lt;/a>
&lt;/span>
&lt;/h2>
&lt;p>&lt;code>mosquitto&lt;/code> leverages &lt;code>systemd&lt;/code> to run as a service, so let&amp;rsquo;s start it up:&lt;/p>
&lt;pre tabindex="0">&lt;code>$ sudo systemctl enable --now
&lt;/code>&lt;/pre>&lt;p>Make sure that port &lt;code>1883&lt;/code> is open in the firewall for client connections:&lt;/p>
&lt;pre tabindex="0">&lt;code>$ sudo iptables -L | grep 1883
ACCEPT tcp -- anywhere anywhere tcp dpt:1883
&lt;/code>&lt;/pre>&lt;h2 id="client-configuration" >Client Configuration
&lt;span>
&lt;a href="#client-configuration" title="Direct Link to Client Configuration">
&lt;svg viewBox="0 0 28 23" height="100%" width="19" alt="" xmlns="http://www.w3.org/2000/svg">&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;/svg>
&lt;/a>
&lt;/span>
&lt;/h2>
&lt;p>We will assume that the Meshtastic node is connected to the Internet already via WiFi/ethernet.&lt;/p>
&lt;p>Client configuration can be set as follows for &lt;strong>MQTT&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>MQTT enabled: &lt;em>on&lt;/em>&lt;/li>
&lt;li>Address: IP or FQDN of your server&lt;/li>
&lt;li>Username: Username you defined&lt;/li>
&lt;li>Password: Password you defined&lt;/li>
&lt;li>Encryption enabled: &lt;em>on&lt;/em>&lt;/li>
&lt;li>JSON output enabled: &lt;em>off&lt;/em>&lt;/li>
&lt;li>TLS enabled: &lt;em>off&lt;/em>&lt;/li>
&lt;li>Root topic: &lt;em>msh/country/state&lt;/em> (Needs to be specific for &lt;code>mqtt.meshtastic.org&lt;/code>, for example: &lt;em>msh/US/PA&lt;/em>)&lt;/li>
&lt;li>Proxy to client enabled: &lt;em>off&lt;/em>&lt;/li>
&lt;li>Map Reporting: &lt;em>on&lt;/em>&lt;/li>
&lt;li>Precise location &lt;em>off&lt;/em> and minimum of &lt;em>1194 ft&lt;/em> to comply with &lt;code>mqtt.meshtastic.org&lt;/code>&lt;/li>
&lt;li>Map reporting interval (seconds): &lt;em>900&lt;/em>&lt;/li>
&lt;/ul>
&lt;p>Client configuration can be set as follows for &lt;strong>Channels &amp;gt; LongFast&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Uplink enabled: &lt;em>on&lt;/em>&lt;/li>
&lt;li>Downlink enabled: &lt;em>off&lt;/em>&lt;/li>
&lt;li>Position enabled: &lt;em>on&lt;/em>&lt;/li>
&lt;li>Precise location &lt;em>off&lt;/em> and minimum of &lt;em>1194 ft&lt;/em> to comply with &lt;code>mqtt.meshtastic.org&lt;/code>&lt;/li>
&lt;/ul>
&lt;h2 id="sources" >Sources
&lt;span>
&lt;a href="#sources" title="Direct Link to Sources">
&lt;svg viewBox="0 0 28 23" height="100%" width="19" alt="" xmlns="http://www.w3.org/2000/svg">&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" fill="none" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>&lt;/svg>
&lt;/a>
&lt;/span>
&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://www.reddit.com/r/meshtastic/comments/1f04xdu/is_it_possible_to_connect_to_two_mqtt_servers_at/">https://www.reddit.com/r/meshtastic/comments/1f04xdu/is_it_possible_to_connect_to_two_mqtt_servers_at/&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://cedalo.com/blog/mosquitto-bridge-configuration/#Bridging_multiple_brokers">https://cedalo.com/blog/mosquitto-bridge-configuration/#Bridging_multiple_brokers&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://adrelien.com/blog/how-to-host-your-own-mqtt-for-your-meshtastic-nodes/">https://adrelien.com/blog/how-to-host-your-own-mqtt-for-your-meshtastic-nodes/&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://meshtastic.org/docs/configuration/module/mqtt/#connect-to-the-default-public-server">https://meshtastic.org/docs/configuration/module/mqtt/#connect-to-the-default-public-server&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.reddit.com/r/meshtastic/comments/1cneou7/deleted_by_user/">https://www.reddit.com/r/meshtastic/comments/1cneou7/deleted_by_user/&lt;/a>&lt;/li>
&lt;/ul></description></item></channel></rss>