Flag cloud/app cameras by MAC OUI, not just open ports - #1
Open
holzmanshmuel wants to merge 1 commit into
Open
Conversation
The port scan only catches devices that run a *local* stream server
(RTSP/ONVIF/DVR on 554/8000/8554/34567/...). Most modern consumer
cameras — and cheap "spy cams" — are cloud/P2P: they dial out to a
vendor cloud and the phone app pulls the feed from there. They listen
on nothing locally, so scan.sh sees the host but never flags it.
Found this in practice: two WiFi baby monitors (IMILAB, and a no-name
cam on a Shenzhen Bilian module) showed up as [VENDOR] hosts with zero
open ports and were silently passed over.
This adds a second, independent detection path: match each host's MAC
OUI against a bundled offline vendor list (scripts/camera_ouis.txt,
247 blocks derived from the IEEE OUI registry via Wireshark's manuf).
- CAM tier -> ">>> KNOWN CAMERA VENDOR" (Hikvision, Dahua, IMILAB,
Wyze, Reolink, Arlo, Nanit...)
- MODULE tier -> ">>> CAMERA-CAPABLE MODULE" (Shenzhen Bilian, Tuya — also
(verify) used in bulbs/plugs)
Notes:
- Offline by design: no network calls at scan time, no device MACs leave
the machine — appropriate for a privacy tool and works on flaky/no
internet (hotel/Airbnb).
- OUI is normalized (arp strips leading zeros: 20:b:cf -> 20:0B:CF).
- bash 3.2-safe (macOS default): plain grep against a TSV, no assoc arrays.
- Limitations documented: a cam using MAC randomization or an unlisted
OUI still won't match — the physical lens sweep remains the backstop.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RQuSmfvdk5Ge3Z28N5SyD7
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
scan.shcurrently flags a host as camera-like only when it has a local stream port open (RTSP/ONVIF/DVR:554/8000/8554/34567/37777/8899/...). That's the right signal for surveillance DVRs/NVRs and classic IP cams — but it structurally misses cloud/P2P cameras, which are most modern consumer cams (and a lot of cheap "spy cams").Those devices don't run a server on the LAN. They open an outbound connection to a vendor cloud and the phone app pulls the feed from there — so they listen on nothing locally,
scan.shlists the host, and then walks right past it because no port matched.I hit this in practice while testing the skill: two WiFi baby monitors — one IMILAB, one no-name cam on a Shenzhen Bilian WiFi module — showed up as
[VENDOR]hosts with zero open ports and were silently ignored. Exactly the failure mode you'd care about in a rental: a cloud spy-cam would slip through the same way.The change
Add a second, independent detection path: match each host's MAC OUI (first 3 octets → manufacturer) against a bundled offline vendor list,
scripts/camera_ouis.txt.Two confidence tiers so it doesn't cry wolf:
CAM>>> KNOWN CAMERA VENDORMODULE>>> CAMERA-CAPABLE MODULE (verify)Example output on a host that opens no port:
Reworked the closing hint to distinguish the two suspect types and to tell the user that a vendor-flagged, no-port host is a cloud cam whose video the network scan can't reach — so the right next move is accounting for it / a physical lens sweep, not
rtsp_probe.pl.Design notes
camera_ouis.txtis 247 OUI blocks derived from the IEEE OUI registry (via Wireshark'smanuf). Header documents how to regenerate. Not exhaustive, and I explicitly excluded ultra-generic silicon (Espressif/Realtek) to avoid flagging every ESP32 smart-plug.arpstrips leading zeros (20:b:cf→20:0B:CF);oui_of()re-pads and uppercases before matching.bash3.2-safe (macOS default): plaingrepagainst a TSV, no associative arrays.SCRIPT_DIRresolves viaBASH_SOURCEso the DB is found regardless ofcwd.[RANDOM]/[VENDOR]/[ROUTER]classification, and the<<< CAMERA-LIKE PORTflag are all untouched. This is purely additive.Limitations (also called out in SKILL.md / README)
A camera using MAC randomization, or one from an unlisted/no-name OUI, still won't match — so the physical lens sweep stays the backstop. This closes a big gap, it doesn't claim completeness.
Testing
bash -nonscan.sh; unit-testedoui_of()/cam_vendor()incl. the zero-stripped-MAC case.scan.shend-to-end on a live /24: the two previously-invisible monitors now flag correctly (IMILAB →CAM, Bilian →MODULE), and I verified two OUI substring false positives ("Carlo Gavazzi", "Arlotto" both containarlo) are excluded.Files
scripts/scan.sh— OUI lookup + output (+38 lines, additive)scripts/camera_ouis.txt— new offline vendor DBSKILL.md,README.md— document the two flag types and the cloud-cam limitationTotally fine to take, leave, or reshape any of this — thanks for open-sourcing the skill, it's a genuinely useful tool. 🙏
🤖 Generated with Claude Code
https://claude.ai/code/session_01RQuSmfvdk5Ge3Z28N5SyD7