Эффективное программирование TCP-IP

       

Выходная информация, формируемая tcpdump


Информация, выдаваемая программой tcpdump, зависит от протокола. Рассмотрим несколько примеров, которые помогут составить представление о том, что можно получить от tcpdump для наиболее распространенных протоколов. Документация, поставляемая вместе с программой, содержит исчерпывающие сведения о формате выдачи.

Первый пример - это трассировка сеанса по протоколу SMTP (Simple Mail Transfer Protocol - простой протокол электронной почты), то есть процедура отправки элек­тронного письма. Распечатка на рис. 4.6 в точности соответствует выдаче tcpdump, только добавлены номера строк, напечатанные курсивом, удалено имя домена хоста bsd и перенесены длинные строки, не уместившиеся на странице.

Для получения трассировки послано письмо пользователю с адресом в домен gte. net. Таким образом, адрес имел вид user@gte.net.

Строки 1-4 относятся к поиску адреса SMTP-сервера, обслуживающего домен gte. net. Это пример выдачи, генерируемой tcpdump для запросов и ответов сервиса DNS. В строке 1 bsd запрашивает у сервера имен своего сервис-провайдера (nsl. ix.netcom.com) имя или имена почтового сервера gte.net. В первом находится временной штамп пакета (12:54:32.920881). Поскольку разрешающая способность таймера на машине bsd составляет 1 мкс, показано шесть десятичных знаков. Вы видите, что пакет ушел из порта 1067 на bsd в порт 53 (domain) на машине nsl. Далее, дается информация о данных в пакете. Первое поле (45801) -

1  12:54:32.920881 bsd.1067 > nsl.ix.netcom.com.domain:

 45801+ MX? gte.net. (25)

2  12:54:33.254981 nsl.ix.netcom.com.domain > bsd.1067:

      45801 5/4/9 (371) (DF)

3  12:54:33.256127 bsd.1068 > nsl.ix.netcom.com.domain:

      45802+ A? mtapop2.gte.net. (33)

4  12:54:33.534962 nsl.ix.netcom.com.domain > bsd.1068:

      45802 1/4/4 (202) (DF)

5  12:54:33.535737 bsd.1059 > mtapop2.gte.net.smtp:

 S 585494507:585494507(0) win 16384

      <mss 1460,nop,wscale 0,nop,nop,

      timestamp 6112 0> (DF)



6  12:54:33.784963 mtapop2.gte.net.smtp > bsd.1059:


      S1257159392:1257159392(0) ack 585494509 win 49152

      <mss 1460,nop,wscale 0,nop,nop,

      timestamp 7853753 6112> (DF)

7  12:54:33.785012 bsd.1059 > mtapop2.gte.net.smtp:

      .ack 1 win 17376 <nop,nop,

      timestamp 6112 7853753> (DF)

8  12:54:34.235066 mtapop2.gte.net.smtp > bsd.1059:

      P 1:109(108) ack 1 win 49152

      <nop,nop,timestamp 7853754 6112> (DF)

9  12:54:34.235277 bsd.1059 > mtapop2.gte.net.smtp:

      P 1:19(10) ack 109 win 17376

      <nop,nop,timestamp 6113 7853754> (DF)

      14 строк опущено

24 12:54:36.675105 bsd.1059 > mtapop2.gte.net.smtp:

      F 663:663(0) ack 486 3win 17376

      <nop,nop,timestamp 6118 7853758> (DF)   

25 12:54:36.685080 mtapop2.gte.net.smtp > bsd.1059:

      F 486:486(0) ack 663 win 49152

      <nop,nop,timestamp 7853758 6117> (DF)

26 12:54:36.685126 bsd.1059 > mtapop2.gte.net.smtp:

      . ack 487 win 17376

      <nop,nop,timestamp 6118 7853758> (DF)

27 12:54:36.934985 mtapop2.gte3.net.smtp > bsd.1059:

      F 486:486(0) ack 664 win 49152

      <nop,nop,timestamp 7853759 6118> (DF)

28 12:54:36.935020 bsd.1059 > mtapop2.gte.net.smtp:

      . ack 487 win 17376

      <nop,nop,timestamp 6118 7853759> (DF)

Рис. 4.6. Трассировка SMTP-сеанса с включением обмена по протоколам DNS и TCP

