Invisible Internetプロジェクト (以降、単にI2P)は、ユーザーのプライバシー要件が強化されたアプリケーションを開発するためのプラットフォームを開発者に提供します。 これは、通常のインターネット上にある仮想ネットワークであり、ノードは実際のIPアドレスを公開せずにデータを交換できます。 Invisible Internet内のIPアドレスの代わりに、I2P Destinationと呼ばれる仮想アドレス間で接続が発生します。 このようなアドレスはいくつでも持つことができ、接続ごとに変更することができます。クライアントの実際のIPアドレスに関する情報は相手側に提供されません。
この記事では、I2Pアプリケーションを作成するために知っておく必要のある基本事項について説明します。 コード例は、asyncio組み込みの非同期フレームワークを使用してPythonで提供されます。
SAM APIの有効化とi2plibのインストール
I2Pは、クライアントアプリケーションと対話するためのいくつかのAPIを提供します。 JavaアプリケーションにはI2CPが使用され、通常のクライアント/サーバーアプリケーションにはI2PTunnel、HTTPおよびSocksプロキシが使用できます。 Pythonでアプリケーションを作成するため、 SAMを選択します。 デフォルトでは、元のJavaクライアントではSAM APIがオフになっているため、有効にする必要があります。 I2PルーターWebコンソールのページ「I2P内部」->「クライアント」に移動します。 [起動時に実行]ボックスをオンにして、[開始]、[クライアント構成の保存]の順にクリックします。
C ++クライアントでは、i2pd SAMはデフォルトですでに有効になっています。
SAM APIを使いやすくするために、 i2plib Pythonライブラリを作成しました。 pip経由でインストールするか、GitHubからソースコードをダウンロードできます。
pip install i2plib
このライブラリは組み込みのasyncio asyncioフレームワークで動作するため、コード例はイベントループで動作する非同期関数(コルーチン)からも取得されることに注意してください。 追加の使用例はリポジトリにあります 。
宛先とセッションの作成
I2P Destinationは、その核となるのは、一連の暗号化キーとデータ署名キーです。 このバンドルの公開鍵はI2Pネットワークで公開され、IPアドレスの代わりに接続を作成するために使用されます。
将来使用するi2plib.Destinationを生成します。
dest = await i2plib.new_destination() print(dest.base32 + ".b32.i2p") # base32
base32アドレスは、他のピアがネットワーク上の宛先を見つけることができるハッシュです。 プログラムでこのDestinationを継続的に使用する場合は、dest.private_key.dataの内容をローカルファイルに保存します。
これで、SAMセッションを作成できます。これは、文字通り、このDestinationをオンラインでオンラインにすることを意味します。
session_nickname = "test-i2p" # nickname _, session_writer = await i2plib.create_session(session_nickname, destination=dest)
session_writerソケットが開いている限り、Destinationはオンラインになることに注意することが重要です。 ネットワークからこのDestinationを「オフ」にする場合は、session_writer.close()を呼び出します。
発信接続を行う
Destinationがオンラインになったので、これを使用して他のノードと通信できます。 たとえば、ノード「udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p」に接続し、HTTP GETリクエストを送信し、応答を読み取ります(Webサーバー「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())
着信接続を受け入れる
ご覧のように、別のホストに接続するときはすべてが簡単ですが、着信を受け入れることで微妙な違いがあります。 新しいクライアントが接続すると、SAMはそのクライアントに宛先文字列をASCIIソケットに送信します。 宛先とデータは一体になっている可能性があるため、これを考慮する必要があります。
これは、単純なPING-PONGサーバーの外観です。これは、着信接続を受け入れ、クライアントのDestinationをremote_destination変数に保存し、PONGを送り返します。
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))
詳細情報
I2PネットワークでTCP / IPの機能を実行するストリーミングプロトコルの使用について説明します。 SAM APIは、UDPプロトコルと同様に、匿名データグラムを送受信する機能も提供します。 この機能はi2plibではまだ利用できず、後で追加されます。
これは最も基本的な情報にすぎませんが、I2Pでプロジェクトを開始するにはすでに十分です。 目に見えないインターネットは、ユーザーのプライバシーを維持することが何よりも重要であるさまざまなアプリケーションを作成するのに適しています。 このネットワークは、開発者に制限を課すものではなく、クライアントサーバーまたはP2Pアプリケーションのいずれでもかまいません。