/wifianalizator.sh
Utworzenie pustego pliku, aby wkleić później zawartość skryptu:
touch wifianalizator.sh
lub pobranie skryptu bezpośrednio ze strony:
wget www.nox11.pl/wifianalizator.sh
Nadanie uprawnień do wykonywania:
chmod u+x wifianalizator.sh
Uruchomienie:
./wifianalizator.sh
Uruchomienie z konkretnym interfejsem np. wlan0
./wifianalizator.sh wlan0
Zawartość skryptu:
#!/bin/bash
# ============================================================
# WIFI ANALIZATOR nox11.pl
# Terminalowy analizator Wi-Fi
#
# Pasma:
# 2.4 GHz
# 5 GHz
# 6 GHz
#
# Wymaga:
# iw
#
# Uruchomienie:
# sudo ./wifianalyzer.sh
#
# Lub:
# sudo ./wifianalyzer.sh wlan0
#
# Szerokosc pol na mapach zajetosci:
# 20 MHz = 3 pola
# 40 MHz = 5 pol
# 80 MHz = 9 pol
#
# Uwagi: im dBm bliżej 0, tym silniejszy sygnał."
# ============================================================
RESET='\033[0m'
GREEN='\033[32m'
BRIGHTGREEN='\033[1;32m'
IFACE="${1:-}"
RAW=$(mktemp)
AP_FILE=$(mktemp)
cleanup()
{
rm -f "$RAW" "$AP_FILE"
printf "${RESET}"
exit 0
}
trap cleanup INT TERM
# ============================================================
# INTERFEJS
# ============================================================
if [ -z "$IFACE" ]; then
IFACE=$(iw dev 2>/dev/null | awk '
$1 == "Interface" {
print $2
exit
}
')
fi
if [ -z "$IFACE" ]; then
echo "Nie znaleziono interfejsu Wi-Fi."
iw dev
exit 1
fi
if [ "$EUID" -ne 0 ]; then
echo "Uruchom jako root:"
echo
echo "sudo $0 $IFACE"
exit 1
fi
if ! iw dev "$IFACE" info >/dev/null 2>&1; then
echo "Nieprawidlowy interfejs: $IFACE"
exit 1
fi
# ============================================================
# CZESTOTLIWOSC 2.4 GHz
# ============================================================
freq_24()
{
local CH="$1"
if [ "$CH" -ge 1 ] && [ "$CH" -le 13 ]; then
echo $((2407 + CH * 5))
elif [ "$CH" -eq 14 ]; then
echo 2484
else
echo 0
fi
}
# ============================================================
# PASMO
# ============================================================
pasmo()
{
local FREQ="$1"
if [ "$FREQ" -ge 2400 ] && [ "$FREQ" -lt 2500 ]; then
echo "2.4 GHz"
elif [ "$FREQ" -ge 4900 ] && [ "$FREQ" -lt 5925 ]; then
echo "5 GHz"
elif [ "$FREQ" -ge 5925 ] && [ "$FREQ" -le 7125 ]; then
echo "6 GHz"
else
echo "-"
fi
}
# ============================================================
# PASEK SYGNALU
# ============================================================
pasek_sygnalu()
{
local SIGNAL="$1"
local MAX_WIDTH=21
local COUNT
COUNT=$(( (SIGNAL + 90) * MAX_WIDTH / 60 ))
[ "$COUNT" -lt 0 ] && COUNT=0
[ "$COUNT" -gt "$MAX_WIDTH" ] && COUNT="$MAX_WIDTH"
printf "${BRIGHTGREEN}"
printf '%*s' "$COUNT" '' | tr ' ' '#'
printf "${RESET}"
}
# ============================================================
# PARSOWANIE SKANU
#
# BSSID|FREQ|CHANNEL|SIGNAL|WIDTH|CENTER|START|END|SSID
# ============================================================
parsuj_skan()
{
awk '
function wyjscie()
{
if (bssid == "" || freq == "" || signal == "")
return
f = int(freq)
if (channel == "") {
if (f >= 2412 && f <= 2472)
channel = int((f - 2407) / 5)
else if (f == 2484)
channel = 14
else if (f >= 5000 && f < 5925)
channel = int((f - 5000) / 5)
else if (f >= 5925 && f <= 7125)
channel = int((f - 5950) / 5)
else
channel = "-"
}
if (width == "")
width = 20
center = f
if (center1 != "") {
c = int(center1)
if (f >= 5000 && f <= 7125)
center = 5000 + c * 5
}
half = width / 2
start = center - half
end = center + half
if (ssid == "")
ssid = ""
printf "%s|%s|%s|%s|%s|%s|%s|%s|%s\n",
bssid,
f,
channel,
signal,
width,
center,
start,
end,
ssid
}
/^BSS / {
wyjscie()
bssid = $2
sub(/\(.*/, "", bssid)
freq = ""
channel = ""
signal = ""
width = 20
center1 = ""
ssid = ""
next
}
/^[[:space:]]*freq:/ {
freq = $2
next
}
/^[[:space:]]*signal:/ {
signal = $2
gsub(/dBm/, "", signal)
signal = int(signal)
next
}
/^[[:space:]]*SSID:/ {
ssid = $0
sub(/^[[:space:]]*SSID:[[:space:]]*/, "", ssid)
next
}
/^[[:space:]]*DS Parameter set: channel/ {
channel = $NF
next
}
/^[[:space:]]*primary channel:/ {
channel = $NF
next
}
/secondary channel offset:/ {
if ($NF == "above" || $NF == "below")
width = 40
next
}
/channel width:/ {
if ($NF == "1")
width = 80
else if ($NF == "2")
width = 160
next
}
/center freq segment 1:/ {
center1 = $NF
next
}
END {
wyjscie()
}
' "$RAW" > "$AP_FILE"
}
# ============================================================
# KOLOROWANIE MAPY
# ============================================================
koloruj_mape()
{
local LINE="$1"
while [[ "$LINE" == *"[###]"* ]]; do
local BEFORE="${LINE%%\[###\]*}"
local AFTER="${LINE#*\[###\]}"
printf "%s${BRIGHTGREEN}[###]${RESET}" "$BEFORE"
LINE="$AFTER"
done
printf "%s\n" "$LINE"
}
# ============================================================
# MAPA 2.4 GHz
# ============================================================
mapa_24()
{
echo
printf "${BRIGHTGREEN}MAPA ZAJETOSCI 2.4 GHz${RESET}\n"
echo "----------------------------------------------------------------------"
echo
# --------------------------------------------------------
# NUMERY KANALOW
# --------------------------------------------------------
printf "%19s" ""
for CH in {1..13}; do
if [ "$CH" -lt 10 ]; then
printf " %s " "$CH"
else
printf " %s " "$CH"
fi
done
echo
# --------------------------------------------------------
# CZESTOTLIWOSCI
# --------------------------------------------------------
printf "%19s" ""
for CH in {1..13}; do
FREQ=$(freq_24 "$CH")
printf "%5s" "$FREQ"
done
echo
# --------------------------------------------------------
# OS MAPY
# --------------------------------------------------------
printf "%19s" ""
for CH in {1..13}; do
printf "|---|"
done
echo
# --------------------------------------------------------
# SIECI
# --------------------------------------------------------
awk -F'|' '
$2 >= 2400 && $2 < 2500 {
name=$9
if (length(name) > 18)
name=substr(name,1,15) "..."
printf "%-18s ", name
channel=$3
width=$5
# ----------------------------------------------------
# 20 MHz = 3 pola
# 40 MHz = 5 pol
# 80 MHz = 9 pol
# ----------------------------------------------------
fields=int(width/10)
if (fields < 3)
fields=3
if (fields % 2 == 0)
fields++
half=int(fields/2)
# ----------------------------------------------------
# MAPA
# ----------------------------------------------------
for (ch=1; ch<=13; ch++) {
distance=ch-channel
if (distance >= -half && distance <= half)
printf "[###]"
else
printf " "
}
printf " CH%s %sdBm %sMHz\n",
$3,
$4,
$5
}
' "$AP_FILE" |
while IFS= read -r LINE; do
koloruj_mape "$LINE"
done
echo
echo
}
# ============================================================
# KANALY 5 GHz
# ============================================================
CHANNELS5="36 40 44 48 52 56 60 64 100 104 108 112 116 120 124 128 132 136 140 144 149 153 157 161 165"
# ============================================================
# MAPA 5 GHz
# ============================================================
mapa_5()
{
echo
printf "${BRIGHTGREEN}MAPA ZAJETOSCI 5 GHz${RESET}\n"
echo "----------------------------------------------------------------------"
echo
printf " "
for CH in $CHANNELS5; do
printf " %3s " "$CH"
done
echo
printf " "
for CH in $CHANNELS5; do
FREQ=$((5000 + CH * 5))
printf "%5s" "$FREQ"
done
echo
printf " "
for CH in $CHANNELS5; do
printf "|----"
done
echo "|"
awk -F'|' -v channels="$CHANNELS5" '
BEGIN {
split(channels, ch, " ")
}
$2 >= 4900 && $2 < 5925 {
name=$9
if (length(name) > 18)
name=substr(name,1,15) "..."
printf "%-18s ", name
for (i=1; i<=25; i++) {
cf=5000 + ch[i]*5
if (cf > $7 && cf < $8)
printf "[###]"
else
printf " "
}
printf " CH%s %sdBm %sMHz\n",
$3,
$4,
$5
}
' "$AP_FILE" |
while IFS= read -r LINE; do
koloruj_mape "$LINE"
done
echo
}
# ============================================================
# KANALY 6 GHz
# ============================================================
CHANNELS6="1 5 9 13 17 21 25 29 33 37 41 45 49 53 57 61 65 69 73 77 81 85 89 93 97 101 105 109 113 117 121 125 129 133 137 141 145 149 153 157 161 165 169 173 177 181 185 189 193 197 201 205 209 213 217 221 225 229 233"
freq_6()
{
local CH="$1"
echo $((5950 + CH * 5))
}
# ============================================================
# OCENA
# ============================================================
ocena()
{
local SCORE="$1"
if [ "$SCORE" -eq 0 ]; then
echo "WOLNY"
elif [ "$SCORE" -lt 30 ]; then
echo "BARDZO DOBRY"
elif [ "$SCORE" -lt 70 ]; then
echo "DOBRY"
elif [ "$SCORE" -lt 120 ]; then
echo "ZAJETY"
else
echo "BARDZO ZAJETY"
fi
}
# ============================================================
# OCENA KANALU 2.4 GHz
# ============================================================
score_24()
{
local CH="$1"
local CENTER
CENTER=$(freq_24 "$CH")
local START=$((CENTER - 10))
local END=$((CENTER + 10))
awk -F'|' -v start="$START" -v end="$END" '
$2 >= 2400 && $2 < 2500 {
overlap_start=(start > $7 ? start : $7)
overlap_end=(end < $8 ? end : $8)
overlap=overlap_end-overlap_start
if (overlap > 0) {
factor=100+$4
if (factor < 1)
factor=1
score+=(overlap/5)*factor
}
}
END {
printf "%.0f\n", score+0
}
' "$AP_FILE"
}
# ============================================================
# OCENA KANALOW 2.4 GHz
# ============================================================
ocena_24()
{
echo
printf "${BRIGHTGREEN}OCENA KANALOW 2.4 GHz${RESET}\n"
echo "----------------------------------------------------------------------"
SCORE1=$(score_24 1)
SCORE6=$(score_24 6)
SCORE11=$(score_24 11)
BEST=1
BEST_SCORE="$SCORE1"
if [ "$SCORE6" -lt "$BEST_SCORE" ]; then
BEST=6
BEST_SCORE="$SCORE6"
fi
if [ "$SCORE11" -lt "$BEST_SCORE" ]; then
BEST=11
BEST_SCORE="$SCORE11"
fi
OCENA1=$(ocena "$SCORE1")
OCENA6=$(ocena "$SCORE6")
OCENA11=$(ocena "$SCORE11")
printf "Kanal 1 : %-4s pkt " "$SCORE1"
if [ "$OCENA1" = "DOBRY" ] || [ "$OCENA1" = "BARDZO DOBRY" ] || [ "$OCENA1" = "WOLNY" ]; then
printf "${BRIGHTGREEN}%s${RESET}\n" "$OCENA1"
else
printf "%s\n" "$OCENA1"
fi
printf "Kanal 6 : %-4s pkt " "$SCORE6"
if [ "$OCENA6" = "DOBRY" ] || [ "$OCENA6" = "BARDZO DOBRY" ] || [ "$OCENA6" = "WOLNY" ]; then
printf "${BRIGHTGREEN}%s${RESET}\n" "$OCENA6"
else
printf "%s\n" "$OCENA6"
fi
printf "Kanal 11 : %-4s pkt " "$SCORE11"
if [ "$OCENA11" = "DOBRY" ] || [ "$OCENA11" = "BARDZO DOBRY" ] || [ "$OCENA11" = "WOLNY" ]; then
printf "${BRIGHTGREEN}%s${RESET}\n" "$OCENA11"
else
printf "%s\n" "$OCENA11"
fi
echo
printf "${BRIGHTGREEN}>>> ZALECANY KANAL: %s${RESET}\n" "$BEST"
printf " Czestotliwosc: ${BRIGHTGREEN}%s MHz${RESET}\n" \
"$(freq_24 "$BEST")"
echo
echo " Najmniejsze obciazenie wykrytych sieci."
echo
}
# ============================================================
# OCENA KANALOW 5 / 6 GHz
# ============================================================
score_channel()
{
local CENTER="$1"
local START=$((CENTER - 10))
local END=$((CENTER + 10))
awk -F'|' -v start="$START" -v end="$END" '
{
overlap_start=(start > $7 ? start : $7)
overlap_end=(end < $8 ? end : $8)
overlap=overlap_end-overlap_start
if (overlap > 0) {
factor=100+$4
if (factor < 1)
factor=1
score+=(overlap/5)*factor
}
}
END {
printf "%.0f\n", score+0
}
' "$AP_FILE"
}
# ============================================================
# OCENA 5 GHz
# ============================================================
ocena_5()
{
echo
printf "${BRIGHTGREEN}OCENA KANALOW 5 GHz${RESET}\n"
echo "----------------------------------------------------------------------"
BEST=""
BEST_SCORE=999999
for CH in $CHANNELS5; do
FREQ=$((5000 + CH * 5))
SCORE=$(score_channel "$FREQ")
if [ "$SCORE" -lt "$BEST_SCORE" ]; then
BEST_SCORE="$SCORE"
BEST="$CH"
fi
done
for CH in $CHANNELS5; do
FREQ=$((5000 + CH * 5))
SCORE=$(score_channel "$FREQ")
STATUS=$(ocena "$SCORE")
printf "Kanal %-3s: %-4s pkt " "$CH" "$SCORE"
if [ "$CH" = "$BEST" ]; then
printf "${BRIGHTGREEN}%s${RESET}\n" "$STATUS"
elif [ "$STATUS" = "DOBRY" ] || \
[ "$STATUS" = "BARDZO DOBRY" ] || \
[ "$STATUS" = "WOLNY" ]; then
printf "${BRIGHTGREEN}%s${RESET}\n" "$STATUS"
else
printf "%s\n" "$STATUS"
fi
done
echo
printf "${BRIGHTGREEN}>>> ZALECANY KANAL 5 GHz: %s${RESET}\n" "$BEST"
printf " Czestotliwosc: ${BRIGHTGREEN}%s MHz${RESET}\n" \
"$((5000 + BEST * 5))"
echo
echo " Najmniejsze obciazenie wykrytych sieci."
echo
}
# ============================================================
# OCENA 6 GHz
# ============================================================
ocena_6()
{
echo
printf "${BRIGHTGREEN}OCENA KANALOW 6 GHz${RESET}\n"
echo "----------------------------------------------------------------------"
BEST=""
BEST_SCORE=999999
for CH in $CHANNELS6; do
FREQ=$(freq_6 "$CH")
SCORE=$(score_channel "$FREQ")
if [ "$SCORE" -lt "$BEST_SCORE" ]; then
BEST_SCORE="$SCORE"
BEST="$CH"
fi
done
for CH in $CHANNELS6; do
FREQ=$(freq_6 "$CH")
SCORE=$(score_channel "$FREQ")
STATUS=$(ocena "$SCORE")
printf "Kanal %-3s: %-4s pkt " "$CH" "$SCORE"
if [ "$CH" = "$BEST" ]; then
printf "${BRIGHTGREEN}%s${RESET}\n" "$STATUS"
elif [ "$STATUS" = "DOBRY" ] || \
[ "$STATUS" = "BARDZO DOBRY" ] || \
[ "$STATUS" = "WOLNY" ]; then
printf "${BRIGHTGREEN}%s${RESET}\n" "$STATUS"
else
printf "%s\n" "$STATUS"
fi
done
echo
printf "${BRIGHTGREEN}>>> ZALECANY KANAL 6 GHz: %s${RESET}\n" "$BEST"
printf " Czestotliwosc: ${BRIGHTGREEN}%s MHz${RESET}\n" \
"$(freq_6 "$BEST")"
echo
echo " Najmniejsze obciazenie wykrytych sieci."
echo
}
# ============================================================
# WYKRYTE SIECI - KONKRETNE PASMO
# ============================================================
sieci_pasma()
{
local BAND="$1"
printf "${BRIGHTGREEN}WYKRYTE SIECI %s${RESET}\n" "$BAND"
echo "----------------------------------------------------------------------"
printf "%-18s %-6s %-10s %-10s %s\n" \
"BSSID" \
"KANAL" \
"SYGNAL" \
"SZEROKOSC" \
"SSID"
echo "----------------------------------------------------------------------"
case "$BAND" in
"2.4 GHz")
FILTER='$2 >= 2400 && $2 < 2500'
;;
"5 GHz")
FILTER='$2 >= 4900 && $2 < 5925'
;;
"6 GHz")
FILTER='$2 >= 5925 && $2 <= 7125'
;;
esac
awk -F'|' "$FILTER {
print
}" "$AP_FILE" |
sort -t'|' -k3,3n -k4,4nr |
while IFS='|' read BSSID FREQ CH SIGNAL WIDTH CENTER START END SSID; do
printf "%-18s %-6s %-10s %-10s %s\n" \
"$BSSID" \
"$CH" \
"${SIGNAL} dBm" \
"${WIDTH} MHz" \
"$SSID"
done
echo
}
# ============================================================
# STATYSTYKA
# ============================================================
statystyka()
{
TOTAL=$(wc -l < "$AP_FILE")
BAND24=$(awk -F'|' '
$2 >= 2400 && $2 < 2500 { n++ }
END { print n+0 }
' "$AP_FILE")
BAND5=$(awk -F'|' '
$2 >= 4900 && $2 < 5925 { n++ }
END { print n+0 }
' "$AP_FILE")
BAND6=$(awk -F'|' '
$2 >= 5925 && $2 <= 7125 { n++ }
END { print n+0 }
' "$AP_FILE")
printf "${BRIGHTGREEN}STATYSTYKA${RESET}\n"
echo "----------------------------------------------------------------------"
printf "Wykryte AP : %s\n" "$TOTAL"
printf "2.4 GHz : %s\n" "$BAND24"
printf "5 GHz : %s\n" "$BAND5"
printf "6 GHz : %s\n" "$BAND6"
echo
}
# ============================================================
# SKANOWANIE
# ============================================================
skanuj()
{
RAW=$(mktemp)
AP_FILE=$(mktemp)
iw dev "$IFACE" scan 2>/dev/null > "$RAW"
if [ ! -s "$RAW" ]; then
clear
printf "${BRIGHTGREEN}======================================================================${RESET}\n"
printf "${BRIGHTGREEN} WIFI ANALIZATOR nox11.pl${RESET}\n"
printf "${BRIGHTGREEN}======================================================================${RESET}\n"
echo
echo "Nie udalo sie wykonac skanowania."
echo
echo "Sprawdz:"
echo
echo " rfkill list"
echo " ip link show $IFACE"
echo
echo "Jesli Wi-Fi jest zablokowane:"
echo
echo " sudo rfkill unblock wifi"
echo
rm -f "$RAW" "$AP_FILE"
sleep 5
return
fi
parsuj_skan
# ========================================================
# EKRAN
# ========================================================
clear
echo
printf "${BRIGHTGREEN}======================================================================${RESET}\n"
printf "${BRIGHTGREEN} WIFI ANALIZATOR nox11.pl${RESET}\n"
printf "${BRIGHTGREEN}======================================================================${RESET}\n"
printf " Interfejs: ${BRIGHTGREEN}%s${RESET}\n" "$IFACE"
printf "${BRIGHTGREEN}======================================================================${RESET}\n"
echo
# ========================================================
# 2.4 GHz
# ========================================================
printf "${BRIGHTGREEN}2.4 GHz${RESET}\n"
echo "----------------------------------------------------------------------"
printf "%-7s %-5s %-10s %-10s %s\n" \
"KANAL" \
"AP" \
"SYGNAL" \
"SZEROKOSC" \
"ZAJETOSC"
echo "----------------------------------------------------------------------"
for CH in {1..13}; do
LINE=$(awk -F'|' -v ch="$CH" '
$3 == ch && $2 >= 2400 && $2 < 2500 {
count++
if (max == "" || $4 > max)
max=$4
w=$5
}
END {
if (count > 0)
printf "%d %d %d", count, max, w
else
printf "0 0 0"
}
' "$AP_FILE")
AP=$(echo "$LINE" | awk '{print $1}')
MAX=$(echo "$LINE" | awk '{print $2}')
WIDTH=$(echo "$LINE" | awk '{print $3}')
if [ "$AP" -eq 0 ]; then
printf "%-7s %-5s %-10s %-10s\n" \
"$CH" "-" "-" "-"
else
printf "%-7s %-5s %-10s %-10s " \
"$CH" \
"$AP" \
"${MAX} dBm" \
"${WIDTH} MHz"
pasek_sygnalu "$MAX"
echo
fi
done
mapa_24
# ========================================================
# 5 GHz
# ========================================================
printf "${BRIGHTGREEN}5 GHz${RESET}\n"
echo "----------------------------------------------------------------------"
printf "%-7s %-5s %-10s %-10s %s\n" \
"KANAL" \
"AP" \
"SYGNAL" \
"SZEROKOSC" \
"ZAJETOSC"
echo "----------------------------------------------------------------------"
awk -F'|' '
$2 >= 4900 && $2 < 5925 {
count[$3]++
if (!($3 in max) || $4 > max[$3])
max[$3]=$4
width[$3]=$5
}
END {
for (ch in count)
printf "%s %d %d %d\n",
ch,
count[ch],
max[ch],
width[ch]
}
' "$AP_FILE" |
sort -n |
while read CH AP MAX WIDTH; do
printf "%-7s %-5s %-10s %-10s " \
"$CH" \
"$AP" \
"${MAX} dBm" \
"${WIDTH} MHz"
pasek_sygnalu "$MAX"
echo
done
mapa_5
# ========================================================
# 6 GHz
# ========================================================
printf "${BRIGHTGREEN}6 GHz${RESET}\n"
echo "----------------------------------------------------------------------"
printf "%-7s %-5s %-10s %-10s %s\n" \
"KANAL" \
"AP" \
"SYGNAL" \
"SZEROKOSC" \
"ZAJETOSC"
echo "----------------------------------------------------------------------"
awk -F'|' '
$2 >= 5925 && $2 <= 7125 {
count[$3]++
if (!($3 in max) || $4 > max[$3])
max[$3]=$4
width[$3]=$5
}
END {
for (ch in count)
printf "%s %d %d %d\n",
ch,
count[ch],
max[ch],
width[ch]
}
' "$AP_FILE" |
sort -n |
while read CH AP MAX WIDTH; do
printf "%-7s %-5s %-10s %-10s " \
"$CH" \
"$AP" \
"${MAX} dBm" \
"${WIDTH} MHz"
pasek_sygnalu "$MAX"
echo
done
printf "\n"
# ========================================================
# LISTY SIECI
# ========================================================
sieci_pasma "2.4 GHz"
sieci_pasma "5 GHz"
sieci_pasma "6 GHz"
# ========================================================
# OCENY
# ========================================================
ocena_24
ocena_5
ocena_6
# ========================================================
# STATYSTYKA
# ========================================================
statystyka
echo "----------------------------------------------------------------------"
printf "Odswiezanie za ${BRIGHTGREEN}5 sekund${RESET}... Ctrl+C = wyjscie\n"
rm -f "$RAW" "$AP_FILE"
}
# ============================================================
# PETLA
# ============================================================
while true; do
skanuj
sleep 5
done