Closed 4c3e closed 2 years ago
This is a great proposal. Thanks for bringing it up. Since I only know the basics about i2p, I will have to do a bit of reading up to understand how we can best integrate with it.
I can’t see why we shouldn’t add this, so let’s do it.
Would the user need to also run an i2p node/daemon/something on their computer, or is the published python libraries enough to get connected over SAM?
I’d be happy to accept a pull request for an I2PInterface, if you feel like you have the time to do it. If you want to go ahead and add it, you can probably use some guidance on the lesser documented aspects of how the current TCPInterface works, namely tunnel synthesis and re-spawning after link drops, which I assume would be very useful (and necessary) for i2p connections as well.
I’ll go read up a bit on i2p as soon as I can. If you have some recommended links to get me started quickly, I’d appreciate them.
Thanks!
Great! I'll start working towards an I2pInterface implementation. I think reading through the UDP/TCP interface files will give me a good enough background to get started. If I run into any blockers, or have questions about these implementations, I'll probably add a comment in this issue.
Would the user need to also run an i2p node/daemon/something on their computer, or is the published python libraries enough to get connected over SAM?
Yes, a user hoping to use a reticulum i2p interface would need to run rnsd and also an i2p router, with the SAM interface enabled. Currently there is a GUI Java router with many bells and whistles, and the streamlined i2pd C++ router which is meant for less powerful computers like raspberry pi's or other SBCs.
Here are some links that should be useful: https://geti2p.net/en/about/intro https://geti2p.net/en/comparison/tor https://geti2p.net/en/docs/api/sam
It also might be possible to use the existing TCPInterface over an i2p tunnel, here is an article explaining how to tunnel ssh through the i2p network: https://eyedeekay.github.io/i2p-i2pd-sshsetup/
@markqvist here is a test you might be interested in running. I just attempted to connect two reticulum nodes using the TCPClient/Server interfaces, tunneled through the i2p network. This test requires two computers with RNS and an i2p router installed on both. I am using the latest version of pip3 install RNS, with 1.6.1-0-1~bionic+1 version of the i2p java router.
Follow the guide for setting up an i2p server tunnel listed in https://eyedeekay.github.io/i2p-i2pd-sshsetup/. An important difference is that I chose to use a high port number like 22222 because its not a ssh connection. Once generated, your server tunnel should have an i2p destination that looks like
Now follow the steps from the guide to set up your client tunnel. The only different step here is to add the port number you chose earlier to the end of the i2p destination. The destination for your client tunnel should look like:
Now you just need to edit the RNS config's on both computers to set up TCPServer/Clients pointing at localhost:port.
You can verify the i2p TCP tunnel is working by running a normal python socket program on the server and client. I am able to successfully run https://github.com/xysun/pychat server and connect to it through this i2p tunnel setup.
Given this i2p tunnel, I had various degrees of success working with Reticulum, I was not able to connect to any nodes over i2p using NomadNet, however I was able to form paths using the TCPInterface, and properly run the Echo.py and Filetransfer.py programs.
Please feel free to reach out if anyone has any questions or comments about this test setup and results.
I was busy with RNode multi-platform suppor for the last few days, but I am going to return to this now. Thanks for the mini-guide, I'll try that out today and see what works and what doesn't.
Did you do any more experiments in the meantime, or have anything else to add?
@4c3e Ok, so I got Reticulum running well over various i2p tunnels today, and had several successful chats using nomadnet connected to the rest of the testnet only over i2p.
I am pretty sure you were having trouble simply due to the TCP timeout and probe parameters configured on the TCP socket by the TCPInterface.
When latency increases to a very high level, or intermittency occurs, the TCP probing scheme will detect this and Reticulum will remove it's internal tunnel associated with the interface, tear it down, and try reconnecting it. The timeouts configured are on the aggressive side for use over a poorly connected i2p router, which could increase latency, or cause periods of intermittency when i2p tunnels are rotated, or i2p lease-sets changed.
Here is what I am currently planning to do:
If you did not already start a SAM implementation, I will go ahead and start writing it within this week probably. I am interested to hear any feedback or comments on the above.
@markqvist thanks for the update! I have also been doing some further testing using the i2p-through-tcpinterface method, I was able to route messages through a mesh of i2p-connected computers, which worked very well. The one issue I am still having is the inability to message over nomadnet, the LXMF peers are able to connect (in the nomadnet UI, it shows that I have "Heard Peers"), however no peers or nodes are ever listed on the interface. Here is a sanitized version of the log message I get each time after startup:
[Notice] Peered with <opposite node's LXMF propagation address>
[Warning] Could not autoselect a prepagation node! LXMF propagation will not be
available until a trusted node announces on the network.
The timeout issue you mentioned could be causing this, because I am using 3-hop routes for all my i2p tunnels which adds a lot of latency. Would love to see if tweaking the TCP timeout config solves this problem.
I have not started work on an I2pInterface yet, but I have been looking through the i2p python libraries. There are two approaches we could take for an I2PInterface: Using the I2PTunnels API, which is essentially an automated version of our current system, and allowing us to reuse the TCPInterface to do the "heavy lifting", or to use the SAM v3 library. The SAM library would be a more complicated implementation, but would be more efficient in the situation where an RNS node is connected to multiple other RNS nodes over i2p. The section on I2PTunnel from the Application Dev section of I2P's docs (the full page is a great read, and very relevant to this topic) has a good statement on this:
The I2PTunnel application allows applications to build specific TCP-like tunnels to peers by creating either I2PTunnel 'client' applications or I2PTunnel 'server' applications. These streams are 8-bit clean, and are authenticated and secured through the same streaming library that SAM uses, but there is a nontrivial overhead involved with creating multiple unique I2PTunnel instances, since each have their own unique I2P destination and their own set of tunnels, keys, etc.
I should be able to help write and test the future I2PInterface implementations :+1: Also, I think the extra work to implement the SAM version of the interface would be worth it because it would allow RNS to more efficiently maintain simultaneous connections to many other RNS nodes over i2p.
An aside: the i2plib library seems to be the most useful i2p python library for this task at the moment because it is the most recently updated and most well documented i2p python library.
@4c3e thanks for all the info and references! This will be very useful moving forward. I agree that the SAMv3 approach is the most efficient approach, and this is definitely the way to go.
As mentioned before, I will first add a few small changes to the TCP interface that will make it work properly over I2P, and then start working on the SAM v3 based i2p interface implementation. It is my hope that we can even add some sort of auto-discovery to this, which would allow Reticulum nodes to automatically mesh over i2p if the user wishes to do so. I will dig into the SAM and i2p docs to gauge how this can be done.
As soon as I have added the i2p support to the TCPInterface and pushed it to master, I will let you know here if you want to try it out.
I still have not properly documented a lot of aspects about LXMF, so my apologies if it is a little opaque and hard to figure out from a cold start. The general gist is this:
You can think of a Propagation Node as kind of a "email server" on the Internet, but you are not locked into using the same propagation node at any time, and you can freely choose the one most convenient for you at any given time. That is why NomadNet will always just try and use the nearest trusted one. That way you can roam a larger network where you trust some servers, and always use one close to you. This is especially useful over slow links like packet radio and LoRa.
Hope the above clears it up a bit! Let me know if there's any doubt :)
Thank you for the info about LXMF! I'll try working with it a bit more and see if I can get it working.
As mentioned before, I will first add a few small changes to the TCP interface that will make it work properly over I2P, and then start working on the SAM v3 based i2p interface implementation.
Sounds good!
It is my hope that we can even add some sort of auto-discovery to this, which would allow Reticulum nodes to automatically mesh over i2p if the user wishes to do so. I will dig into the SAM and i2p docs to gauge how this can be done.
I think this is a great idea, this should be fairly straightforward to implement, assuming it is acceptable to rely on publicly listed, high-uptime bootstrapping nodes to introduce new nodes to the rns-i2p mesh. New nodes could first ping bootstrapping nodes with a "Join" command along with their i2p destination info, and get back a list of i2p destinations seen by the bootstrapping node. This same idea could also probably be used over the clearnet with the TCPInterface, to allow easily accessible, p2p networks over i2p and tcp/ip.
Maybe this could be done with the addition of an "I2PMeshInterface" and "TCPMeshInterface" (name TBD) where users define a list of bootstrap nodes in the config file and it goes through this handshake automatically. As an addition to the individual tunnel config.
I can't remember if I actually mentioned this elsewhere, but there is now preliminary suppor for using the TCP interfaces over I2P tunnels in the master branch. It is not in a release yet, but you can at least test it out from the source tree. I have been testing it quite a bit, and so far, it seems to work as expected.
@markqvist Just saw your i2pinterface additions! Very exciting, I should be able to start testing it this weekend.
Thanks, that is great! I'd very much appreciate help in getting it thoroughly tested. I had a bit of an architectural challenge getting it integrated into a seamless interface, since i2plib uses asyncio, and Reticulum uses threads for multitasking. I think I managed to do it in a rather clean way, but there might definitely still be bugs ;)
I will release version 0.3.3 shortly (maybe tomorrow), which will include the I2P interface, but until then it is available here in the master branch.
I will also set up an I2P-reachable node on the testnet to play around with, whill post the b32 address here when it is up.
Please also note that the new I2P interface is still compatible with the normal TCP interfaces tunneled over I2P, so they can be used with each other, for example, the "native" I2P interface can connect to an I2P b32 address that exposes a "normal" RNS TCP interface over I2P.
I just added documentation for the I2P interfaces to the manual and documentation site. If you have any thoughts on those sections let me know!
Feature implemented and will be included in the forthcoming v0.3.3 release.
@4c3e if you already tried it out, I must apologise. A bug had gotten in while implementing other features of the 0.3.3 release, so there is a chance you had a non-working version if you pulled the latest master at the wrong time. Situation correctified now ;) I have one transport-enabled instance accessible on I2P already, if you want to play around:
ykzlw5ujbaqc2xkec4cpvgyxj257wcrmmgkuxqmqcur7cq3w3lha.b32.i2p
Also, please see #13, where we still have some work to do.
"The Invisible Internet Project is an anonymous network layer that allows for censorship-resistant, peer-to-peer communication."
The i2p community created a couple python libraries for easily sending data over the i2p network through their SAM protocol:
An i2p interface for the RNS would allow for anonymous communication between reticulum nodes over the internet and it would allow users with non-static IP's to host internet accessible reticulum nodes. An i2p interface implementation would probably resemble the current TCP client/server interface.
If there is any interest in adding this to the core reticulum project, I could begin work on a pull request. Regardless, I'll probably experiment with adding this feature as an add-on because it sounds useful to me :+1: