AsyncSSH は forward_socks() を通じて動的な TCP 転送を提供します。AsyncSSH をすでに利用しているアプリケーションなら、SSH 接続上にローカルの SOCKS リスナーを作成できます。

import asyncio
import asyncssh

async def main():
    async with asyncssh.connect(
        'jump.example.net', username='operator'
    ) as connection:
        listener = await connection.forward_socks('127.0.0.1', 1080)
        await listener.wait_closed()

asyncio.run(main())

SSH サーバーとアカウントはあくまで例です。通常の AsyncSSH のホスト鍵検証が適用されます。サーバー側で要求した TCP 転送を許可しておく必要があります。コマンドラインでの同等機能では、OpenSSH のローカル動的転送が SSH から宛先へという同じ向きを使います。

ローカルクライアントは 127.0.0.1:1080 を SOCKS のエンドポイントとして使えるようになります。SOCKS 要求ごとに宛先が渡され、SSH サーバーが対応する外向き TCP 接続を開きます。アプリケーションが URL ごとにリモートのダウンローダーを実行する必要はありません。

待機することで、非同期関数は接続のスコープ内にとどまります。リスナー作成後すぐに戻るとそのスコープを抜け、支えている接続が閉じてしまいます。より大きな asyncio アプリケーションでは、同じイベントループ上で他のタスクを動かしながら、この接続を開いたままにできます。

関連記事