How to make friends a python with the Invisible Internet? Basics of developing I2P applications in Python and asyncio

  • Tutorial

The project Invisible Internet (hereinafter referred to as I2P) provides developers with a platform for developing applications with enhanced user privacy requirements. This is a virtual network on top of the regular Internet, in which the nodes can exchange data and not disclose their real IP address. Instead of IP addresses within the Invisible Internet, connections occur between virtual addresses that are called I2P Destination. You can have any number of such addresses and change them at least for each connection; they do not provide the other party with any information about the real IP address of the client.

This article describes the basic things you need to know to write I2P applications. Code examples are provided in Python using the asyncio built-in async framework.

Enabling SAM API and installing i2plib

I2P offers several APIs for interacting with client applications. For Java applications, I2CP is used, for normal client-server applications, I2PTunnel, HTTP and Socks proxy can be used. We will do the application in Python, so choose SAM . By default, in the original Java client, the SAM API is disabled, so you need to enable it. Go to the I2P router web console, page "I2P internals" -> "Clients". Check the box "Run at Startup" and click "Start", then "Save Client Configuration".

SAM is already enabled by default in the C ++ client i2pd .

For ease of use SAM API I have written the Python library i2plib . You can install it via pip or download the source code from GitHub.

pip install i2plib

Since this library works with the built-in asyncio async framework , keep in mind that code examples are also taken from asynchronous functions (coroutines) that work in the event loop. Additional examples of use are in the repository .

Destination and session creation

At its core, I2P Destination is a bunch of encryption keys and data signatures. Public keys from this bundle are published on the I2P network and are used instead of the IP address to create connections.

Generate i2plib.Destination , which we will use in the future:

dest = await i2plib.new_destination()
print(dest.base32 + ".b32.i2p") # вывод base32 адреса

The base32 address is a hash where other peers can find your Destination on the network. If you plan to use this Destination in your program on an ongoing basis, save the contents of to a local file.

Now you can create a SAM session, which literally means making this Destination online in the network:

    session_nickname = "test-i2p"# каждая сессия должна иметь уникальный nickname
    _, session_writer = await i2plib.create_session(session_nickname, destination=dest)

It is important to note here that Destination will be online as long as the session_writer socket is open. If you want to turn off this Destination from the network, call session_writer.close ().

Making outgoing connections

Now that Destination is online, we can use it to communicate with other nodes. For example, we connect to the node "udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p", send an HTTP GET request and read the answer (there is a web server "i2p-projekt.i2p"):

remote_host = "udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p"
reader, writer = await i2plib.stream_connect(session_nickname, remote_host)
writer.write("GET /en/ HTTP/1.0\nHost: {}\r\n\r\n".format(remote_host).encode())
buflen, resp = 4096, b""while1:
    data = await
    iflen(data) > 0:
        resp += data

Accept incoming connections

When you connect to another host, as you can see, everything is simple, but with the acceptance of incoming there is one nuance. When a new client connects to you, SAM sends an ASCII string with the Destination of this client to the socket. Since Destination and data may come together, you need to take this into account.

This is how a simple PING-PONG server looks like, which accepts an incoming connection, saves the client's Destination to the remote_destination mode, and sends back to PONG:

asyncdefhandle_client(incoming, reader, writer):"""Обработка клиентского соединения"""
    dest, data = incoming.split(b"\n", 1)
    remote_destination = i2plib.Destination(dest.decode())
    ifnot data:
        data = await
    if data == b"PING":
# Вечный цикл, который принимает клиентские соединения и запускает обработчикwhileTrue:
    reader, writer = await i2plib.stream_accept(session_nickname)
    incoming = await
    asyncio.ensure_future(handle_client(incoming, reader, writer))

More information

It describes the use of Streaming protocol, which performs the functions of TCP / IP in the I2P network. SAM API also provides the ability to send and receive anonymous datagrams, like the UDP protocol. This functionality is missing in i2plib and will be added later.

This is only the most basic information, but it is already enough to start your project in I2P. The invisible Internet is suitable for writing various applications, in which it is first and foremost important to preserve the privacy of users. The network does not impose any restrictions on developers, it can be either a client-server or a P2P application.

Also popular now: