14

私はLinuxベースのサーバーシステムで作業しています。このサーバーシステムには2つのネットワークインターフェイスがあり、両方とも同じサブネット上にあります(今のところ、それらは172.17.32.10&であるとだけ言っておきます172.17.32.11)。ネットワーク上のホストにデータを送信するときに、データが送信されるサーバー上のインターフェイスを指定したいと思います。ソフトウェアで1つのインターフェイスから別のインターフェイスに切り替える(または両方で送信する)ことができる必要があります(静的ルーティングルールはこのアプリケーションでは機能しません)。

StackOverflowで、ネットリンクライブラリを使用してルートをその場で変更することを提案する関連する質問を見つけました。これは直感的には機能するように見えますが、これと同じ結果を達成するための他のオプションがあるかどうか疑問に思いました。

4

1 に答える 1

18

不快感はありませんが、bind()の使用に関する答えはかなり間違っています。bind()は、パケットIPヘッダー内に配置された送信元IPアドレスを制御します。パケットの送信に使用されるインターフェイスは制御されません。カーネルのルーティングテーブルが参照され、特定の宛先に到達するためのコストが最も低いインターフェイスが決定されます。(*ノートを参照してください)

代わりに、SO_BINDTODEVICEsockoptを使用する必要があります。これは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アドレスがあるパケットはドロップされる可能性があります。

于 2008-10-06T04:23:40.930 に答える