LoginSignup
0
0

More than 3 years have passed since last update.

scapy で仮想 IP を作成し ping の応答を得る。

Posted at

はじめに

Scapy は、ネットワークパケット操作のツールで、パケットの生成からデコードまで、色々な事ができます。
例えば、通信エラー発生時のパケットを同じように作成して動作確認するなど、問題の再現テストなどにも利用できると思います。
ここでは、単に仮想的なアドレスに対しての ping 応答を得るだけの環境を作成してみましたので、その説明です。

scapy のインストール

・RedHat
 https://access.redhat.com/solutions/3759961
 (How to install scapy for network troubleshooting in Red Hat Enterprise Linux 7? )

arp 応答プログラム

IP 通信を行うためには、まずは arp の問い合わせに対して応答を返さないといけません。
そのためのプログラムとして以下。※どこかの URL を参考にしたのですが、もう思い出せない。

#!/usr/bin/python3

from scapy.all import *

# Your network broadcast address
broadcastNet = "192.168.1.255"

macDict = { "192.168.1.123" : "01:01:01:01:01:01" }

# Use MAC address of this machine as source. If not eth0, change this:            
myMAC = get_if_hwaddr('eth1')

def handle_packet(packet):
    if packet[ARP].op == 1:     # who-has
        print("Someone is asking about " + packet.pdst)
        print(packet.summary())

        if packet.pdst in macDict:
            print("Sending ARP response for " + packet.pdst)
            reply = ARP(op=2, hwsrc=macDict[packet.pdst], psrc=packet.pdst, hwdst="ff:ff:ff:ff:ff:ff", pdst=broadcastNet)
            # reply = ARP(op=ARP.is_at, hwsrc=macDict[packet.pdst], psrc=packet.pdst, hwdst="ff:ff:ff:ff:ff:ff", pdst=broadcastN
et)
            go = Ether(dst="ff:ff:ff:ff:ff:ff", src=myMAC) / reply
            sendp(go)
    return

# Sniff for ARP packets. Run handle_packet() on each one
sniff(filter="arp", prn=handle_packet, store=0)

ping を打って arp テーブルを確認

つまり、こういう事。
ping の応答は、まだ得られませんが arp テーブルは出来ていることがわかります。

arp.jpg

ping の応答プログラム

#!/usr/bin/python3

from scapy.all import *

def handle_packet(packet):
    if str(packet[ICMP].type) == "8":
        if packet[IP].dst == '192.168.1.123':
            # packet.show()
            echoReply = IP(dst=packet[IP].src, src='192.168.1.123')/ICMP()/Raw()
            echoReply[ICMP].type = 0    # echo reply
            echoReply[ICMP].id = packet[ICMP].id
            echoReply[ICMP].seq = packet[ICMP].seq
            echoReply[ICMP][Raw].load = packet[ICMP][Raw].load
            send(echoReply)
    return

# Sniff for icmp packets
sniff(filter="icmp", prn=handle_packet, store=0)

実行してみる

こんな感じ、めでたく 192.168.1.123 へ ping が飛びました。

ping.jpg

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0