WindowsでScapyを使用して特定のEtherインターフェースでrawパケットを送信する方法【Python Ethernet rawパケット送信】

Python
この記事は約7分で読めます。
スポンサーリンク

プログラム解説

ここからは、プログラムの解説です。
このプログラムの流れは以下のような感じになっています。

  1. PC上のインターフェース確認
  2. インターフェース名取得
  3. ソケット生成
  4. データ送信
  5. ソケットのクローズ

では順に解説していきます。

PC上のインターフェース確認

まずはPC上のインターフェースを確認する方法です。

from scapy.all import *
IFACES.show()  # IFACE 確認

上記2行をプログラムにいれて実行すれば、PC内のインターフェースを確認できます。
IPアドレス等はぼかしていますが、以下のような感じでインターフェスのインデックスを取得できます。
Index列を確認してください。

Note

毎回呼び出ししても問題にはなりませんが、この処理は、一番最初に使用したインターフェースを確認するときのみ実行すれば大丈夫です。

インターフェース名取得

インターフェースのインデックスをステップ1で取得できれば、次はインターフェース名を取得します。
以下がその処理にあたります。
今回はインデックス4になりますので、VirtualBox Host-Only Ethernet Adapterのインターフェース名を取得しています。

注意
認識が間違っている方もいるかと思いますが、「VirtualBox Host-Only Ethernet Adapter」というのはDescriptionという項目にあたり、インターフェース名にはなりません。(私もそうでした。。。)
インターフェース名は、「\Device\NPF_{XXXXXXXXXXXX}」というような形になります。

iface = IFACES.dev_from_index(4)  # Iface名取得

ソケット生成

続いてソケット生成です。
ソケットの生成では、先ほどのインターフェース名を指定して、 conf.L2socketというAPIを呼び出すだけとなります。

socket = conf.L2socket(iface=iface)  # ソケット取得

データ送信

続いてデータ送信です。
scapyでは、基本的に以下のように、①パケットを生成②で送信という手順になります。

 ①pcakt = Ether(dst='11:22:33:44:55:66',src='66:55:44:33:22:11',type=2048)
 ②socket.send(pcakt) # send raw data

送信自体は、②のsendだけで問題ありませんが、パケットの生成はやり方がありますので、こちらについて簡単に説明します。

scapyでは、レイヤー事にヘッダをつなぎ合わせることでパケットを生成します。
順番にEther()/IP()/TCP()という順にレイヤーをそれぞれ”/”でつなぎ合わせることでパケットを作成します。
ちなみに、ARP()や、ICMP()といったものも生成できます。
それぞれのプロトコルの意味については、各自で調べてみてください。

また、それぞれのエイヤーのヘッダの内容を設定できるようになっていて、以下のように、それぞれのレイヤーのAPIの中身の引数を設定すれば、それぞれのヘッダの内容を変更できます。

 Ether(dst='11:22:33:44:55:66',src='66:55:44:33:22:11',type=2048)

また、それぞれのレイヤの中身が知りたい場合は”ls()”関数呼び出せば中身が確認できます。
以下のような感じで、知りたいAPIを”ls”関数で呼び出せば中身が確認できます。

ls(Ether)  <- Etherの設定内容が知りたいとき
ls(ARP)    <- ARPの設定内容が知りたいとき

ちなみに、Etherをlsで呼び出すと以下のような感じで確認できます。

最後に、今回私がもっとも試してみたかったものとしてVLANタグをつけたパケットを送信することができましたのでその方法を記載します。
基本的にはこれまでと同様の方法で、設定するのですが、VALNを付けるために、”Dot1Q”という関数を呼び出すことで、VLANタグをつけたパケットを生成できました。
ちなみに、以下のように記述すれば、Vlanタグを複数つけることも可能です。

 pcakt = Ether()/Dot1Q(vlan=1)/Dot1Q(vlan=2)/IP()/TCP()

ソケットのクローズ

最後に、ソケットをクローズして処理終了です。

socket.close()
スポンサーリンク

まとめ

今回は、Ethernetのパケットを自身で生成して、好きに投げる方法が知りたいなと思って、やってみたのですが、通常のsocket通信の方法よりも簡単にできてしまいました。
ただ、各レイヤのヘッダの意味を理解していないと使いこなせないので、使い道はかなり限定されるのかなというのが印象で、普通にTCPやUDPの通信がしたいだけなら、一般的なsocket通信を使うのが特殊な知識等が不要でいいのではないかと思いました。

ちなみに、pythonで一般的なsocket通信をする方法については、以下記事でまとめていますので、気になった方は参考にしてみてください。

最後に、Pythonの基礎を学びたい方は以下がおすすめです。私も持っていてたまに眺めて勉強していますものですのでぜひ購入して学習してみてください。

コメント

タイトルとURLをコピーしました