Spyke

Posts

Reticulum·Reticulum Networkbyignirtoq

[Update] No Native Layer 3 Interface?

I would link to my last post, but I don't know how to do that so that it works cross instance. I have two older posts with the same title (first one without the [Update] portion), so they should be easy to find on your local instance.

So I underestimated the differences between user-space software development and developing for the kernel. "This weekend" became 4 months, largely while I had to learn how to find information. I had several false starts, the most costly of which was trying to understand and mirror the IP stack. That was way more complicated than I needed, and abandoning trying to hook into the sockets API made the result much more manageable. I settled on a custom character device, /dev/rns, that user-space programs open a regular file descriptor with. They then use read() to receive messages and write() to send them, and ioctl() calls set Reticulum-specific metadata, like a program's Reticulum destination address.

Anyway, today I finished the MVP. I've put it up on Codeberg here. It does the minimal possible to meet the requirements of "over Ethernet and not on top of IP," so there are several known issues and limitations I'll discuss at the end. It's also still very experimental, so the installation process is still rough. I'll put the details in a separate section as well, but the basic summary is four steps: build and install the module, install the Python interface file for the reference Python-based Reticulum rnsd to use, update your rnsd configuration to use the custom interface, and run rnsd either as root or a user in a special group with a specific capability (detailed in the setup instructions).

Its limitations means you probably shouldn't use it as your daily-driver Reticulum interface, but I hope to get it to that level very soon. My next steps are to see if I can get it to integrate with rns-rs so I can run it on my OpenWRT router and get my multi-router home network setup. And long term I want to have as much of a full rnsd implementation in the kernel module as possible, so that it can efficiently handle routing, MAC addressing, and other parts.

If anyone is interested in working on this with me, please let me know! I would love to have others on this project with me!

Installation

Prerequisites: You will need the Linux kernel headers for the version of the kernel your desired destination system is running, a C compiler, and make. You will need root permissions on the destination system in order to load the kernel module and either run rnsd as root or configure the system so that you can run it rootless.

  1. Clone the repository and build the kernel module with make. Do not install it at this stage unless you plan to run it as root.
  2. (Optional; for rootless usage) Run the install.sh script to create a new group, called rns-net by default, and a udev rule to set the /dev/rns node ownership and permissions for group access when the device node is created by installing the kernel module.
  3. Install the kernel module with sudo insmod rns.ko.
  4. (Optional; for rootless usage) Run the install-service.sh script to create a systemd service for your existing Python rnsd program. This gives it the CAP_NET_RAW capability at run time as an alternative to giving the Python interpreter the capability permanently, which is a greater security risk.
  5. Install the KernelEthernetInterface.py file in your (or root's) ~/.reticulum/interfaces directory, and update your (or root's) ~/.reticulum/config file following the example.
  6. Start the rnsd executable either with the systemd service for rootless execution (sudo systemctl start rns) or as root.

Limitations and Known Issues

The upside to this module is it's not like other Reticulum interfaces that take a bit of configuration and some specialized knowledge (other than building and installing the kernel module, but I plan to simplify that process dramatically in the future). The configuration is setting some rnsd fields (type and enabled) and then setting the network interface you want it to use. That's it. With that, I didn't need a backbone on the network for UDP discovery or anything. My two test devices just found each other; running NomadNet on both was kind of magical in that respect.

That being said, there are quite a few issues. One is, since the kernel module isn't doing the routing, all packets are addressed to the MAC broadcast address, so all other devices on your network have to determine if the packet is meant for them. Another limitation is that, since I picked an arbitrary unused Ethertype value, no network equipment that's not running this module will understand what that traffic is, and will likely drop it. That means it's local network only; your ISP won't understand it and will drop it.

Finally, I took some shortcuts on the implementation, intending to flesh it out later. IFAC is completely unsupported, and because of that and a lower limit on the size of valid Ethernet frames, very small packets will have zero-pad bytes at the end that will likely make them unintelligible to the reference rnsd. I think this will only apply to unencrypted packets, which are an extremely niche case, so I don't think you will encounter this issue in practice.

The excitement of loading the kernel module on my two test machines and sending messages between them with NomadNet is a feeling I haven't experienced in probably the last 5+ years of my software development career. I will definitely be continuing with this project.

View original on feddit.online
6
Reticulum·Reticulum Networkbyignirtoq

[Update] No Native Layer 3 Interface?