Это номер запроса, используемый функциями разрешения имен на bsd для сопоставления ответов с запросами. Знак «+» означает, что функция разрешения задает опрос DNS-сервером других серверов, если у него нет информации об ответе. Строка «MX?» показывает, что это запрос о записи почтового обмена для сети, имя которой стоит в следующем поле (gte.net). Строка «(25)» свидетельствует о том, что длина запроса - 25 байт.

Строка 2 - это ответ на запрос в строке 1. Число 45801 - это номер запроса, к которому относится ответ. Следующие три поля, разделенные косой чертой, - количество записей в ответе, записей от сервера имен (полномочного агента) и прочих записей. Строка «(371)» показывает, что ответ содержит 371 байт. И, наконец, строка «(DF)» означает, что в IP-заголовке ответа был поднят бит «Don't fragment» (не фрагментировать). Итак, эти две строки иллюстрируют использование системы DNS для поиска обработчиков почты (об этом кратко упоминалось в совете 29).



Если в двух первых строках было выяснено имя обработчика почты для сети gte.net, то в двух последующих выясняется его программа tcpdump IP-адрес. «А?» в строке 3 указывает, что это запрос IP-адреса хоста mtapop2.gte.net - одного из почтовых серверов компании GTE.

Строки 5-28 содержат детали обмена по протоколу SMTP. Процедура трехстороннего квитирования между хостами bsd и mtapop2 начинается в строке 5 и заканчивается строкой 7. Первое поле после временного штампа и имен хостов - это поле flags. «S» в строке 5 указывает, что в сегменте установлен флаг SYN. Другие возможные значения флага: «F» (FIN), «U» (URG), «P» (PUSH), «R» (RST) и «.» (нет флагов). Далее идут порядковые номера первого и последнего байтов, а за ними в скобках - число байтов данных. Эти поля могут вызвать некоторое недоумение, так как «порядковый номер последнего» - это первый неиспользованный порядковый номер, но только в том случае, когда в пакете есть данные. Удобнее всего считать, что первое число - это порядковый номер первого байта в сегменте (SYN или информационном), а второе - порядковый номер первого байта плюс число байтов данных в сегменте. Следует отметить, что по умолчанию показываются реальные порядковые номера для SYN-сегментов и смещения - для последующих сегментов (так удобнее следить). Это поведение можно изменить с помощью опции - S в командной строке.

Во всех сегментах, кроме первого SYN, имеется поле АСК, показывающее, какой следующий порядковый номер ожидает отправитель. Это поле (в виде ack nnn), как и раньше, по умолчанию содержит смещение относительно порядкового номера, указанного в сегменте SYN.

За полем АСК идет поле window. Это количество байтов данных, которое готов принять удаленный хост. Обычно оно отражает объем свободной памяти в буферах соединения.

И, наконец, в угловых скобках указаны опции TCP. Основные опции рассматриваются в RFC 793 [Postel 1981b] и RFC 1323 [Jacobson et al. 1992]. Они обсуждаются также в книге [Stevens 1994], а их полный перечень можно найти на Web-странице http://www.isi.edu/in-notes/iana/assignments/tcp-parameters.



В строках 8- 23 показан диалог между программой sendmail на bsd и SMTP сервером на машине mtapop2. Большая часть этих строк опущена. Строки 24-28 отражают процедуру разрыва соединения. Сначала bsd посылает FIN в строке 24 затем приходит FIN от mtapop2 (строка 25). Заметьте, что в строке 27 mtapop повторно посылает FIN. Это говорит о том, что хост не получил от bsd подтверждения АСК на свой первый FIN, и еще раз подчеркивает важность состояния ТIME-WAIT (совет 22).

Теперь посмотрим, что происходит при обмене UDP-датаграммами. С помощью клиента udphelloc (совет 4) следует послать один нулевой байт в порт сервера времени дня в домене netсоm.com:

bsd: $ udphelloc netcom4.netcom.com daytime

Thu Sep 16 15:11:49 1999

bsd: $

Хост netcom4 возвращает дату и время в UDP-датаграмме. Программа tcpdump печатает следующее:

18:12:23.130009 bsd.1127 > nectom4.netcom.com.daytime: udp 1

18:12:23.389284 nectom4.netcom.com.daytime > bsd.1127: udp 26

Отсюда видно, что bsd послал netcom4 UDP-датаграмму длиной один байт, a netcom4 ответил датаграммой длиной 26 байт.

