Простой WiFi-анализатор

()

При огранизации соединения между несколькими компьютерами посредством Wi-Fi часто возникает необходимость оценить качество приёма в различных точках помещения. А если говорить об организации Wi-Fi-моста и/или настройке направленных антенн то необходимо ещё учитывать соседние Wi-Fi-точки.

Полноценное исследование эфира требует достаточно высоких затрат, которые обычно не оправданы. Чаще всего просто нужен сканер эфира, который показывает доступные точки и качество их сигнала. Для смартфонов таких приложений существует великое множество, а вот под Linux кроме громоздкого Kismet ничего подходящего найти не удалось. В итоге оказалось проще написать свой инструмент.

Основная идея при написании своего инструмента заключалась в том, что вся необходимая информация содержится в выводе команды:

iwlist wlan0 scan 

Но вывод этой команды не удобен для восприятия. В итоге было решено написать скрипт, который в бесконечном цикле будет запускать эту команду, парсить её вывод и отображать результат. Листинг полученного скрипта:

#!/usr/bin/perl

use strict;
use warnings;
use diagnostics;

use Math::Round;

# Если число аргументов не равно единице
if (@ARGV != 1) {
        # Печатаем краткую справку
        print "Usage:\n";
        print "  $0 ifname\n\n";
        # Завершаем работу
        exit;
}

# Будем использовать полученные данные для очистки экрана в дальнейшем
my $clear_screen = `clear`;


# Получаем имя интерфейса
my $ifname = shift;

while (1) {
        # Сканируем эфир
        my $scan_result = `iwlist $ifname scan`;
        # Получаем код ошибки
        my $error_code = $?;
        # Завершаем работу если что-то не так
        exit if $error_code;
        # Наскорую руку разбиваем результат сканирования на элементы
        my @scan_results_tmp = split /Cell \d+/is, $scan_result;
        # Начинаем полноценный разбор
        my @scan_results = ();
        # Перебираем элементы
        foreach my $hotspot_line (@scan_results_tmp) {
                # Если нет номера канала значит это мусор, который надо пропустить
                next if $hotspot_line !~ m{Channel\:}is;
                # Строим элемент
                my %hotspot = ();
                # Номер канала
                $hotspot{'Channel'} = $hotspot_line;
                $hotspot{'Channel'} =~ s{^.+Channel\:(\d+).+$}{$1}is;
                # SSID
                $hotspot{'SSID'} = $hotspot_line;
                $hotspot{'SSID'} =~ s{^.+ESSID\:"((.+?)?)".+$}{$1}is;
                # Наличие шифрований
                $hotspot{'Crypted'} = $hotspot_line;
                $hotspot{'Crypted'} =~ s{^.+Encryption key:(\w+?)\s.+$}{$1}is;
                # Уровень сигнала. И сразу переводим его в проценты
                my $q1 = $hotspot_line;
                $q1 =~ s{^.+Quality=(\d+)/\d+.+$}{$1}is;
                my $q2 = $hotspot_line;
                $q2 =~ s{^.+Quality=\d+/(\d+).+$}{$1}is;
                $hotspot{'Quality'} = round($q1 * 100 / $q2);
                push @scan_results, \%hotspot;
        }
        # Сортируем
        @scan_results = sort { sprintf("%02d", $a->{Channel}) cmp sprintf("%02d", $b->{Channel}) } @scan_results;

        # Очищаем экран
        print $clear_screen;
        # Печатаем данные
        print sprintf("  % 2.2s [% 9.9s] [% 32.32s] [% 7.7s]\n", "Ch", "Quality", "SSID", "Crypt");
        print sprintf('%1$s'x61 . "\n", "-");
        foreach my $hotspot (@scan_results) {
                print sprintf("  %02d [% 8d%%] [% 32.32s] [% 7.7s]\n",
                        $hotspot->{Channel},
                        $hotspot->{Quality},
                        $hotspot->{SSID},
                        $hotspot->{Crypted});
        }
        # Делаем паузу
        sleep 1;
}

Скрипт принимает один единственный параметр: имя интерфейса, на котором надо осуществлять мониторинг. Например так:

./wifiscan.pl wlan2

Вывод скрипта выглядит примерно так:

  Ch [  Quality] [                            SSID] [  Crypt]
