Add Raspberry Pi 5 monitor mode scripts for RA/TA capture
- Add rpi_monitor_setup.sh: Basic monitor mode setup script - Add rpi_capture_ra_ta.sh: Bash script for capturing RA/TA addresses - Add rpi_capture_ra_ta_python.py: Python script using scapy for detailed 802.11 frame parsing - Add RPI_MONITOR_GUIDE.md: Comprehensive guide for monitor mode setup and usage - Add RPI_INSTALL_SCAPY.md: Installation instructions for scapy on Raspberry Pi These scripts help debug WiFi traffic by capturing and displaying Receiver Address (RA) and Transmitter Address (TA) from 802.11 frames, useful for comparing with ESP32 monitor mode captures. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
bb6bd568ce
commit
8ba4bff040
|
|
@ -0,0 +1,40 @@
|
|||
# Installing Scapy on Raspberry Pi 5
|
||||
|
||||
## Option 1: Install via apt (Recommended)
|
||||
|
||||
```bash
|
||||
sudo apt-get install python3-scapy
|
||||
```
|
||||
|
||||
This is the safest method and integrates with the system package manager.
|
||||
|
||||
## Option 2: Use --break-system-packages (For system tools)
|
||||
|
||||
Since this is a system-level monitoring tool that runs as root, you can use:
|
||||
|
||||
```bash
|
||||
sudo pip3 install --break-system-packages scapy
|
||||
```
|
||||
|
||||
## Option 3: Virtual Environment (Not recommended for root tools)
|
||||
|
||||
If you prefer a virtual environment (though less convenient for root tools):
|
||||
|
||||
```bash
|
||||
python3 -m venv ~/scapy-env
|
||||
source ~/scapy-env/bin/activate
|
||||
pip install scapy
|
||||
```
|
||||
|
||||
Then run the script with:
|
||||
```bash
|
||||
sudo ~/scapy-env/bin/python3 rpi_capture_ra_ta_python.py 11
|
||||
```
|
||||
|
||||
## Quick Install Command
|
||||
|
||||
For this use case (system monitoring tool), Option 2 is acceptable:
|
||||
|
||||
```bash
|
||||
sudo pip3 install --break-system-packages scapy
|
||||
```
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
# Raspberry Pi 5 WiFi Monitor Mode Guide
|
||||
|
||||
## Quick Setup
|
||||
|
||||
1. **Copy the setup script to your Raspberry Pi:**
|
||||
```bash
|
||||
scp rpi_monitor_setup.sh pi@your-pi-ip:~/
|
||||
```
|
||||
|
||||
2. **SSH into your Raspberry Pi and run:**
|
||||
```bash
|
||||
sudo ./rpi_monitor_setup.sh [channel]
|
||||
```
|
||||
|
||||
Example for channel 11:
|
||||
```bash
|
||||
sudo ./rpi_monitor_setup.sh 11
|
||||
```
|
||||
|
||||
## Manual Setup (Alternative)
|
||||
|
||||
If you prefer to run commands manually:
|
||||
|
||||
```bash
|
||||
# 1. Check available interfaces
|
||||
iw dev
|
||||
|
||||
# 2. Bring down the interface
|
||||
sudo ip link set wlan0 down
|
||||
|
||||
# 3. Set to monitor mode
|
||||
sudo iw dev wlan0 set type monitor
|
||||
|
||||
# 4. Bring up the interface
|
||||
sudo ip link set wlan0 up
|
||||
|
||||
# 5. Set channel (e.g., channel 11)
|
||||
sudo iw dev wlan0 set channel 11
|
||||
|
||||
# 6. Verify monitor mode
|
||||
iw dev wlan0 info
|
||||
```
|
||||
|
||||
## Capturing Packets
|
||||
|
||||
Once monitor mode is active, you can capture packets:
|
||||
|
||||
### Using tcpdump (simple)
|
||||
```bash
|
||||
# View packets in real-time
|
||||
sudo tcpdump -i wlan0 -n
|
||||
|
||||
# Save to file
|
||||
sudo tcpdump -i wlan0 -w capture.pcap
|
||||
|
||||
# Filter by MAC address (e.g., your Pi's MAC)
|
||||
sudo tcpdump -i wlan0 -n ether host 80:84:89:93:c4:b6
|
||||
|
||||
# Filter by channel (if using multiple interfaces)
|
||||
sudo tcpdump -i wlan0 -n -c 100 # Capture 100 packets
|
||||
```
|
||||
|
||||
### Using airodump-ng (advanced, requires aircrack-ng)
|
||||
```bash
|
||||
# Install aircrack-ng if needed
|
||||
sudo apt-get update
|
||||
sudo apt-get install aircrack-ng
|
||||
|
||||
# Capture on specific channel
|
||||
sudo airodump-ng wlan0 -c 11
|
||||
|
||||
# Save to file
|
||||
sudo airodump-ng wlan0 -c 11 -w capture
|
||||
```
|
||||
|
||||
### Using Wireshark (GUI)
|
||||
```bash
|
||||
# Install wireshark if needed
|
||||
sudo apt-get install wireshark
|
||||
|
||||
# Run wireshark (may need to add user to wireshark group)
|
||||
sudo wireshark -i wlan0
|
||||
```
|
||||
|
||||
## Capturing RA/TA Addresses
|
||||
|
||||
### Quick Capture Script (Recommended)
|
||||
|
||||
Use the provided Python script for best results:
|
||||
|
||||
```bash
|
||||
# Install scapy if needed
|
||||
sudo apt-get install python3-pip
|
||||
sudo pip3 install scapy
|
||||
|
||||
# Capture on channel 11 (shows all frames with RA/TA)
|
||||
sudo python3 rpi_capture_ra_ta_python.py 11
|
||||
|
||||
# Capture and filter by specific MAC address
|
||||
sudo python3 rpi_capture_ra_ta_python.py 11 80:84:89:93:c4:b6
|
||||
```
|
||||
|
||||
The script will:
|
||||
- Automatically set monitor mode
|
||||
- Parse 802.11 frames correctly
|
||||
- Display RA (Receiver Address) and TA (Transmitter Address)
|
||||
- Show frame type, RSSI, length, and QoS info
|
||||
- Provide statistics when stopped (Ctrl+C)
|
||||
|
||||
### Alternative: Bash Script
|
||||
|
||||
For a simpler bash-based solution:
|
||||
|
||||
```bash
|
||||
# Capture on channel 11
|
||||
sudo ./rpi_capture_ra_ta.sh 11
|
||||
|
||||
# Capture and filter by MAC
|
||||
sudo ./rpi_capture_ra_ta.sh 11 80:84:89:93:c4:b6
|
||||
```
|
||||
|
||||
## Monitoring Specific Traffic
|
||||
|
||||
### Filter by MAC address (TA/RA)
|
||||
```bash
|
||||
# Capture frames from specific transmitter (TA)
|
||||
sudo tcpdump -i wlan0 -n ether src 80:84:89:93:c4:b6
|
||||
|
||||
# Capture frames to specific receiver (RA)
|
||||
sudo tcpdump -i wlan0 -n ether dst e0:46:ee:07:df:e1
|
||||
|
||||
# Capture frames involving either address
|
||||
sudo tcpdump -i wlan0 -n "ether host 80:84:89:93:c4:b6 or ether host e0:46:ee:07:df:e1"
|
||||
```
|
||||
|
||||
### Filter by frame type
|
||||
```bash
|
||||
# Data frames only
|
||||
sudo tcpdump -i wlan0 -n "type wlan type data"
|
||||
|
||||
# Management frames (beacons, probes, etc.)
|
||||
sudo tcpdump -i wlan0 -n "type wlan type mgt"
|
||||
|
||||
# Control frames (RTS, CTS, ACK)
|
||||
sudo tcpdump -i wlan0 -n "type wlan type ctl"
|
||||
```
|
||||
|
||||
## Restoring Normal WiFi
|
||||
|
||||
To restore normal WiFi operation:
|
||||
|
||||
```bash
|
||||
# Bring down interface
|
||||
sudo ip link set wlan0 down
|
||||
|
||||
# Set back to managed mode
|
||||
sudo iw dev wlan0 set type managed
|
||||
|
||||
# Bring up interface
|
||||
sudo ip link set wlan0 up
|
||||
|
||||
# Reconnect to your network (use NetworkManager, wpa_supplicant, etc.)
|
||||
sudo nmcli device wifi connect "YourSSID" password "YourPassword"
|
||||
# OR
|
||||
sudo wpa_supplicant -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf &
|
||||
sudo dhclient wlan0
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Interface not found
|
||||
```bash
|
||||
# List all network interfaces
|
||||
ip link show
|
||||
|
||||
# Check WiFi interfaces specifically
|
||||
iw dev
|
||||
```
|
||||
|
||||
### Permission denied
|
||||
- Make sure you're using `sudo` for all monitor mode commands
|
||||
- Some distributions require adding your user to specific groups
|
||||
|
||||
### Can't set monitor mode
|
||||
- Some WiFi adapters don't support monitor mode
|
||||
- Check adapter capabilities: `iw phy | grep -A 10 "Supported interface modes"`
|
||||
- Raspberry Pi 5 built-in WiFi should support monitor mode
|
||||
|
||||
### Channel not changing
|
||||
- Make sure the interface is up: `sudo ip link set wlan0 up`
|
||||
- Try bringing it down first, then setting channel, then bringing it up
|
||||
|
||||
## Useful Commands
|
||||
|
||||
```bash
|
||||
# Check current interface status
|
||||
iw dev wlan0 info
|
||||
|
||||
# Scan for networks (won't work in monitor mode, but useful before switching)
|
||||
iw dev wlan0 scan
|
||||
|
||||
# Check signal strength and link info (before switching to monitor mode)
|
||||
iw dev wlan0 link
|
||||
|
||||
# Monitor channel activity
|
||||
watch -n 1 "iw dev wlan0 info | grep channel"
|
||||
```
|
||||
|
||||
## Comparing with ESP32 Monitor
|
||||
|
||||
When comparing captures between your ESP32 and Raspberry Pi:
|
||||
|
||||
1. **Ensure same channel**: Both devices must monitor the same channel
|
||||
2. **Time sync**: Consider using NTP for accurate timestamp comparison
|
||||
3. **MAC filtering**: Use tcpdump filters to match your ESP32's filter settings
|
||||
4. **Frame types**: Both should capture the same frame types (data, management, control)
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
#!/bin/bash
|
||||
# Raspberry Pi 5 WiFi Monitor Mode - Capture RA/TA Addresses
|
||||
# This script sets up monitor mode and captures 802.11 frames showing RA and TA
|
||||
|
||||
set -e
|
||||
|
||||
WIFI_INTERFACE="wlan0"
|
||||
CHANNEL="${1:-11}" # Default to channel 11, or pass as argument
|
||||
FILTER_MAC="${2:-}" # Optional: filter by MAC address (e.g., 80:84:89:93:c4:b6)
|
||||
|
||||
echo "=== Raspberry Pi 5 WiFi Monitor - RA/TA Capture ==="
|
||||
echo "Interface: $WIFI_INTERFACE"
|
||||
echo "Channel: $CHANNEL"
|
||||
if [ -n "$FILTER_MAC" ]; then
|
||||
echo "Filter: $FILTER_MAC"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Check if running as root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Please run as root (use sudo)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if interface exists
|
||||
if ! ip link show "$WIFI_INTERFACE" &>/dev/null; then
|
||||
echo "Error: Interface $WIFI_INTERFACE not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check current mode
|
||||
CURRENT_MODE=$(iw dev "$WIFI_INTERFACE" info 2>/dev/null | grep "type" | awk '{print $2}' || echo "unknown")
|
||||
|
||||
if [ "$CURRENT_MODE" != "monitor" ]; then
|
||||
echo "Setting $WIFI_INTERFACE to monitor mode..."
|
||||
ip link set "$WIFI_INTERFACE" down
|
||||
iw dev "$WIFI_INTERFACE" set type monitor
|
||||
ip link set "$WIFI_INTERFACE" up
|
||||
iw dev "$WIFI_INTERFACE" set channel "$CHANNEL"
|
||||
echo "Monitor mode activated on channel $CHANNEL"
|
||||
else
|
||||
echo "Already in monitor mode, setting channel to $CHANNEL..."
|
||||
iw dev "$WIFI_INTERFACE" set channel "$CHANNEL"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== Starting Capture (showing RA/TA addresses) ==="
|
||||
echo "Press Ctrl+C to stop"
|
||||
echo ""
|
||||
|
||||
# Build tcpdump filter
|
||||
TCPDUMP_FILTER=""
|
||||
if [ -n "$FILTER_MAC" ]; then
|
||||
# Remove colons from MAC for tcpdump
|
||||
MAC_CLEAN=$(echo "$FILTER_MAC" | tr -d ':')
|
||||
TCPDUMP_FILTER="ether host $FILTER_MAC"
|
||||
fi
|
||||
|
||||
# Use tcpdump with verbose output to show MAC addresses
|
||||
# -e shows link-level headers (includes MAC addresses)
|
||||
# -n prevents DNS resolution
|
||||
# -v increases verbosity
|
||||
if [ -n "$TCPDUMP_FILTER" ]; then
|
||||
tcpdump -i "$WIFI_INTERFACE" -e -n -v "$TCPDUMP_FILTER" 2>&1 | \
|
||||
grep -E "(ether|RA|TA|SA|DA|BSSID)" | \
|
||||
awk '
|
||||
{
|
||||
# Extract MAC addresses from tcpdump output
|
||||
# tcpdump shows: ether src/dst MAC
|
||||
if (match($0, /ether (src|dst) ([0-9a-f:]{17})/, arr)) {
|
||||
direction = arr[1]
|
||||
mac = arr[2]
|
||||
print "[" direction "] " mac
|
||||
}
|
||||
# Also show full frame info
|
||||
print $0
|
||||
}'
|
||||
else
|
||||
# Show all frames with MAC address extraction
|
||||
tcpdump -i "$WIFI_INTERFACE" -e -n -v 2>&1 | \
|
||||
while IFS= read -r line; do
|
||||
# Extract and highlight MAC addresses
|
||||
if echo "$line" | grep -q "ether"; then
|
||||
# Extract source MAC (TA in 802.11)
|
||||
if echo "$line" | grep -q "ether src"; then
|
||||
TA=$(echo "$line" | grep -oP 'ether src \K[0-9a-f:]{17}' || echo "")
|
||||
if [ -n "$TA" ]; then
|
||||
echo "TA (Transmitter): $TA"
|
||||
fi
|
||||
fi
|
||||
# Extract destination MAC (RA in 802.11)
|
||||
if echo "$line" | grep -q "ether dst"; then
|
||||
RA=$(echo "$line" | grep -oP 'ether dst \K[0-9a-f:]{17}' || echo "")
|
||||
if [ -n "$RA" ]; then
|
||||
echo "RA (Receiver): $RA"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
echo "$line"
|
||||
done
|
||||
fi
|
||||
|
|
@ -0,0 +1,307 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Raspberry Pi 5 WiFi Monitor - Capture RA/TA Addresses
|
||||
Uses scapy to parse 802.11 frames and display RA/TA addresses clearly
|
||||
|
||||
Requirements:
|
||||
sudo apt-get install python3-pip
|
||||
sudo pip3 install scapy
|
||||
|
||||
Usage:
|
||||
sudo python3 rpi_capture_ra_ta_python.py [channel] [filter_mac]
|
||||
|
||||
Example:
|
||||
sudo python3 rpi_capture_ra_ta_python.py 11
|
||||
sudo python3 rpi_capture_ra_ta_python.py 11 80:84:89:93:c4:b6
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
import signal
|
||||
from datetime import datetime
|
||||
from scapy.all import *
|
||||
from scapy.layers.dot11 import Dot11, Dot11QoS
|
||||
|
||||
# Configuration
|
||||
WIFI_INTERFACE = "wlan0"
|
||||
CHANNEL = int(sys.argv[1]) if len(sys.argv) > 1 else 11
|
||||
FILTER_MAC = sys.argv[2] if len(sys.argv) > 2 else None
|
||||
|
||||
def setup_monitor_mode():
|
||||
"""Set WiFi interface to monitor mode"""
|
||||
print(f"=== Setting up monitor mode on {WIFI_INTERFACE} ===")
|
||||
|
||||
# Check current mode
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["iw", "dev", WIFI_INTERFACE, "info"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True
|
||||
)
|
||||
if "type monitor" in result.stdout:
|
||||
print(f"Already in monitor mode")
|
||||
else:
|
||||
print(f"Setting {WIFI_INTERFACE} to monitor mode...")
|
||||
subprocess.run(["ip", "link", "set", WIFI_INTERFACE, "down"], check=True)
|
||||
subprocess.run(["iw", "dev", WIFI_INTERFACE, "set", "type", "monitor"], check=True)
|
||||
subprocess.run(["ip", "link", "set", WIFI_INTERFACE, "up"], check=True)
|
||||
print("Monitor mode activated")
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error setting monitor mode: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
# Set channel
|
||||
try:
|
||||
subprocess.run(["iw", "dev", WIFI_INTERFACE, "set", "channel", str(CHANNEL)], check=True)
|
||||
print(f"Channel set to {CHANNEL}")
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error setting channel: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
def get_frame_type_name(dot11):
|
||||
"""Get human-readable frame type name"""
|
||||
type_names = {
|
||||
0: { # Management
|
||||
0: "Association Request",
|
||||
1: "Association Response",
|
||||
2: "Reassociation Request",
|
||||
3: "Reassociation Response",
|
||||
4: "Probe Request",
|
||||
5: "Probe Response",
|
||||
8: "Beacon",
|
||||
10: "Disassociation",
|
||||
11: "Authentication",
|
||||
12: "Deauthentication"
|
||||
},
|
||||
1: { # Control
|
||||
10: "RTS",
|
||||
11: "CTS",
|
||||
12: "ACK",
|
||||
13: "CF-End",
|
||||
14: "CF-End+CF-Ack"
|
||||
},
|
||||
2: { # Data
|
||||
0: "Data",
|
||||
1: "Data+CF-Ack",
|
||||
2: "Data+CF-Poll",
|
||||
3: "Data+CF-Ack+CF-Poll",
|
||||
4: "Null",
|
||||
8: "QoS Data",
|
||||
9: "QoS Data+CF-Ack",
|
||||
10: "QoS Data+CF-Poll",
|
||||
11: "QoS Data+CF-Ack+CF-Poll",
|
||||
12: "QoS Null"
|
||||
}
|
||||
}
|
||||
return type_names.get(dot11.type, {}).get(dot11.subtype,
|
||||
f"Type{dot11.type}/Subtype{dot11.subtype}")
|
||||
|
||||
def parse_80211_frame(pkt):
|
||||
"""Parse 802.11 frame and extract RA/TA addresses"""
|
||||
if not pkt.haslayer(Dot11):
|
||||
return None
|
||||
|
||||
dot11 = pkt[Dot11]
|
||||
|
||||
# 802.11 addressing:
|
||||
# For Data frames (To DS=1, From DS=1):
|
||||
# addr1 = RA (Receiver Address) = Next hop destination
|
||||
# addr2 = TA (Transmitter Address) = Transmitting station
|
||||
# addr3 = DA (Destination Address) = Final destination
|
||||
# addr4 = SA (Source Address) = Original source
|
||||
|
||||
# For Data frames (To DS=0, From DS=1): AP to STA
|
||||
# addr1 = RA = DA (Destination STA)
|
||||
# addr2 = TA = SA (Source AP)
|
||||
# addr3 = BSSID
|
||||
|
||||
# For Data frames (To DS=1, From DS=0): STA to AP
|
||||
# addr1 = RA = BSSID (AP)
|
||||
# addr2 = TA = SA (Source STA)
|
||||
# addr3 = DA (Destination)
|
||||
|
||||
frame_type = dot11.type
|
||||
frame_subtype = dot11.subtype
|
||||
|
||||
# Get addresses
|
||||
addr1 = dot11.addr1 if dot11.addr1 else "N/A"
|
||||
addr2 = dot11.addr2 if dot11.addr2 else "N/A"
|
||||
addr3 = dot11.addr3 if dot11.addr3 else "N/A"
|
||||
addr4 = dot11.addr4 if hasattr(dot11, 'addr4') and dot11.addr4 else None
|
||||
|
||||
# Extract To DS and From DS flags
|
||||
to_ds = dot11.FCfield & 0x1
|
||||
from_ds = (dot11.FCfield >> 1) & 0x1
|
||||
|
||||
# Determine RA and TA based on frame type
|
||||
if frame_type == 2: # Data frame
|
||||
# For data frames:
|
||||
# addr1 is always RA (receiver)
|
||||
# addr2 is always TA (transmitter)
|
||||
ra = addr1
|
||||
ta = addr2
|
||||
|
||||
# Additional context based on To DS / From DS
|
||||
if to_ds and from_ds:
|
||||
# WDS frame: addr3=DA, addr4=SA
|
||||
context = f"WDS: DA={addr3}, SA={addr4 if addr4 else 'N/A'}"
|
||||
elif to_ds and not from_ds:
|
||||
# STA to AP: addr3=DA
|
||||
context = f"STA→AP: DA={addr3}"
|
||||
elif not to_ds and from_ds:
|
||||
# AP to STA: addr3=BSSID
|
||||
context = f"AP→STA: BSSID={addr3}"
|
||||
else:
|
||||
# Ad-hoc: addr3=BSSID
|
||||
context = f"Ad-hoc: BSSID={addr3}"
|
||||
else:
|
||||
# For management/control frames, addr1=DA, addr2=SA
|
||||
ra = addr1 # Receiver/Destination
|
||||
ta = addr2 # Transmitter/Source
|
||||
context = f"BSSID={addr3}" if addr3 != "N/A" else ""
|
||||
|
||||
# Get RSSI if available
|
||||
rssi = "N/A"
|
||||
if hasattr(pkt, "dBm_AntSignal"):
|
||||
rssi = f"{pkt.dBm_AntSignal} dBm"
|
||||
elif hasattr(pkt, "notdecoded"):
|
||||
# Try to extract from radiotap header if present
|
||||
pass
|
||||
|
||||
# Check for QoS data
|
||||
is_qos = pkt.haslayer(Dot11QoS)
|
||||
qos_info = ""
|
||||
if is_qos:
|
||||
qos = pkt[Dot11QoS]
|
||||
tid = qos.TID if hasattr(qos, 'TID') else "N/A"
|
||||
qos_info = f", TID={tid}"
|
||||
|
||||
return {
|
||||
"type": frame_type,
|
||||
"subtype": frame_subtype,
|
||||
"name": get_frame_type_name(dot11),
|
||||
"ra": ra,
|
||||
"ta": ta,
|
||||
"bssid": addr3,
|
||||
"context": context,
|
||||
"rssi": rssi,
|
||||
"len": len(pkt),
|
||||
"qos": is_qos,
|
||||
"qos_info": qos_info,
|
||||
"retry": bool(dot11.FCfield & 0x8) if hasattr(dot11, 'FCfield') else False
|
||||
}
|
||||
|
||||
# Statistics
|
||||
stats = {
|
||||
"total": 0,
|
||||
"by_ta": {},
|
||||
"by_ra": {},
|
||||
"by_type": {}
|
||||
}
|
||||
|
||||
def packet_handler(pkt):
|
||||
"""Handle captured packets"""
|
||||
frame_info = parse_80211_frame(pkt)
|
||||
if not frame_info:
|
||||
return
|
||||
|
||||
# Apply MAC filter if specified
|
||||
if FILTER_MAC:
|
||||
filter_mac_clean = FILTER_MAC.lower().replace(":", "").replace("-", "")
|
||||
ta_clean = frame_info["ta"].replace(":", "").replace("-", "").lower() if frame_info["ta"] != "N/A" else ""
|
||||
ra_clean = frame_info["ra"].replace(":", "").replace("-", "").lower() if frame_info["ra"] != "N/A" else ""
|
||||
|
||||
if filter_mac_clean.lower() not in ta_clean and filter_mac_clean.lower() not in ra_clean:
|
||||
return # Skip this frame
|
||||
|
||||
# Update statistics
|
||||
stats["total"] += 1
|
||||
if frame_info["ta"] != "N/A":
|
||||
stats["by_ta"][frame_info["ta"]] = stats["by_ta"].get(frame_info["ta"], 0) + 1
|
||||
if frame_info["ra"] != "N/A":
|
||||
stats["by_ra"][frame_info["ra"]] = stats["by_ra"].get(frame_info["ra"], 0) + 1
|
||||
frame_type_key = f"{frame_info['name']}"
|
||||
stats["by_type"][frame_type_key] = stats["by_type"].get(frame_type_key, 0) + 1
|
||||
|
||||
# Print frame information
|
||||
timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
|
||||
retry_str = " [RETRY]" if frame_info["retry"] else ""
|
||||
|
||||
print(f"\n[{timestamp}] {frame_info['name']}{retry_str}")
|
||||
print(f" RA (Receiver): {frame_info['ra']}")
|
||||
print(f" TA (Transmitter): {frame_info['ta']}")
|
||||
if frame_info['bssid'] != "N/A":
|
||||
print(f" BSSID: {frame_info['bssid']}")
|
||||
if frame_info['context']:
|
||||
print(f" Context: {frame_info['context']}")
|
||||
print(f" RSSI: {frame_info['rssi']}")
|
||||
print(f" Length: {frame_info['len']} bytes{frame_info['qos_info']}")
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
"""Handle Ctrl+C gracefully"""
|
||||
print("\n\nStopping capture...")
|
||||
sys.exit(0)
|
||||
|
||||
def main():
|
||||
"""Main function"""
|
||||
print(f"=== Raspberry Pi 5 WiFi Monitor - RA/TA Capture ===")
|
||||
print(f"Interface: {WIFI_INTERFACE}")
|
||||
print(f"Channel: {CHANNEL}")
|
||||
if FILTER_MAC:
|
||||
print(f"Filter: {FILTER_MAC}")
|
||||
print("")
|
||||
|
||||
# Check if running as root
|
||||
if os.geteuid() != 0:
|
||||
print("Error: This script must be run as root (use sudo)")
|
||||
sys.exit(1)
|
||||
|
||||
# Setup monitor mode
|
||||
setup_monitor_mode()
|
||||
|
||||
# Register signal handler
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
print("\n=== Starting Capture (showing RA/TA addresses) ===")
|
||||
print("Press Ctrl+C to stop\n")
|
||||
|
||||
# Build filter
|
||||
bpf_filter = None
|
||||
if FILTER_MAC:
|
||||
bpf_filter = f"ether host {FILTER_MAC}"
|
||||
|
||||
# Start capturing
|
||||
try:
|
||||
sniff(
|
||||
iface=WIFI_INTERFACE,
|
||||
prn=packet_handler,
|
||||
filter=bpf_filter,
|
||||
store=False
|
||||
)
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n" + "="*60)
|
||||
print("Capture stopped by user")
|
||||
print("="*60)
|
||||
print(f"\nStatistics:")
|
||||
print(f" Total frames captured: {stats['total']}")
|
||||
print(f"\n Top 5 TAs (Transmitters):")
|
||||
sorted_tas = sorted(stats['by_ta'].items(), key=lambda x: x[1], reverse=True)[:5]
|
||||
for ta, count in sorted_tas:
|
||||
print(f" {ta}: {count} frames")
|
||||
print(f"\n Top 5 RAs (Receivers):")
|
||||
sorted_ras = sorted(stats['by_ra'].items(), key=lambda x: x[1], reverse=True)[:5]
|
||||
for ra, count in sorted_ras:
|
||||
print(f" {ra}: {count} frames")
|
||||
print(f"\n Frame types:")
|
||||
for ftype, count in sorted(stats['by_type'].items(), key=lambda x: x[1], reverse=True):
|
||||
print(f" {ftype}: {count}")
|
||||
except Exception as e:
|
||||
print(f"\nError during capture: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
#!/bin/bash
|
||||
# Raspberry Pi 5 WiFi Monitor Mode Setup Script
|
||||
# Run this script with sudo on your Raspberry Pi
|
||||
|
||||
set -e
|
||||
|
||||
# Configuration
|
||||
WIFI_INTERFACE="wlan0" # Change if your interface is different
|
||||
MONITOR_INTERFACE="mon0" # Monitor mode interface name
|
||||
CHANNEL="${1:-11}" # Default to channel 11, or pass as argument: ./rpi_monitor_setup.sh 36
|
||||
|
||||
echo "=== Raspberry Pi 5 WiFi Monitor Mode Setup ==="
|
||||
echo "Interface: $WIFI_INTERFACE"
|
||||
echo "Monitor interface: $MONITOR_INTERFACE"
|
||||
echo "Channel: $CHANNEL"
|
||||
echo ""
|
||||
|
||||
# Check if running as root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Please run as root (use sudo)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if interface exists
|
||||
if ! ip link show "$WIFI_INTERFACE" &>/dev/null; then
|
||||
echo "Error: Interface $WIFI_INTERFACE not found"
|
||||
echo "Available interfaces:"
|
||||
ip link show | grep -E "^[0-9]+:" | awk '{print $2}' | sed 's/://'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if monitor interface already exists
|
||||
if ip link show "$MONITOR_INTERFACE" &>/dev/null; then
|
||||
echo "Monitor interface $MONITOR_INTERFACE already exists. Removing..."
|
||||
iw dev "$MONITOR_INTERFACE" del
|
||||
fi
|
||||
|
||||
# Bring down the interface
|
||||
echo "Bringing down $WIFI_INTERFACE..."
|
||||
ip link set "$WIFI_INTERFACE" down
|
||||
|
||||
# Set monitor mode
|
||||
echo "Setting $WIFI_INTERFACE to monitor mode..."
|
||||
iw dev "$WIFI_INTERFACE" set type monitor
|
||||
|
||||
# Bring up the monitor interface
|
||||
echo "Bringing up monitor interface..."
|
||||
ip link set "$WIFI_INTERFACE" up
|
||||
|
||||
# Set channel
|
||||
echo "Setting channel to $CHANNEL..."
|
||||
iw dev "$WIFI_INTERFACE" set channel "$CHANNEL"
|
||||
|
||||
# Verify monitor mode
|
||||
echo ""
|
||||
echo "=== Verification ==="
|
||||
iw dev "$WIFI_INTERFACE" info
|
||||
|
||||
echo ""
|
||||
echo "=== Monitor mode is now active! ==="
|
||||
echo "Interface: $WIFI_INTERFACE"
|
||||
echo "Channel: $CHANNEL"
|
||||
echo ""
|
||||
echo "To capture packets, you can use:"
|
||||
echo " sudo tcpdump -i $WIFI_INTERFACE -n"
|
||||
echo " sudo tcpdump -i $WIFI_INTERFACE -w capture.pcap"
|
||||
echo " sudo wireshark -i $WIFI_INTERFACE"
|
||||
echo ""
|
||||
echo "To stop monitor mode and restore normal WiFi:"
|
||||
echo " sudo ip link set $WIFI_INTERFACE down"
|
||||
echo " sudo iw dev $WIFI_INTERFACE set type managed"
|
||||
echo " sudo ip link set $WIFI_INTERFACE up"
|
||||
echo " # Then reconnect to your network"
|
||||
Loading…
Reference in New Issue