A media access control (MAC) address is a 48-bit hexadecimal string. The first eight bits of a MAC address determine many of its properties.
random-mac is a fun, little experiment that uses machine learning (binary classification) to evaluate these properties and identify randomly-generated MAC addresses.
random-mac is available on GitHub at https://github.com/critical-path/random-mac.
If you do not have pip version 18.1 or higher, then run the following command from your shell.
[user@host ~]$ sudo pip install --upgrade pip
To install random-mac with test-related dependencies, run the following command from your shell.
[user@host ~]$ sudo pip install --editable git+https://github.com/critical-path/random-mac.git#egg=random-mac[test]
To install it without test-related dependencies, run the following command from your shell.
[user@host ~]$ sudo pip install git+https://github.com/critical-path/random-mac.git
(If necessary, replace pip
with pip3
.)
random-mac requires lists of organzationally-unique identifiers (OUI) and company IDs (CID) assigned by the IEEE. To fetch them from the IEEE's website, run the following commands from your shell.
[user@host random-mac]$ curl http://standards-oui.ieee.org/oui/oui.csv > oui.csv
[user@host random-mac]$ curl http://standards-oui.ieee.org/cid/cid.csv > cid.csv
random-mac's dataset consists of data (samples) and labels (targets). The data include one non-random MAC address for every OUI and CID assigned by the IEEE (currently about 26,000) as well as a configurable number of random MAC addresses. To make a dataset with two random MAC addresses for every non-random address (a 2:1 ratio), run the following command from your Python interpreter.
(Use the ratio that is most appropriate for your needs. Different ratios require different trade-offs. To get a sense of these trade-offs, use scikit-learn's classification reports.)
>>> import sklearn.model_selection
>>> import random_mac
>>> data, labels = random_mac.dataset.make(
... 2,
... oui_file="./oui.csv",
... cid_file="./cid.csv"
... )
random-mac needs to use some data and labels for training while reserving others for testing. To split data and labels into two different groups, run the following command from your Python interpreter.
>>> training_data, testing_data, training_labels, testing_labels = sklearn.model_selection.train_test_split(data, labels)
random-mac uses a binary classifier. To make, train, and test this classifier, run the following commands from your Python interpreter.
>>> classifier = random_mac.classifier.make()
>>> classifier = random_mac.classifier.train(
... classifier,
... training_data,
... training_labels
... )
>>> score = random_mac.classifier.test(
... classifier,
... testing_data,
... testing_labels
... )
>>> print("score = {}%".format(str(int(100 * score))))
score = 83%
To use the classifier, run the following command from your Python interpreter.
>>> address = "a0b1c2d3e4f5"
>>> results = random_mac.is_random_mac(classifier, address)
>>> print(results)
True
To save (pickle) a classifier for future use, run the following command from your Python interpreter.
>>> random_mac.classifier.save(
... classifier,
... file="./random-mac-classifier.pickled"
... )
To restore (unpickle) a classifier, run the following command from your Python interpreter.
>>> classifier = random_mac.classifier.restore(
... file="./random-mac-classifier.pickled"
... )
# Import modules.
>>> import sklearn.model_selection
>>> import random_mac
# Make a dataset.
>>> data, labels = random_mac.dataset.make(
... 2,
... oui_file="./oui.csv",
... cid_file="./cid.csv"
... )
# Split the dataset.
>>> training_data, testing_data, training_labels, testing_labels = sklearn.model_selection.train_test_split(data, labels)
# Make, train, and test a classifier.
>>> classifier = random_mac.classifier.make()
>>> classifier = random_mac.classifier.train(
... classifier,
... training_data,
... training_labels
... )
>>> score = random_mac.classifier.test(
... classifier,
... testing_data,
... testing_labels
... )
>>> print("score = {}%".format(str(int(100 * score))))
score = 83%
# Save the classifier.
>>> random_mac.classifier.save(
... classifier,
... file="./random-mac-classifier.pickled"
... )
# Import module.
>>> import random_mac
# Find a MAC address in a host's ARP cache, a switch's MAC address table, etc.
>>> address = "aabbccddeeff"
# Restore the classifier.
>>> classifier = random_mac.classifier.restore(file="./random-mac-classifier.pickled")
# Use the classifier.
>>> result = random_mac.is_random_mac(classifier, address)
>>> print(result)
True
To conduct testing, run the following command from your shell.
[user@host random-mac]$ pytest --cov --cov-report=term-missing
If pytest raises an INTERNALERROR
, then run the following command from your shell.
[user@host random-mac]$ sudo $(which pytest) --cov --cov-report=term-missing