-------------------------------------------------------------
  01 [      93%] [                   Yuldash House] [     on]
  02 [      94%] [                        serr_dom] [     on]
  04 [      94%] [                   home-of-moose] [     on]
  06 [      93%] [                wifi.tattele.com] [    off]
  06 [      93%] [                     KEENETIC 4G] [     on]
  06 [      94%] [          MTS_telefon_2-65-60-30] [     on]
  06 [      94%] [                        home.net] [     on]
  08 [      93%] [                            YOTA] [     on]
  10 [      93%] [                       Estucador] [     on]
  10 [      93%] [                    DIR-300NRUB6] [     on]

Если нужны будут какие-то другие параметры то их получение и отображение легко дописать в скрипт. Автор использовал этот скрипт при эксприментах с баночными антеннами и с помощью этого скрипта смог найти нужное направление на необходимую точку.

На этом всё. Приятной работы!

Ключевые слова: wifi, wi-fi, сканер, анализатор, скрипт.

Подписаться на обновления: RSS-лента Канал в TamTam Telegram канал Канал в ICQ

Комментарии:

oermolaev 2013-05-20 23:51:05 (#)

что то у меня "не взлетело":
:~$ perl ./scanerwifi.pl wlan0
Can't locate Math/Round.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.14.2 /usr/local/share/perl/5.14.2 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.14 /usr/share/perl/5.14 /usr/local/lib/site_perl .) at ./scanerwifi.pl line 7.
BEGIN failed--compilation aborted at ./scanerwifi.pl line 7 (#1)
    (F) You said to do (or require, or use) a file that couldn't be
    found. Perl looks for the file in all the locations mentioned in @INC,
    unless the file name included the full path to the file.  Perhaps you
    need to set the PERL5LIB or PERL5OPT environment variable to say where
    the extra library is, or maybe the script needs to add the library name
    to @INC.  Or maybe you just misspelled the name of the file.  See
    "require" in perlfunc and lib.
    
Uncaught exception from user code:
	Can't locate Math/Round.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.14.2 /usr/local/share/perl/5.14.2 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.14 /usr/share/perl/5.14 /usr/local/lib/site_perl .) at ./scanerwifi.pl line 7.
BEGIN failed--compilation aborted at ./scanerwifi.pl line 7.
 at ./scanerwifi.pl line 7

MooSE 2013-05-22 15:00:04 (#)

что то у меня "не взлетело":

Ответ у тебя уже в сообщении об ошибке:) Смотри:

Can't locate Math/Round.pm


На Debian/Ubuntu этот модуль есть в пакете libmath-round-perl.

oermolaev 2013-05-24 00:24:56 (#)

класс! реально работает! жаль только вокруге никого кроме меня не оказалось:
Ch [  Quality] [   SSID] [  Crypt]
---------------------------------------------------
  02 [     100%] [  DIR-615-E] [     on]


Но вот как у меня происходит - между очисткой экрана и выдачей результата нового сканирования проходит до 120 секунд. Это при экспериментах с точкой доступа созданной по http://www.ylsoftware.com/news/668. Это может потому что она ни кем не задействована.

MooSE 2013-05-28 23:33:25 (#)

Но вот как у меня происходит - между очисткой экрана и выдачей результата нового сканирования проходит до 120 секунд.

А команда "iwlist scan" у тебя так же долго отрабатывает?

oermolaev 2013-05-30 17:37:18 (#)

посмотрел на работе с секундомером, между обнаружением сетей
  Ch [  Quality] [                            SSID] [  Crypt]
-------------------------------------------------------------
  01 [      91%] [                            prof] [     on]
  06 [      91%] [\x00\x00\x00\x00\x00\x00\x00\x00] [     on]

и отсутствием обнаружения проходит по 30 секунд. Т.е. 30 сек.есть сети, 30 сек.нет сетей.
команда iwlist wlan0 scan, соответственно, то обнаруживает сети, то:
$ iwlist wlan0 scan
wlan0     No scan results

И это при том что два клиента подключены.
Впрочем, мой адаптер при этом не был подключен к нужной сети. После регистрации в одной из сетей wifi, последняя уже не пропадает, но пропадает другая - которая без клиентов. С той же периодичностью.
Т.е., полагаю, что так и должно быть :-)

Anonymous 2013-08-28 04:21:33 (#)

После запуска скрипта, отображается только та точка, к которой я подключён, если я подключён вообще к какой либо точке, другие точки появляются только спустя какое то время, засёк один раз, у меня это около 50 секунд. Что очень долго. Вообще желательно, что бы обновлялась информацией раз в 5 секунд. Через некотороые время точки к которым я не подключён пропадают, и после появляются снова. Что не очень, кажется скрипт требует доработки, может быть у вас позже будут идеи...
Дистрибутив Ubuntu 12.04.3 ядро 3.8 Wi-fi с проприетарным драйвером от броадком. После перехода на новое ядро перестал работать wavemon, из за чего я и обратил внимание на ваш скрипт. Спасибо за проделанную работу.

Anonymous 2013-08-28 04:40:12 (#)

Уважаемый MooSE, прошу прощения за негативно-некоректный отзыв, на самом деле всё работает, если запустить от рута, в Ubuntu это sudo в начале команды. Например:
sudo ./wifiscan.pl wlan0
Большое спасибо. Классный скрипт.

Anonymous 2015-03-29 16:34:05 (#)

что то у меня "не взлетело":
:~$ perl ./scanerwifi.pl wlan0
Can't locate Math/Round.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.14.2 /usr/local/share/perl/5.14.2 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.14 /usr/share/perl/5.14 /usr/local/lib/site_perl .) at ./scanerwifi.pl line 7.
BEGIN failed--compilation aborted at ./scanerwifi.pl line 7 (#1)
    (F) You said to do (or require, or use) a file that couldn't be
    found. Perl looks for the file in all the locations mentioned in @INC,
    unless the file name included the full path to the file.  Perhaps you
    need to set the PERL5LIB or PERL5OPT environment variable to say where
    the extra library is, or maybe the script needs to add the library name
    to @INC.  Or maybe you just misspelled the name of the file.  See
    "require" in perlfunc and lib.
    
Uncaught exception from user code:
	Can't locate Math/Round.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.14.2 /usr/local/share/perl/5.14.2 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.14 /usr/share/perl/5.14 /usr/local/lib/site_perl .) at ./scanerwifi.pl line 7.
BEGIN failed--compilation aborted at ./scanerwifi.pl line 7.
 at ./scanerwifi.pl line 7


Была та же проблема. Решение:
sudo apt-get-install libmath-round-perl

Отличная вещь. К сожалению, Perl не знаю, а хотел бы добавить функционал отслеживания появившихся каналов. Что бы, например в в конце отображения скрипт показывал список каналов, на которых не была найдена ни одна из SSID. С накоплением, получается.

Anonymous 2015-11-14 17:57:40 (#)

Ребят, как заставить работать скрипт? А то я чайник еще. Вродебы создал пустой фаил wifiscan.pl туда скопировал скрипт, через консоль запускаю sudo ./wifiscan.pl wlan0
Выводит sudo: ./wifiscan.pl: command not found
Что я делаю не так?

Anonymous 2015-11-17 05:42:13 (#)

На файл надо напустить заклинание:
sudo chmod u+x wifiscan.pl

Anonymous 2017-11-15 11:51:06 (#)

Здравствуйте! Скрипт отличный, но хотелось бы добавить отображение BSSID а как добавить не знаю. У меня много открытых сетей с одинаковым именем но разными BSSID и при подключении к таким сетям я прописываю BSSID что-бы адаптер не перепрыгивал при скачках сигнала. Помогите пожалуйста дополнить скрипт.

MooSE 2017-11-17 02:24:52 (#)

хотелось бы добавить отображение BSSID

Насколько я понял BSSID это Address из вывода "iwlist scan". Если да то вот обновлённый скрипт.

Anonymous 2017-11-17 14:35:09 (#)

Спасибо большое теперь благодаря Вам и обновленному скрипту я имею отсортированную информацию о сетях и могу выбрать нужный BSSID

MooSE 2017-11-19 20:03:41 (#)

На самом деле уже после написания скрипта я нашёл wavemon. Делает всё то же самое и даже больше:)
Новый комментарий

Жирный текстКурсивный текстПодчёркнутый текстЗачёркнутый текстПрограммный кодСсылкаИзображение




© 2006-2024 Вадим Калинников aka MooSE
Политика конфиденциальности