A few days ago I asked about an OSI layer 3 interface for reticulum because the interfaces in the reference implementation that go over Ethernet/WiFi are all implemented on top of protocols that use IP. I asked if there were any good reasons why one isn't provided, and if not I would try writing my own. Well I wrote my own prototype (hosted on Codeberg here), and in the process I think I've answered my own questions.

In order to write a layer 3 protocol in user space, I had to create a layer 2 socket to read the Ethernet frames. In Linux, you can only do so as root, so my implementation has to be run as root, which comes with a bunch of its own issues. Separate to the must-be-run-as-root issue, since I'm reading the raw Ethernet frames, the socket my Python script creates bypasses the Linux kernel's normal routing of traffic on that network interface. This means all traffic on that interface is routed to the Python script, so if you want to use that hardware interface for anything else besides reticulum traffic, the Python script will block that (it drops frames it doesn't recognize).

From what I can tell, the standard way to do all of this in Linux is to write a kernel module that registers packet routing functions with the kernel for handling the Ethernet frames associated with your protocol, and then those kernel module functions will pass the data to the right process in user space. I'm guessing Mark Qvist weighed the pros and cons of requiring a kernel module and opted for implementations on top of protocols already provided in the Linux kernel (and other OS kernels) to make it as easy as possible to get started. But now that there's a solid community around reticulum, I don't see a reason we couldn't write a kernel module and a new interface that uses it (if available), so I'm going to give that a try over the weekend. Given the packet structure and routing architecture of reticulum, I think there's actually very little code that must go in the kernel. I'll see how far I can get.

View original on feddit.online
12
Reticulum·Reticulum Networkbyignirtoq

No Native Layer 3 Interface?

Hi all. I'm new to reticulum, having found it about 2 weeks ago. I am a software engineer by trade, so it wasn't too big of a learning curve to jump into. I have rnsd and nomadnet running on a pair of Linux devices, RNode running on a pair of Lilygo T-Echo radios to test LoRa with, and I managed to cross-compile rns-rs and get its version of rnsd running on my OpenWRT router (which is an ARM64 architecture with musl for libc, which presented some headaches). My router vendor doesn't provide pip or the cryptography Python library as installable packages, so rather than muck about with firmware and potentially break my home network entirely, it seemed less risky to compile a binary with minimal dynamic libraries to link and run that. Seems to work.

I have read through the Zen of Reticulum, particularly the Death to the Address section, and I interpreted that as a project goal to replace the Internet Protocol (i.e. IP), a layer 3 protocol in the OSI model. The Hardware section of reticulum.network also seems to jive with that interpretation, as "Any ethernet device" is listed separately from "TCP over IP networks" and "UDP over IP networks."

However, when I read through the Configuring Interfaces section of the manual, all of the options for Ethernet/WiFi seem to be built on top of either TCP or UDP, which are themselves built on IP. The AutoInterface uses UDP, the BackboneInterface uses TCP, there are specific TCP and UDP interfaces, and then everything else seems to be for more specialized connections (RNodes, serial connections, amateur radio, etc.) or compatibility interfaces with other cryptographic or anonymization protocols (I2P and Yggdrasil). Am I missing something?

I'm not a low-level network programmer, so I am definitely out of my element here and wanted to check with others who may be more knowledgeable in the domain. I have done some reading on building Ethernet frames and was planning to try my hand at writing some kind of EthernetInterface using the Custom Interfaces API, but if there's a reason such an implementation doesn't exist, and I would be wasting my time, I wanted to ask. I was planning to do a Python implementation as a prototype and then write an extension to rns-rs to try on my router.

Update : Small update. I have a prototype Python implementation working on my home devices. There's a big caveat to my implementation: in order to get access to raw Ethernet frames required by this interface, rnsd needs to be run as root. This makes sense to me because differentiation of network traffic data packets is typically handled by TCP and UDP sockets, so layer 4. I'm doing a layer 3 implementation, so working with layer 2 data, where we have no differentiation of what owns what data, so it has to be handled by root (and honestly should probably be handled in the kernel). This appears to require other processes that want to share the transport instance (e.g. NomadNet) to run as root as well, but I could be doing that part wrong. If any of my reasoning is flawed here, please let me know! Otherwise, I need to clean up error-handling and then I'll post my code on a new repository on Codeberg.

View original on feddit.online
19

You reached the end