WFPドライバーのコールアウトで「パケットを送出するNIC」を変更したい

Jay Robinson 20 評価のポイント
2025-07-08T11:36:52.7766667+00:00

■概要と経緯

私はWFPドライバーを開発しています。

WFPドライバーのコールアウトで「パケットを送出するNIC」を変更したいです。

色々と調査や実験を行った結果「TCPパケット」については下記の方法で実現できました。

・FWPS_LAYER_ALE_CONNECT_REDIRECT_V4/V6レイヤーでパケットをフック

・フックの際writableLayerDataとして存在しているFWPS_CONNECT_REQUEST0構造体の「localAddressAndPort」を書き換える

・書き換え内容は、パケットのSrcIP(IN_ADDR構造体)を、パケット送出させたいNICのIPアドレスに変更するというもの

■本題

しかし「UDPパケット」と「ICMP」については上記の方法では実現できませんでした。

おそらくTCPと違い、パケットの送信に「connect()」3WHS の手順が存在しないからではないかと私どもは思いました。

別のWFPのレイヤーでもよいので「UDP」「ICMP」もパケット送出するNICを変更するにはどうすればよいかご教示いただきたいです。

■調査状況

・FWPS_LAYER_OUTBOUND_TRANSPORT_V4/V6レイヤーでパケットをフックし、オリジナルのパケットを破棄した上で、

 SrcIPを物理NICのIPに書き換えた複製パケットを「再注入」すれば、「UDP」「ICMP」パケットも、

 VPNトンネルへ流さないことが出来るのではないか、との仮説のもとWFPドライバーを実装しているが、

 サンプルコード等の参考となる情報が見つからず、未だ成功には至っていない状況

開発者テクノロジ | C++
開発者テクノロジ | C++

C プログラミング言語の拡張機能として作成された高レベルの汎用プログラミング言語。低レベルのメモリ操作機能に加えて、オブジェクト指向、汎用、関数型の機能を備えています。


質問作成者が受け入れた回答
gekka 14,551 評価のポイント MVP ボランティア モデレーター
2025-07-13T08:22:53.1966667+00:00

たとえば、ネットワークインターフェースが 169.254.121.246と169.254.238.193 の 2個あるとして

>ipconfig

Windows IP 構成

イーサネット アダプター イーサネット:

   接続固有の DNS サフィックス . . . . .:
   リンクローカル IPv6 アドレス. . . . .: fe80::a4db:20d0:acdb:6b06%14
   自動構成 IPv4 アドレス. . . . . . . .: 169.254.238.193
   サブネット マスク . . . . . . . . . .: 255.255.0.0
   デフォルト ゲートウェイ . . . . . . .:

イーサネット アダプター イーサネット 2:

   接続固有の DNS サフィックス . . . . .:
   リンクローカル IPv6 アドレス. . . . .: fe80::e876:ee45:c89e:9640%11
   自動構成 IPv4 アドレス. . . . . . . .: 169.254.121.246
   サブネット マスク . . . . . . . . . .: 255.255.0.0
   デフォルト ゲートウェイ . . . . . . .:

>arp -a

インターフェイス: 169.254.121.246 --- 0xb
  インターネット アドレス 物理アドレス           種類
  169.254.213.207       00-15-5d-01-b8-1a     動的
 
インターフェイス: 169.254.238.193 --- 0xe
  インターネット アドレス 物理アドレス           種類
  169.254.5.248         00-15-5d-01-b8-18     動的

以下のようなUDP送信があるとする。

UDP送信元
  宛先アドレス: 169.254.213.207
  宛先ポート  : 20090 

そうすると、通常はARPのテーブルに宛先があるので到達可能として、169.254.121.246のインターフェースが選択されて送信される。

ここで、WDKのサンプルの一つであるWFPSamplerを使って、宛先を変更してやる。

wfpsampler -s BASIC_PACKET_MODIFICATION -l FWPM_LAYER_OUTBOUND_TRANSPORT_V4 -ipp UDP -iprp 20090 -mtdp 20090 -mida 169.254.5.248

そうすると、新しいアドレスに対応するインターフェースに切り替わって送信されました。

つぎに、

UDP送信元
  バインド    : 169.254.238.193 # バインドして強制
  宛先アドレス: 169.254.213.207
  宛先ポート  : 20090 

のようにARPでは選ばれないインターフェースになるようにバインドしてやると、ARPが解決できなくてUDPの送信はされずに失敗します。


これの宛先IPアドレスを、バインドしているインターフェースからARPで解決されるインターフェース側にある宛先IPアドレスになるようにWFPで変更してやる

wfpsampler -s BASIC_PACKET_MODIFICATION -l FWPM_LAYER_OUTBOUND_TRANSPORT_V4 -ipp UDP -iprp 20090 -mtdp 20090 -mida 169.254.5.248

そうするとバインドされているインターフェースではなく変更されたインターフェースから送信されるようになりました。


つぎに、WIPパケットの送信元IPアドレスを別のインターフェースへ、さらにMACアドレスも変更先のインターフェースのにWFPで変更してみます。

wfpsampler -s BASIC_PACKET_MODIFICATION -l FWPM_LAYER_OUTBOUND_IPPACKET_V4 -ipp UDP -iprp 20090 -misa 169.254.238.193 -mmsa 00-15-5D-01-B8-18 

ここまでやるとインターフェースが変更されたらしく変更先のインターフェース(169.254.238.193)にARPの問い合わせが発生しました。 ARP解決までできなかったので結局はUDPパケットは送信できてませんが。


結論としては、WFPSamplerのKrnlHlprIPHeaderModifySourceAddressやあたりを参考にして書き換えればインターフェースを変更して送信要求できそうだけど、ARPの宛先解決をできなければ送信まではできないのかも。

# これ以上の調査は大変すぎるのでおしまいです


追記:202507140830 最後に宛先が無くても送信できるマルチキャスト(224.0.0.0)でUDPを送信させた状態で上記の書き換えを行います。

wfpsampler -s BASIC_PACKET_MODIFICATION -l FWPM_LAYER_OUTBOUND_IPPACKET_V4 -ipp UDP -iprp 20090 -misa 169.254.238.193 -mmsa 00-15-5D-01-B8-18 

このような宛先解決が必要でなければインターフェースを切り替えてUDPパケットが送信できました 追記:202507151220

文章のおかしかった箇所を修正

この回答は役に立ちましたか?


0 件の追加の回答

並べ替え方法: 古い順

お客様の回答

質問作成者は回答に "承認済み"、モデレーターは "推奨" とマークできます。これにより、ユーザーは作成者の問題が回答によって解決したことを把握できます。