Протокол обмена ICMP-пакетами аналогичен. Ниже приведена трассировка одного запроса, генерируемого программой ping с хоста bsd на хост netcom4:

1 06:21:28.690390 bsd > netcom4.netcom.com: icmp: echo request

2 06:21:29.400433 netcom4.netcom.com > bsd: icmp: echo reply

Строка icmp: означает, что это ICMP-датаграмма, а следующий за ней текст описывает тип этой датаграммы.

Один из недостатков tcpdump - это неполная поддержка вывода собственно данных. Часто во время отладки сетевых приложений необходимо знать, какие данные посылаются. Эту информацию можно получить, задав в командной строке опции -s и -х, но данные будут выведены только в шестнадцатеричном формате. Опция -х показывает, что содержимое пакета нужно выводить в шестнадцатерич­ном виде. Опция -s сообщает, сколько данных из пакета выводить. По умолчанию tcpdump выводит только первые 68 байт (в системе SunOS NIT - 96 байт). Этого достаточно для заголовков большинства протоколов. Повторим предыдущий при­мер, касающийся UDP, но здесь нужно выводить также следующие данные:



tcpdump -х -s 100 -l

После удаления строк, относящихся к DNS, и исключения имени домена из адреса хоста bsd получается следующий результат:

1 12:57:53.299924 bsd.1053 > netcom4.netcom.com.daytime: udp 1

4500 001d 03d4 0000 4011 17al c7b7 c684

c7b7 0968 041d 000d 0009 9c56 00

2 12:57:53.558921 netcom4.netcom.com.daytime > bsd.1053: udp 26

4500 0036 f0c8 0000 3611 3493 c7b7 0968

c7b7 c684 000d 041d 0022 765a 5375 6e20

5365 7020 3139 2030 393a 3537 3a34 3220

3139 3939 0a0d

Последний байт в первом пакете - это нулевой байт, который udphelloc посылает хосту netcom4. Последние 26 байт второго пакета - это полученный ответ. Интерпретировать приведенные в нем шестнадцатеричные цифры довольно трудно.

Авторы tcpdump не хотели давать ASCII-представление данных, так как полагали, что это упростит кражу паролей для технически неподготовленных лиц. Теперь многие считают, что широкое распространение программ для кражи паролей сделало это опасение неактуальным. Поэтому есть основания полагать, что в последующие версии tcpdump будет включена поддержка вывода в коде ASCII*.(* Начиная с версии 3.5 tcpdump позволяет выводить и ASCII-представление. Для этого надо одновременно указать опции -X и -х. - Прим. автора.)

А пока многие сетевые программисты упражняются в написании фильтр, преобразующих выдачу tcpdump в код ASCII. Несколько подобных программ есть в Internet. Показанный в листинге 4.1 сценарий Perl запускает tcpdump, перенаправляет ее вывод к себе и перекодирует данные в ASCII.

Листинг 4.1. Perl-сценарий для фильтрации выдачи tcpdump

1    #! /usr/bin/perl5

2    $tcpdump = "/usr/sbin/tcpdump";

3    open( TCPD, "$tcpdump 8ARGV |" )

4    die "не могу запустить tcpdump: \$!\\n";

5    $| = 1;

6    while ( <TCPD> )

7    {

8    if ( /^\t/ }

9    {

10     chop;

11     $str =  $_;

12     $str =~ tr / \t//d;

13     $str = pack "H*"  , $str;

14     $str =~ tr/\x0-\xlf\x7f-\xff/./;

15     printf "\t%-40s\t%s\n", substr(   $_, 4 ), $str;

16   }

17   else

18   {

19     print;

20   }

21   }

Если еще раз прогнать последний пример, но вместо tcpdump использоват tcpd, то получится следующее:

1 12:58:56.428052 bsd.1056 > netcom4.netcom.com.daytime: udp 1

4500 OOld 03d7 0000 4011 179e c7b7 c684 E.......@....

c7b7 0968 041d OOOd 0009 9c56 00 ..-h......S.

2 12:58:56.717128 netcom4.netcom.com.daytime > bsd.1053: udp 26

4500 0036 lOfl 0000 3611 146b c7b7 0968  E..6....6..k..h

c7b7 c684 OOOd 0420 0022 7656 5375 6e20  ......."rVSun

5365 7020 3139 2030 393a 3538 3a34 3620  Sep 19 09:58:46

3139 3939 OaOd                         1999..


Содержание раздела