Skip to content
alex-mextnerPublic

About

What kind of device is that? Data-driven fingerprints (OUI, hostname, mDNS, SSDP, HTTP, ports, TTL) that classify home-network devices with an icon, a confidence and the evidence.

Topics

Resources

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

Repository files navigation

netprint

What kind of device is that? netprint turns what you can observe about a device on a home network (MAC vendor, hostname, mDNS/DNS-SD services and TXT records, SSDP/UPnP descriptions, web UI titles, open ports, TTL, NetBIOS names, router API facts, Home Assistant's registry) into a category, a Material Design icon, a confidence, the device's brand, product, model, OS and firmware, the name it goes by, a display name and the evidence behind it.

$ python -m netprint classify tv.json
tv.json: tv (0.99) mdi:television  Samsung TV 48″ J5500
    brand=Samsung  product=TV 48″ J5500  model=UE48J5500 (2015)  model_id=UE48J5500  friendly_name=[TV] Samsung 5 Series (48)
    +0.95  [ssdp] Samsung TV model UE48J5500
    +0.90  [ssdp] UPnP name [TV] Samsung 5 Series (48)
    +0.85  [ssdp] UPnP st=urn:samsung.com:device:RemoteControlReceiver:1
    +0.70  [ports] port 7676,9197 (Samsung TV control/DLNA)
    ...
  • Data, not code. ~580 rules in netprint/data/rules/*.json; adding a device family is a JSON edit plus a fixture. See CONTRIBUTING.md.
  • Brand from all the evidence, not just the OUI. A Chromecast on a private Wi-Fi MAC is still "Google" (its Cast model says so); a Snapmaker is not "AMPAK" (its Wi-Fi module). Apple model identifiers (Mac16,7, iPhone16,1, Watch7,8) become marketing names from a table generated from AppleDB.
  • Names people recognise. "Google Chromecast «Кухня»", "Apple MacBook Pro 16″ «Sam's MBP»": brand + product + the device's own name when that name is a label (a room, a person) rather than a repeat of the model. Configurable in data/naming.json.
  • Stdlib only, Python 3.11+. No network access: netprint classifies, it does not scan. Collectors (an mDNS browser, an SSDP listener, a port probe, a router API) live in the tools that use it, e.g. router-cli.
  • Ships the IEEE OUI (MA-L) table and handles randomized / locally administered MACs (the "private Wi-Fi address" phones, watches and laptops use) as a signal of its own.

Categories

id icon
phone mdi:cellphone
tablet mdi:tablet
watch mdi:watch
laptop mdi:laptop
desktop mdi:desktop-tower-monitor
tv mdi:television
media-player mdi:cast Chromecast, Apple TV, Android TV boxes, Roku
speaker mdi:speaker smart speakers and voice assistants (Yandex Station, Echo, HomePod)
printer mdi:printer
3d-printer mdi:printer-3d Klipper/Moonraker, OctoPrint, Creality, Bambu, Prusa
camera mdi:cctv
router mdi:router-network network gear
access-point mdi:router-wireless APs, mesh nodes, routers in bridge mode; network gear
nas mdi:nas
server mdi:server home servers, Home Assistant hosts, VMs, containers
iot-plug mdi:power-socket-eu Tuya, Shelly, Sonoff, Tasmota
iot-light mdi:lightbulb WLED, Yeelight, Hue
iot-sensor mdi:home-automation sensors, climate, appliances
ir-remote mdi:remote Broadlink, ESPHome IR blasters
esp-diy mdi:chip self-built ESP8266/ESP32 (ESPHome)
game-console mdi:gamepad-variant
raspberry-pi mdi:raspberry-pi Raspberry Pi and other SBCs
unknown mdi:help-network not enough evidence

A rule may override the icon (e.g. mdi:home-assistant, mdi:watch-variant).

Use it

from netprint import Signals, MdnsService, classify

signals = Signals(
    mac="da:a1:19:00:00:01",  # locally administered -> "random MAC"
    hostnames=["Sams-iPhone"],
    mdns=[MdnsService("_companion-link._tcp", "Sam's iPhone", txt={"rpMd": "iPhone15,2"})],
)
r = classify(signals)
r.category, r.icon, r.confidence, r.display_name
# ('phone', 'mdi:cellphone', 0.99, "Apple iPhone 14 Pro «Sam's iPhone»")
r.brand, r.product, r.model_id, r.friendly_name, r.os
# ('Apple', 'iPhone 14 Pro', 'iPhone15,2', "Sam's iPhone", 'iOS')
[e.to_dict() for e in r.evidence]
# [{'source': 'mdns', 'detail': 'Apple model iPhone15,2: iPhone 14 Pro', 'weight': 0.99}, ...]

Signals fields (all optional): mac, vendor (looked up from the MAC when omitted), hostnames, netbios, mdns (type, name, port, txt), ssdp (server, st, usn, location, friendly_name, manufacturer, model_name, model_number, model_description, device_type), http (port, title, server, favicon_hash, markers), open_ports, ttl, dhcp_vendor, extra (free-form facts such as gateway=1 or miwifi.model=...).

Helpers for collectors:

  • netprint.fingerprint_ports() — every TCP port a rule looks at (what to probe).
  • netprint.find_markers(html) — product words in a page body (esphome, mainsail, miwifi, ...), for HttpService.markers.
  • netprint.vendor(mac), netprint.is_locally_administered(mac).
  • netprint.is_generic_name(name) — android-1f2e..., ESP_1A2B3C, wlan0 and friends.

Local rules: load_db([Path("my-rules/")]) adds rule files; a rule with the id of a shipped rule replaces it (set "weight": 0 to disable one).

How scoring works

Every rule that matches is evidence of weight w for its category. Evidence for one category combines as a noisy-OR, 1 - Π(1 - w): two independent 0.6 hints make 0.84, and nothing is ever certain (confidence is capped at 0.99). Negative weights and demote lower a category. The best category wins if it reaches 0.2; otherwise the device is unknown.

CLI

python -m netprint classify device.json [--rules my-rules/] [--json]
python -m netprint lint [--rules my-rules/]
python -m netprint categories
python -m netprint oui-update            # maintainers: refresh data/oui.tsv.gz from the IEEE
python -m netprint apple-update          # maintainers: regenerate data/tables/apple.json (AppleDB)

Privacy

Fixtures are synthetic: MACs end in 00:00:NN, addresses come from documentation ranges, and names are made up. test_fixtures_are_synthetic enforces it. Never commit captures from a real network.

License

MIT. The OUI table is derived from the public IEEE registry. data/tables/apple.json is generated from AppleDB (MIT); data/tables/yandex.json follows the platform list of AlexxIT/YandexStation (MIT).

About

What kind of device is that? Data-driven fingerprints (OUI, hostname, mDNS, SSDP, HTTP, ports, TTL) that classify home-network devices with an icon, a confidence and the evidence.

Topics

Resources

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages