不快感はありませんが、bind()の使用に関する答えはかなり間違っています。bind()は、パケットIPヘッダー内に配置された送信元IPアドレスを制御します。パケットの送信に使用されるインターフェイスは制御されません。カーネルのルーティングテーブルが参照され、特定の宛先に到達するためのコストが最も低いインターフェイスが決定されます。(*ノートを参照してください)
代わりに、SO_BINDTODEVICE
sockoptを使用する必要があります。これは2つのことを行います:
- パケットは、カーネルルーティングテーブルの内容に関係なく、指定したインターフェイスから常に出力されます。
- 指定されたインターフェースに到着したパケットのみがソケットに渡されます。他のインターフェースに到着するパケットはそうではありません。
切り替えたいインターフェースが複数ある場合は、インターフェースごとに1つのソケットを作成することをお勧めします。select()
また、バインドしたインターフェイスへのパケットのみを受信するため、これらのソケットをすべて//使用するものに追加する必要がありますpoll()
。
#include <net/if.h>
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, "eth1", sizeof(ifr.ifr_name));
if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE,
(void *)&ifr, sizeof(ifr)) < 0) {
perror("SO_BINDTODEVICE failed");
}
(*注)
Bind()
インターフェイスのIPアドレスに対しては、混乱を招く可能性がありますが、それでも正しい動作になります。たとえばbind()
、eth1のIPアドレスにアクセスしたが、ルーティングテーブルがパケットをeth0から送信した場合、パケットはeth0ワイヤに表示されますが、eth1インターフェイスの送信元IPアドレスを伝送します。これは奇妙ですが許可されていますが、eth1のIPアドレスに返送されたパケットはeth1にルーティングされます。これは、2つのiPインターフェイスを備えたLinuxシステムを使用してテストできます。私はそれを持っていて、それをテストしました、そしてbind()
、物理的なインターフェースからパケットを操縦するのに効果的ではありません。
技術的には許可されていますが、トポロジによっては、これが機能しない場合があります。攻撃者が偽造されたIP送信元アドレスを使用する分散型サービス拒否攻撃を阻止するために、多くのルーターがReverse Path Forwarding(RPF)チェックを実行するようになりました。「間違った」パスに送信元IPアドレスがあるパケットはドロップされる可能性があります。