📜 ⬆️ ⬇️

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


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 inside 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 proxies 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 "Run at Startup" checkbox 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 the 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 an 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 permanently, save the contents of dest.private_key.data 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"" while 1: data = await reader.read(buflen) if len(data) > 0: resp += data else: break writer.close() print(resp.decode()) 

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 client's Destination to the socket. Since Destination and the 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 PONG back:


 async def handle_client(incoming, reader, writer): """  """ dest, data = incoming.split(b"\n", 1) remote_destination = i2plib.Destination(dest.decode()) if not data: data = await reader.read(BUFFER_SIZE) if data == b"PING": writer.write(b"PONG") writer.close() #  ,        while True: reader, writer = await i2plib.stream_accept(session_nickname) incoming = await reader.read(BUFFER_SIZE) 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 quite enough to start your project in I2P. The invisible Internet is suitable for writing various applications in which it is primarily important to keep users private. The network does not impose any restrictions on developers, it can be either a client-server or a P2P application.



')

Source: https://habr.com/ru/post/426315/


All Articles