はじめに
多くのブロードバンドルーターはDHCP ( Dynamic Host Configuration Protocol ) を用いてネットワーク機器に自動的にIPアドレスを割り当てる。DHCPでは初めにDHCPクライアント(ネットワーク機器)がDHCPサーバー(ブロードバンドルーター)に問い合わせをするためにLAN内の全ての宛先(ブロードキャスト)にDHCP Discoverメッセージを送信する。多くの場合、このDHCP Discoverメッセージの中のオプションにクライアントのホスト名が含まれる。このホスト名を抽出することが今回の目標である。
環境
Raspberry Pi OS (32-bit)
Python 3.7.3
scapy==2.4.5
DHCP Discoverメッセージ(DHCPクライアント->DHCPサーバー)をtcpdumpで取得する
sudo apt-get install tcpdump
tcpdumpをインストール
sudo tcpdump -i wlan0 dst port 67 -w test.pcap
-
-i wlan0
: 監視するネットワークインターフェースを指定。wlan0
は無線LAN。 -
dst port 67
: 宛先ポートが67であれば真。67はDHCPクライアントがDHCPサーバ宛にパケットを送る際のポート番号。 -
-w test.pcap
:test.pcap
というファイル名でログを保存。
scapyでパケットを解析しホスト名を表示する
pip3 install --pre scapy[basic]
pipでscapyをインストール。
from scapy.all import *
from datetime import datetime
pcap_path = "test.pcap"
packets = rdpcap(pcap_path)
for packet in packets:
try:
options = packet[DHCP].options
for option in options:
if option[0] == 'hostname':
hostname = option[1].decode()
print('Time: {} | Hostname: {}'.format(datetime.fromtimestamp(packet.time), hostname))
except IndexError as e:
print(e)
python3 parse_dhcp_discover_packet.py
パケットが送信された時刻とDHCPクライアントのホスト名が表示される。
上記のコードを補足
from scapy.all import *
from datetime import datetime
必要なモジュールをインポート。
pcap_path = "test.pcap"
packets = rdpcap(pcap_path)
tcpdumpで取得したログ(test.pcap)をrdpcapで読み込む。
<Ether ... |<IP ... |<UDP ... |<BOOTP ... |<DHCP options=[... hostname=[ホスト名] ...] |>>>>>
packetは上記のように構成されている。packet[DHCP]
とすることでDHCPの情報のみ取得できる。
packet[DHCP].options
でoptionsを取得する。options
はiterableなのでforでoption
を一つ一つ取り出す。
option
のキーoption[0]
が'hostname'
であるとき、option[1].decode()
がホスト名となる。
参考
- TCP/IP - DHCP: https://www.infraexpert.com/study/tcpip13.html
- Download and Installation: https://scapy.readthedocs.io/en/latest/installation.html
- Scapy入門: https://qiita.com/Howtoplay/items/4080752d0d8c7a9ef2aa
- Scapy 2.4.5 documentation: https://scapy.readthedocs.io/en/latest/api/scapy.utils.html
- Usage: https://scapy.readthedocs.io/en/latest/usage.html