Title: Using the I2P network with OpenBSD and NixOS
       Author: Solène
       Date: 20 June 2021
       Tags: i2p tor openbsd nixos networking
       Description: 
       
       # Introduction
       
       In this text I will explain what is the I2P network and how to provide
       a service over I2P on OpenBSD and how to use to connect to an I2P
       service from NixOS.
       
       # I2P
       
       This acronym stands for Invisible Internet Project and is a network
       over the network (Internet).  It is quite an old project from 2003 and
       is considered stable and reliable.  The idea of I2P is to build a
       network of relays (people running an i2p daemon) to make tunnels from a
       client to a server, but a single TCP session (or UDP) between a client
       and a server could use many tunnels of n hops across relays. 
       Basically, when you start your I2P service, the program will get some
       information about the relays available and prepare many tunnels in
       advance that will be used to reach a destination when you connect.
       
       Some benefits from I2P network:
       
       * your network is reliable because it doesn't take care of operator
       peering
       * your network is secure because packets are encrypted, and you can
       even use usual encryption to reach your remote services (TLS, SSH)
       * provides privacy because nobody can tell where you are connecting to
       * can prevent against habits tracking (if you also relay data to
       participate to i2p, bandwidth allocated is used at 100% all the time,
       and any traffic you do over I2P can't be discriminated from standard
       relay!)
       * can only allow declared I2P nodes to access a server if you don't
       want anyone to connect to a port you expose
       
       It is possible to host a website on I2P (by exposing your web server
       port), it is called an eepsite and can be accessed using the SOCKs
       proxy provided by your I2P daemon.  I never played with them though but
       this is a thing and you may be interested into looking more in depth.
       
 (HTM) I2P project and I2P implementation (java) page
 (HTM) i2pd project (a recent C++ implementation that I use for this tutorial)
 (HTM) Wikipedia page about I2P
       
       # I2P vs Tor
       
       Obviously, many people would question why not using Tor which seems
       similar.  While I2P can seem very close to Tor hidden services, the
       implementation is really different.  Tor is designed to reach the
       outside while I2P is meant to build a reliable and anonymous network. 
       When started, Tor creates a path of relays named a Circuit that will
       remain static for an approximate duration of 12 hours, everything you
       do over Tor will pass through this circuit (usually 3 relays), on the
       other hand I2P creates many tunnels all the time with a very low
       lifespan.  Small difference, I2P can relay UDP protocol while Tor only
       supports TCP.
       
       Tor is very widespread and using a tor hidden service for hosting a
       private website (if you don't have a public IP or a domain name for
       example) would be better to reach an audience, I2P is not very well
       known and that's partially why I'm writing this.  It is a fantastic
       piece of software and only require more users.
       
       Relays in I2P doesn't have any weight and can be seen as a huge P2P
       network while Tor network is built using scores (consensus) of relaying
       servers depending of their throughput and availability.  Fastest and
       most reliable relays will be elected as "Guard server" which are entry
       points to the Tor network.
       
       I've been running a test over 10 hours to compare bandwidth usage of
       I2P and Tor to keep a tunnel / hidden service available (they have not
       been used).  Please note that relaying/transit were desactivated so
       it's only the uploaded data in order to keep the service working.
       
       * I2P sent 55.47 MB of data in 114 430 packets. Total / 10 hours = 1.58
       kB/s average.
       * Tor sent 6.98 MB of data in 14 759 packets. Total / 10 hours = 0.20
       kB/s average.
       
       Tor was a lot more bandwidth efficient than I2P for the same task:
       keeping the network access (tor or i2p) alive.
       
       # Quick explanation about how it works
       
       There are three components in an I2P usage.
       
       - a computer running an I2P daemon configured with tunnels servers (to
       expose a TCP/UDP port from this machine, not necessarily from localhost
       though)
       - a computer running an I2P daemon configured with tunnel client (with
       information that match the server tunnel)
       - computers running I2P and allowing relay, they will receive data from
       other I2P daemons and pass the encrypted packets.  They are the core of
       the network.
       
       In this text we will use an OpenBSD system to share its localhost ssh
       access over I2P and a NixOS client to reach the OpenBSD ssh port.
       
       # OpenBSD
       
       The setup is quite simple, we will use i2pd and not the i2p java
       program.
       
       ```shell commands
       pkg_add i2pd
       
       # read /usr/local/share/doc/pkg-readmes/i2pd for open files limits
       
       cat <<EOF > /etc/i2pd/tunnels.conf
       [SSH]
       type = server
       port = 22
       host = 127.0.0.1
       keys = ssh.dat
       EOF
       
       rcctl enable i2pd
       rcctl start i2pd
       ```
       
       You can edit the file /etc/i2pd/i2pd.conf to uncomment the line
       "notransit = true" if you don't want to relay.  I would encourage
       people to contribute to the network by relaying packets but this would
       require some explanations about a nice tuning to limit the bandwidth
       correctly.  If you disable transit, you won't participate into the
       network but I2P won't use any CPU and virtually no data if your tunnel
       is in use.
       
       Visit http://localhost:7070/ for the admin interface and check the menu
       "I2P Tunnels", you should see a line "SSH => " with a long address
       ending by .i2p with :22 added to it.  This is the address of your
       tunnel on I2P, we will need it (without the :22) to configure the
       client.
       
       # Nixos
       
       As usual, on NixOS we will only configure the
       /etc/nixos/configuration.nix file to declare the service and its
       configuration.
       
       We will name the tunnel "ssh-solene" and use the destination seen on
       the administration interface on the OpenBSD server and expose that port
       to 127.0.0.1:2222 on our NixOS box.
       
       ```nixos configuration file
       services.i2pd.enable = true;
       services.i2pd.notransit = true;
       
       services.i2pd.outTunnels = {
         ssh-solene = {
           enable = true;
           name = "ssh";
           destination = "gajcbkoosoztqklad7kosh226tlt5wr2srr2tm4zbcadulxw2o5a.b32.i2p";
           address = "127.0.0.1";
           port = 2222;
           };
       };
       ```
       
       Now you can use "nixos-rebuild switch" as root to apply changes.
       
       Note that the equivalent NixOS configuration for any other OS would
       look like that for any I2P setup in the file "tunnel.conf" (on OpenBSD
       it would be in /etc/i2pd/tunnels.conf).
       
       ```i2pd tunnels.conf
       [ssh-solene]
       type = client
       address = 127.0.0.1  # optional, default is 127.0.0.1
       port = 2222
       destination = gajcbkoosoztqklad7kosh226tlt5wr2srr2tm4zbcadulxw2o5a.b32.i2p
       ```
       
       # Test the setup
       
       From the NixOS client you should be able to run "ssh -p 2222 localhost"
       and get access to the OpenBSD ssh server.
       
       Both systems have a http://localhost:7070/ interface because it's a
       default setting that is not bad (except if you have multiple people who
       can access the box).
       
       # Conclusion
       
       I2P is a nice way to share services on a reliable and privacy friendly
       network, it may not be fast but shouldn't drop you when you need it. 
       Because it can easily bypass NAT or dynamic IP it's perfectly fine for
       a remote system you need to access when you can use NAT or VPN.