Part II · Protocol & Services · Chapter 6

Beyond Tor: I2P

Commands only. What each step does, why it is built this way, and the judgment behind it are in the book.

LAB 6.1

An I2P router in the lab

Step 1, Bring up the testnet

Ubuntu
# several i2pd routers on an isolated network, with their own netid so they
# only ever talk to each other — never the live I2P network
$ ./lab up i2p
$ ./lab stop i2p      # stop — containers kept; ./lab up i2p resumes them
$ ./lab down i2p      # delete — removes containers (add --volumes to drop the seed)
Expected, the testnet routers start
darkweb-i2p-ff1    started   (floodfill)
darkweb-i2p-ff2    started   (floodfill)
darkweb-i2p-r1     started
darkweb-i2p-r2     started
darkweb-i2p-r3     started
i2p testnet: 5 routers, netid 42, isolated network (no route out)

Step 2, Open the router console

Ubuntu
# the i2pd web console for router r1, proxied to your host on 7070
$ ./lab i2p console r1
  console for darkweb-i2p-r1 → http://127.0.0.1:7070

Step 3, Why that number is the headline

Verify in the Docker host
Ubuntu
$ ./lab check 6.1
  • The testnet is up and the routers run on an isolated network with a custom netid
  • A router console is reachable and reports a converging view of known routers
  • At least one router is building or carrying tunnels (it has joined the network)
LAB 6.2

The NetDB and floodfill

Step 1, Read the database that has no owner

Ubuntu
# count what this router knows, and pick out the floodfills that hold the DB
$ ./lab i2p netdb r1
  known routers   : 5
  floodfills      : 2   (ff1, ff2)
  leaseSets held  : 1

Step 2, Publish a record and watch it land

Ubuntu
# start a throwaway service on r2; its leaseSet is published into the NetDB
$ ./lab i2p publish r2
  destination : k6r4...q2wa.b32.i2p
  leaseSet published; held by floodfills closest to its routing key

Step 3, Eclipse the record

Ubuntu
# which floodfills hold that destination's leaseSet — and how hard is it to
# become them? the analyzer works over routers you already run.
$ ./labs/artifacts/i2p-netdb/eclipse.py --target k6r4...q2wa
Expected, the closest floodfills, and the cost to displace them
routing key (today) : 3f9c...a1
floodfills by XOR distance to the key:
  ff2   distance 2^249.3   *holds the leaseSet
  ff1   distance 2^250.1   *holds the leaseSet
to eclipse: craft 2 router identities closer than ff2
  identities tried : 41067   (grinding SHA-256 for proximity)
  result           : target's lookups would resolve to attacker floodfills
note: the routing key rotates daily — grinding must be redone every day
Verify in the Docker host
Ubuntu
$ ./lab check 6.2
  • The NetDB holds routerInfos and the floodfills are identifiable
  • The eclipse analyzer's distance logic self-tests correctly on synthetic hashes
  • You can explain what daily key rotation costs an attacker
LAB 6.3

Tunnels, unidirectional

Step 1, Inbound and outbound are different tunnels

Ubuntu
$ ./lab i2p tunnels r1
Expected, two sets of tunnels, different routers in each
outbound tunnels (traffic leaving r1):
  #1   r1 → r3 → ff1        (gateway r1, endpoint ff1)
inbound tunnels (traffic arriving at r1):
  #1   r2 → ff2 → r1        (gateway r2, endpoint r1)
note: the outbound and inbound paths share no interior router

Step 2, A round trip is four tunnels

Step 3, What the leaseSet gives away

Verify in the Docker host
Ubuntu
$ ./lab check 6.3
  • The router has both inbound and outbound tunnels, built through different routers
  • A published destination's leaseSet lists its inbound gateways
  • You can explain why correlation is harder here and what the leaseSet exposes in exchange
LAB 6.4

Eepsites: access and host

Step 1, Host an eepsite

Ubuntu
# point an i2pd server tunnel at a small web server running on r2
$ ./lab i2p eepsite r2 --serve
  serving on r2:8080 through an i2pd server tunnel
  destination : k6r4...q2wa.b32.i2p

Step 2, Reach it from another router

