単純なソケット転送の場合は、カーネルに任せてください。iptables、またはフロントエンドの 1 つを使用して構成します。
実世界で使用するために複雑なデータ スニッフィング/マングリング/転送が必要な場合は、iptables モジュールを記述します。
データ ストリームをティー (複製/分割) する必要がある場合、またはデータを検査または変更する必要がある場合は、読み進めてください。
Linux 2.6.17 以降と glibc 2.5 以降では、いくつかの優れた機能が提供されていsplice()
ますtee()
。これらを使用して、ペイロードがユーザー空間との間でコピーされるのを回避し、カーネルに特定の量のバイトをある記述子から別の記述子に転送するように指示できます。(tee()
データを消費しないため、データの 1 つ以上のコピーを他の記述子に送信できます。)
接続ごとに 2 つのスレッド (方向ごとに 1 つ) を使用し、必要に応じて各スレッドにデータ ストリームの検査/マングル/ティーを読み取らせることができます。1 つの発信ソケットに転送するN 個の着信バイトがあることがわかっている場合は、 を使用しますsplice()
。複数の発信ソケットがある場合はtee()
、一度に小さなチャンクで非ブロッキング発信ソケットを使用splice()
します (ただし、各チャンクの最後の発信ソケットには使用します)。
スレッドは、受信データの一部またはすべてを読み取って、それをどう処理するかを決定できますが、 or を使用する前に、送信する必要があるか、write()
またはsend()
既に読み取った部分を送信する必要があることに注意してください。既に消費されたデータを魔法のように取得することはありません。splice()
tee()