A Python port of the Invisible Internet Project (I2P)

I2P Python#

A complete, from-scratch Python implementation of the I2P anonymous network protocol. This is not a wrapper or binding — it is a full reimplementation of the Java I2P router, capable of connecting to the live I2P network.

Built by bimo.studio.

Installation#

pip install i2p-python

Or install individual components:

pip install i2p-py-router      # Router only
pip install i2p-py-sam          # SAM bridge only
pip install i2p-crypto          # All crypto primitives

Requirements#

  • Python 3.11 or later
  • cryptography >= 41.0

Running the Router#

Quick Start#

i2p-router

This starts the router with default settings:

Setting Default Description
Listen host 0.0.0.0 Bind address for incoming connections
Listen port 9700 NTCP2 transport port (TCP)
Data directory ~/.i2p-python Router identity and state
Tunnel count 3 in / 3 out Exploratory tunnel pool size
Tunnel length 3 hops Privacy level per tunnel
Bandwidth limit Unlimited Set I2P_BANDWIDTH_LIMIT_KBPS to cap

Command-Line Options#

i2p-router --host 0.0.0.0 --port 9700 --data-dir ~/.i2p-python
i2p-router --log-level DEBUG          # Verbose logging
i2p-router --reseed                   # Force reseed on startup

Environment Variables#

Every setting can also be controlled via environment variables:

export I2P_LISTEN_HOST=0.0.0.0
export I2P_LISTEN_PORT=9700
export I2P_DATA_DIR=~/.i2p-python
export I2P_INBOUND_TUNNEL_COUNT=3
export I2P_OUTBOUND_TUNNEL_COUNT=3
export I2P_TUNNEL_LENGTH=3
export I2P_TUNNEL_LIFETIME=600
export I2P_BANDWIDTH_LIMIT_KBPS=256
export I2P_FLOODFILL=false
export I2P_HANDSHAKE_TIMEOUT=30
export I2P_IDLE_TIMEOUT=300

Running the SAM Bridge#

The SAM bridge lets external applications (e.g., I2P-enabled IRC clients, torrent clients) connect through your router:

i2p-sam                                # Default: 127.0.0.1:7656
i2p-sam --host 127.0.0.1 --port 7656   # Explicit

First-Run Bootstrap#

On first startup, the router must bootstrap into the I2P network:

  1. Identity generation (~1 second) — creates Ed25519 signing keys and X25519 NTCP2 transport keys, saved to ~/.i2p-python/router.keys.json.
  2. Reseed (5-25 minutes) — downloads RouterInfo entries from reseed servers over HTTPS to populate the local NetDB. Triggers automatically when the NetDB has fewer than 50 entries. Downloads from at least 2 of 13 hardcoded reseed servers.
  3. Peer connections (~1-2 minutes) — connects to 5 initial peers via NTCP2, exchanging RouterInfo.
  4. Tunnel building (~1-2 minutes) — constructs 3 inbound and 3 outbound exploratory tunnels through the network.

Expect 10-30 minutes before the router is fully integrated. Subsequent startups are faster because the router identity is reused and the NetDB may retain entries from the previous run.

You can monitor progress via log output at --log-level INFO or higher.

Known Issues and Operational Notes#

Ports and Firewalls#

The router listens on TCP port 9700 by default (NTCP2 transport). For the router to accept inbound connections from the I2P network:

  • Port 9700/TCP must be reachable from the internet (or at least from I2P peers).
  • If your firewall blocks inbound TCP, the router will still function in outbound-only mode — it can build tunnels and route traffic, but other routers cannot initiate connections to you. This reduces your contribution to the network and may slightly increase latency.
  • The SAM bridge (port 7656) should not be exposed to the internet — it is a local API for applications on the same machine.

NAT Traversal#

If your router is behind a NAT (home router, cloud VPC, etc.):

  • Port forwarding is the most reliable option. Forward TCP 9700 from your gateway to the machine running the I2P router.
  • UPnP auto-configuration is not yet implemented in this Python port. The Java I2P router has UPnP support; this is planned for a future release.
  • SSU2 (UDP transport) includes NAT detection infrastructure (peer testing and relay/introduction), but it is not yet integrated into the main router bootstrap. Until SSU2 integration is complete, the router operates NTCP2-only.
  • If you cannot forward ports, the router will work but will be classified as "firewalled" by the network. Other routers can still reach you through existing tunnels, but you cannot participate as a relay.

Low-Memory and Residential Routers#

