- Shell 59.5%
- Python 22.7%
- Dockerfile 14.5%
- Makefile 3.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .devcontainer | ||
| scripts | ||
| tools | ||
| .gitignore | ||
| Makefile | ||
| README.md | ||
wlan-recorder
Passive Wi-Fi survey and packet-recording lab for an Alfa AWUS036ACM on a
Linux Docker host. It provides Kismet for environmental surveys, rotating
pcapng recording with radiotap metadata, Wireshark/TShark analysis, and
SQLite/CSV summaries.
The development container also includes airgeddon for interactive security audits in an isolated, explicitly authorized school lab. airgeddon is not a server; it is a root-run Bash interface which coordinates wireless auditing tools.
Only collect traffic where you own the equipment or have explicit permission. Captures can contain persistent device identifiers and private traffic even when payloads are encrypted.
Host prerequisites
-
Install Docker and VS Code with the Dev Containers extension.
-
Plug in the AWUS036ACM and confirm that the host sees it:
lsusb iw devThe adapter normally uses the in-kernel
mt76x2udriver. A common USB ID is0e8d:7612, but hardware revisions can differ. -
Open this directory in VS Code and run Dev Containers: Reopen in Container.
-
In the container, verify access:
sudo check-adapter
The container installs Kismet, Wireshark/TShark/Dumpcap, Scapy, tcpdump, the
Aircrack-ng utilities, airgeddon, SQLite, and the Linux wireless tools. Rebuild the
container after pulling changes to the Dockerfile. Wireshark needs a graphical
display forwarded into the container; TShark works in every terminal.
Quick start
The examples use the detected Alfa interface. Find the correct name with
iw dev; never substitute the interface carrying your SSH or internet session.
export ALFA_IF=wlx00c0cabaa33f
make check INTERFACE="$ALFA_IF"
Start airgeddon in an authorized lab
Keep the computer online through Ethernet or its built-in Wi-Fi. airgeddon can change the selected adapter's mode and may stop processes which interfere with monitor mode, so select only the external Alfa adapter. Start its interactive menu with:
make check INTERFACE="$ALFA_IF"
make airgeddon
The image pins airgeddon v12.01 under /opt/airgeddon; rebuilding the
container installs that known version. Use active features only against an
isolated access point and clients owned by the project or covered by written
permission. Do not test the school network itself unless the responsible
administrator has explicitly approved the exact test and time window.
Survey the Wi-Fi environment
Kismet controls channel hopping, records device history, and normally exposes
its UI at http://localhost:2501/. If that port is occupied, the survey picks
the next available port and prints the URL. On first use, the UI asks you to
create credentials; its home/configuration is retained under
data/kismet/home/.
make survey INTERFACE="$ALFA_IF"
# Optionally request a different starting web port
make survey INTERFACE="$ALFA_IF" WEB_PORT=2601
Press Ctrl-C to stop. Logs are placed under data/kismet/. A hopping survey is
good for discovering devices but cannot capture every frame because this radio
listens to only one channel block at a time.
Make a detailed channel recording
This creates a temporary monitor interface, locks it to a 20 MHz channel, and
writes a lossless radiotap pcapng. The MT7612U requires its original managed
interface to be lowered while tuning; the script remembers and restores that
interface's prior state afterward. It does not touch other Wi-Fi interfaces.
# Record channel 1 for 60 seconds
make record INTERFACE="$ALFA_IF" CHANNEL=1 DURATION=60
# Record channel 36 until Ctrl-C; files rotate at roughly 100 MB
make record INTERFACE="$ALFA_IF" CHANNEL=36 DURATION=0
Captures go to captures/. Regulatory restrictions are enforced by the kernel;
the script fails if the requested channel cannot be selected. The initial
recorder intentionally uses HT20 so channel selection is unambiguous. Wider
40/80 MHz capture can be added later with an explicit center frequency.
If a process is interrupted and leaves the temporary interface behind:
make clean-monitor INTERFACE="$ALFA_IF"
Analyze a recording
make analyze FILE=captures/20260722T120000Z_ch1.pcapng
This creates data/analysis/<capture-name>/ containing:
capture-info.txt: file duration, packet counts, rates, and encapsulationbeacons.csv: AP observations with time, SSID, BSSID, frequency, and RSSIframes.csv: frame types, addresses, retries, frequency, and RSSIobservations.sqlite3: indexed tables plus anetworkssummary viewsummary.txt: basic frame and network totals
Example queries:
sqlite3 -header -column data/analysis/*/observations.sqlite3 \
'SELECT * FROM networks ORDER BY avg_signal_dbm DESC;'
tshark -r captures/example.pcapng -Y 'wlan.fc.retry == 1'
wireshark captures/example.pcapng
The CSV and SQLite exports retain MAC addresses. Sanitize them before sharing.
The raw pcapng files, generated data, and Kismet databases are excluded by
.gitignore.
AI coding CLIs
Codex and Claude Code are installed globally in the image. The host's
~/.codex/auth.json is bind-mounted into the container for the node user,
so Codex uses the same login and can persist refreshed credentials. The source
file must exist on the host before the container is created; running codex login on the host creates it.
Interactive Bash and Zsh shells define these aliases:
alias codex='command codex --dangerously-bypass-approvals-and-sandbox'
alias claude='command claude --dangerously-skip-permissions'
These flags disable the CLIs' permission protections. Combined with this container's privileged host access, either agent can modify the host and control attached devices without confirmation. Use only with trusted prompts and code.
Claude authentication is not shared from the host; run claude once inside the
container and follow its login flow.
If the USB device is absent, unplug and reconnect it, then rebuild/reopen the
container. If lsusb sees it but iw dev does not, inspect the host first with
sudo dmesg --follow while reconnecting the adapter.
Why the container has broad access
The configuration uses --privileged so tools can control the USB device and
wireless PHY, and --network=host because Linux Wi-Fi interfaces live in a
network namespace. It also mounts the USB bus, udev database, and host kernel
modules. This gives processes in the container extensive control over the host;
only run code you trust in it.
The host and container share networking. NetworkManager or another host service may claim the adapter while you experiment. Check its state with:
nmcli device status
Disconnecting a Wi-Fi interface from NetworkManager can interrupt connectivity, so keep the machine's built-in Wi-Fi or Ethernet as the management connection.
Only capture or test networks and devices that you own or have explicit permission to assess.