Created
July 15, 2022 12:14
-
-
Save oskar456/fa014b5847e4f4b8f7e63e10696ea0e3 to your computer and use it in GitHub Desktop.
Analyze IPv6-only preferred (option 108) in DHCP requests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
""" | |
Analyze a PCAP file containing DHCP Discover messages. | |
Print stats including number of unique MAC addresses, | |
number of MAC addresses requesting DHCP option 108 | |
(IPv6-only Preferred) and MAC adresses flapping between | |
requesting and not requesting it. | |
To collect PCAP file, tcpdump can be used like this: | |
# tcpdump -i eth0 -s0 -w dhcp_messages.pcap udp port bootpc | |
To analyse collected file, run: | |
$ python3 -m venv venv | |
$ source ./venv/bin/activate | |
(venv) $ pip install click dpkt scapy | |
(venv) $ python analyze_v6_only_preferred.py dhcp_messages.pcap | |
""" | |
import io | |
import os | |
import click | |
from scapy.all import Ether, DHCP | |
import dpkt | |
def dhcp_option(options, name): | |
"""Return DHCP option of name provided.""" | |
for option in options: | |
if option[0] == name: | |
return option[1] | |
@click.command() | |
@click.argument("pcapfile", type=click.File("rb")) | |
def main(pcapfile): | |
"""Parse PCAP files to look for option 108 in DHCP requests.""" | |
devicestatus = dict() | |
flapping = set() | |
pcapfile.seek(0, io.SEEK_END) | |
size = pcapfile.tell() | |
pcapfile.seek(0, io.SEEK_SET) | |
pos = 0 | |
with click.progressbar(length=size) as bar: | |
for ts, buf in dpkt.pcap.Reader(pcapfile): | |
newpos = pcapfile.raw.tell() | |
bar.update(newpos - pos) | |
pos = newpos | |
p = Ether(buf) | |
srcmac = p[Ether].src | |
if not p.haslayer(DHCP): | |
continue | |
if dhcp_option(p[DHCP].options, 'message-type') != 1: | |
continue | |
v6onlysupported = 108 in dhcp_option(p[DHCP].options, 'param_req_list') | |
if srcmac not in devicestatus: | |
devicestatus[srcmac] = v6onlysupported | |
elif devicestatus[srcmac] != v6onlysupported: | |
flapping.add(srcmac) | |
total = len(devicestatus) | |
enabled = len([d for d in devicestatus.values() if d]) | |
print("Unique MACs:", total) | |
print("Option 108 enabled:", enabled, f"{100*enabled//total}%") | |
print("Flapping:", len(flapping)) | |
print(", ".join(flapping)) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment