diff --git a/RPI_INSTALL_SCAPY.md b/RPI_INSTALL_SCAPY.md new file mode 100644 index 0000000..e0bdf8d --- /dev/null +++ b/RPI_INSTALL_SCAPY.md @@ -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 +``` diff --git a/RPI_MONITOR_GUIDE.md b/RPI_MONITOR_GUIDE.md new file mode 100644 index 0000000..f92bd26 --- /dev/null +++ b/RPI_MONITOR_GUIDE.md @@ -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) diff --git a/rpi_capture_ra_ta.sh b/rpi_capture_ra_ta.sh new file mode 100755 index 0000000..454c747 --- /dev/null +++ b/rpi_capture_ra_ta.sh @@ -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 diff --git a/rpi_capture_ra_ta_python.py b/rpi_capture_ra_ta_python.py new file mode 100755 index 0000000..1b4da57 --- /dev/null +++ b/rpi_capture_ra_ta_python.py @@ -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() diff --git a/rpi_monitor_setup.sh b/rpi_monitor_setup.sh new file mode 100755 index 0000000..dd3dbbe --- /dev/null +++ b/rpi_monitor_setup.sh @@ -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"