Ubuntu
# from r1, fetch the eepsite through r1's own HTTP proxy (all in-testnet)
$ ./lab i2p fetch r1 k6r4...q2wa.b32.i2p
Expected, the page comes back over I2P
looked up leaseSet for k6r4...q2wa   (via floodfill ff2)
built client tunnels; fetching...
HTTP/1.1 200 OK
<title>lab eepsite on r2</title>

Step 3, Naming without DNS

Verify in the Docker host
Ubuntu
$ ./lab check 6.4
  • An eepsite is served through an i2pd server tunnel and has a b32 destination
  • Another router resolves that destination and fetches the page, all in-testnet
  • You can explain the addressbook / jump-service model and its chokepoints
LAB 6.5

I2P's threat model vs Tor's

Step 1, Move the adversaries onto I2P

Step 2, Score a concrete role

Worked model, operator of an I2P eepsite (1 low … 5 high)
threat                          L   I   E   weight   vs Tor onion (Lab 5.7)
-----------------------------   -   -   -   ------   ----------------------
application leak / canary       4   5   2    40      unchanged — app layer ignores the network
operator OPSEC mistake          4   5   2    40      unchanged — persona, stylometry, reuse
exit reads destination/content  1   2   1     2      much lower — no exit for in-network svc
NetDB floodfill eclipse (6.2)   2   4   3    24      NEW — no Tor equivalent
leaseSet gateway harvest (6.3)  3   3   3    27      NEW — inbound edge is published
correlation (four-tunnel)       2   4   2    16      harder to mount than Tor's both-ends
being a router yourself         3   2   3    18      NEW — you carry traffic by default

Step 3, The headline

Verify in the Docker host
Ubuntu
$ ./lab check 6.5
  • The I2P threat-model worksheet ships with the shifted and new rows pre-listed
  • The testnet the model reasons about is up and its floodfills are present
  • You produced a weighted model for a specific I2P activity, not "I2P in general"
LAB 6.6

Both networks, side by side

Step 1, Bring up both

Ubuntu
$ ./lab up base     # the Tor gateway + workstation from Part I
$ ./lab up i2p      # the I2P testnet alongside it
$ ./lab ps

Step 2, Prove the isolation

Ubuntu
# the I2P routers have no clearnet path — this must fail (that's the pass)
$ docker exec darkweb-i2p-r1 sh -c 'wget -qO- -T5 https://check.torproject.org' ; echo "exit=$?"
  exit=1

Step 3, Keep the streams apart

Verify in the Docker host
Ubuntu
$ ./lab check 6.6
  • Both stacks are running at once
  • An I2P router has no clearnet route (the egress test fails, which is the pass)
  • The Tor workstation's fail-closed egress lock still holds (Lab 2.7 still passes)
LAB 6.7

A comparison you can defend

Step 1, Lay the two networks side by side

Tor vs I2P, by property (Hyphanet stubbed for Ch. 7)
property              Tor                        I2P
-------------------   ------------------------   ------------------------------
trust root            9 signed dir authorities   no authority; Kademlia NetDB
                      → one hourly consensus      → floodfills, daily-rotated keys
path model            one bidirectional circuit  four unidirectional tunnels
                      (guard sees both ends)      (no interior sees both ends)
who routes            volunteers run relays;      every router routes by default
                      clients don't relay
clearnet exit         yes — exit nodes; core      no by default; in-network first,
                      use case is reaching it     outproxy is a separate choice
hidden services       v3 onion addresses          eepsites, .b32.i2p destinations
naming                onion address = key;        addressbook + jump services
                      no human-name layer         (a social trust layer)
key exposure          intro points published      inbound gateways published in
                                                  the leaseSet (ties to eclipse)
biggest lever         both-ends correlation;      floodfill/NetDB attacks on a
                      malicious guard+exit        specific destination
reach for it when     anonymous access to the     a self-contained darknet:
                      clearnet; onion services     in-network services, resilience
                                                  to authority-based blocking

Step 2, Let the threat model choose

Verify in the Docker host
Ubuntu
$ ./lab check 6.7
  • The overlay comparison matrix ships, populated for Tor and I2P
  • It has a stubbed column ready for Hyphanet (Chapter 7)
  • You produced a network choice for a specific task, justified by a property and a threat-model row