Дампим Telnet/CLI сессию, для последующего анализа

Продолжая темы: пишем заглушку для Telnet/CLI, пишем заглушку для Telnet/CLI на Perl.

Студент попался нерадивый и не знает как сделать дамп/трассировку telnet сессии. Приведу два примера: средствами утилитами командной строки GNU/Linux, и средствами Perl.

Командная строка GNU/Linux

netcat host 23 | tee dump.dat

Тут мы использовали netcat и tee, netcat используем для получения сырых данных, включает управляющие символы telnet, tee утилита которая перенаправляет входящий поток данных в stdout и файл.

Средствами Perl

Тут мы пользуемся пакетом Net::Telnet в конструкторе которого можно указать логировать вход(Input_log), логировать выход(Option_log)

Пример:

#!/usr/bin/perl 

use 5.010;
use strict;
use warnings;
use Net::Telnet;

my $session = new Net::Telnet (Host=>"host", Input_log=>"input_dump.dat");
$session->cmd(...);
$session->close;

Пишем заглушку для Telnet/CLI на Perl

В Пишем заглушку для Telnet/CLI в качестве сервера выступал tcpserver из пакета ucspi-tcp. Раз уж использовал Perl, то приведу пример как можно сделать на чистом Perl.

Perl богат модулями на все случаи жизни, среди его модулей есть пакет Net::Server который представляет из себя движок для написание сервера. В основе Net::Server лежит паттерн шаблонный метод, он берет на себя работу по созданию и настройке сокета, ожидании и обработки нового подключения, и выводит для использования ряд переопределяемых методов.

Стоит дополнительно отметить, что после создания нового соединения, Net::Server переключает дескриптор сокета, на дескрипторы stdin и stdout, делая возможность читать из сокета привычным <>, а писать привычным print или say.

#!/usr/bin/perl

package MockServer;

use 5.010;
use strict;
use warnings;
use base qw(Net::Server::PreFork);

sub process_request
{
    while(<>)
    {
        chomp;
        if(/quit/)
        {
            say "bye";
            return;
        }

        print `$_`;
	}
}

1;

Net::Server::PreFork это реализация Net::Server использующая pre-fork модель обработки соединений, т.е. создается N процессов(ну, нет нормальной многопоточности в скриптовых языках Perl/Python/PHP) каждый из которых может держать по M соединений.

Реализация сервера:

#!/usr/bin/perl

use 5.010;
use MockServer;

my $server = MockServer->new(port=>23023);
$server->run();

Пишем заглушку для Telnet/CLI.

Сейчас работаю на контору, которая занимается мониторингом сетей передачи данных и сетевого оборудования. Одному из студентов на полставки было получено разработать компонент, получающий характеристики с одного устройства по CLI(Command-line interface) через Telnet. Все вроде как шло хорошо, пока не дошло дело до тестирования.

Студенту сразу же захотелось протестировать свой код на боевом сервере, видите ли ему нужна реальная железка. Естественно он был послан в песочницу, где он должен сделать заглушку.
Естественно я не могу требовать от других то, что не могу сделать сам. Привожу пример такой заглушки без всяких сокетов!
Будем использовать мощь UNIX-way в GNU/Linux.

Есть такой крутой man Daniel J. Bernstein, который помимо всего прочего написал пакет ucspi-tcp, это набор утилит с интерфейсом командной строки, для разработки клиент-серверных приложений.

Чувствуете мощь *nix систем ? Клиент-серверное приложение на bash’e !

Будем использовать программу tcpserver, а вместо баша любимый Perl, вот так выглядит её интерфейс:

tcpserver opts host port prog

opts опции запуска, host хост на котором будет висеть сервер, port порт на котором будет висеть сервер, prog наш скрипт или программа.

Как это все работает? tcpserver вешается на выбранный хост и порт, и начинает принимать входящие соединения. Когда кто-то к нему подключается, то он переключает дескриптор сокета на дескриптор 0 для чтения, и дескриптор 1 для записи и запускает программу prog. Для тех, кто не в курсе:

  • 0 — это дескриптор стандартного входа(stdin);
  • 1 — это дескриптор стандартного выхода(stdout).

Нам остается только лишь написать скрипт/программу которая читает строку их stdin, в зависимости от команды генерируем ответ в том виде, в каком отвечает железяка. В качестве примера привожу простой скрипт на Perl, считывает команду, если это quit, то выходим, иначе запускает команду и выводим результат на экран:

use 5.010;
 
$|=1;
 
while(<>)
{
    chomp;
    if(/quit/)
    {
        say "bye";
        exit(0);
    }
    
    print `$_`;
}

Запуск сервера:

tcpserver localhost 23023 ./cli.pl

Проверяем, подключаемся по telnet и получаем информацию о процессоре:

$ telnet localhost 23023 
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
cat /proc/cpuinfo