Running an I2P router on hardware with limited resources (e.g., Linksys, OpenWrt, Raspberry Pi, or small VPS instances) requires care:

  • Connection count: The router maintains up to 50 peer connections by default. Each connection holds state, buffers, and crypto context. On devices with < 256 MB RAM, consider reducing tunnel counts to lower overall load.
  • Tunnel overhead: Each tunnel (default: 6 total, 3 hops each) requires per-hop encryption state. Reducing I2P_INBOUND_TUNNEL_COUNT and I2P_OUTBOUND_TUNNEL_COUNT to 1-2 lowers memory and CPU load.
  • Residential NAT routers (Linksys, Netgear, etc.) have limited connection tracking tables (typically 4,096-16,384 entries). An I2P router with 50 peers, each with multiple tunnels, can exhaust this table, causing the residential router to drop connections for all devices on the network. Symptoms: intermittent internet outages, DNS failures, smart home devices going offline. Mitigation: set I2P_BANDWIDTH_LIMIT_KBPS to a conservative value (128-256) and reduce tunnel counts, or run the I2P router behind a dedicated gateway.
  • CPU: Tunnel encryption uses AES-256-CBC and Ed25519 signatures. On ARM-based devices (Pi 3/4), expect higher CPU usage than x86. Python's cryptography library uses OpenSSL under the hood, which is reasonably optimized, but Python's async overhead adds up.
  • NetDB growth: The in-memory NetDB grows as the router learns about peers. A mature router may hold 1,000+ RouterInfo entries. Each is small (~256 bytes), but there is currently no eviction policy — the NetDB grows monotonically until restart.

Bandwidth Limiting#

export I2P_BANDWIDTH_LIMIT_KBPS=256   # Cap at 256 KB/s

Set this on metered connections or shared infrastructure. 0 (default) means unlimited.

Upgrading#

Safe Upgrade Path#

pip install --upgrade i2p-python

Your configuration and identity are preserved. The router stores its identity keys in ~/.i2p-python/router.keys.json and this file is never modified by package upgrades. Your router will keep the same identity (and therefore the same network reputation) across upgrades.

What Can Break#

  • Major version bumps (e.g., 0.x to 1.x) may change the config format or data directory layout. Release notes will include migration instructions.
  • Dependency updates to cryptography are generally safe but may require recompiling native extensions (pip install --force-reinstall cryptography).
  • Do not delete ~/.i2p-python/ unless you want to start fresh with a new identity. Regenerating your identity means losing your reputation in the network and going through the full bootstrap process again.

Rollback#

pip install i2p-python==0.1.0

Pin to a known-good version if an upgrade causes issues.

Architecture#

I2P Python is split into 34 independent packages grouped into layers:

Layer Packages Description
Crypto i2p-py-crypto-* (14 packages) AES, ChaCha20, DSA, EdDSA, ElGamal, X25519, HKDF, HMAC, SipHash, SHA-256, ML-KEM, Noise, Garlic, Session Keys
Data i2p-py-data-* (4 packages) Core types, I2NP messages, RouterInfo, remaining data structures
Transport i2p-py-transport-* (3 packages) Base transport, NTCP2 (TCP), SSU2 (UDP)
Network i2p-py-netdb, i2p-py-tunnel, i2p-py-peer, i2p-py-kademlia Network database, tunnel management, peer connections, DHT
Applications i2p-py-router, i2p-py-sam, i2p-py-streaming, i2p-py-apps, i2p-py-client Router, SAM bridge, streaming lib, applications, client API
Utilities i2p-py-util, i2p-py-stat, i2p-py-time, i2p-py-integration Shared utilities, statistics, clock sync, integration tests

Six meta-packages provide convenient dependency groups:

pip install i2p-python      # Everything — full router + SAM + all deps
pip install i2p-crypto       # All 14 crypto packages
pip install i2p-data         # All 4 data packages
pip install i2p-transport    # All 3 transport packages
pip install i2p-network      # NetDB + tunnel + peer + kademlia
pip install i2p-utils        # Util + stat + time

Protocol Compatibility#

This implementation follows the I2P protocol specifications:

  • NTCP2 transport (Noise XK handshake + AES-CBC frame obfuscation)
  • I2NP message format (DatabaseStore, DatabaseLookup, TunnelData, etc.)
  • Ed25519 router signing keys (SigType 7)
  • X25519 NTCP2 transport keys
  • ElGamal/AES+SessionTag garlic encryption
  • Kademlia-based network database (NetDB / floodfill)
  • SAM v3.0-3.3 bridge protocol

Tested against live Java I2P peers (version 2.x). NTCP2 handshake interoperability confirmed.

License#

MIT License. Copyright (c) 2026 bimo.studio.

This is an independent reimplementation. No code was copied from the original Java I2P project. The original Java I2P core (i2p.jar, router.jar, SAM, streaming) is public domain. See LICENSE for the full text.