Netstat, где мои дейтаграммы?

    Вероятно, что трудно найти другую, настолько же полезную и плохо документированную программу, как Netstat, имеется в виду, опция показа статистики сетевого потока данных. Когда мы проводим инспекцию состояния сети на отдельно взятом Linux узле, всегда можно быть уверенным, что это утилита имеется в наличии. И вот мы хотим понять — справляется ли сетевой стэк с нагрузкой, или проблема на верхних этажах OSI, собственно там, где сосредоточенно крутятся колесики бизнес-логики нашего приложения.




    (5:562)$ netstat -s |wc -l
    124

    Ура, у нас куча полезной информации, сейчас мы быстренько сообразим, что к чему. Вот только бы понять, что же это за зверь такой timeout in transit, явно что-то нехорошее.


    Icmp:
    11475275 ICMP messages received
    327527 input ICMP message failed.
    ICMP input histogram:
    detination unreachable: 2233840
    timeout in transit: 5612259

    Сейчас гляну в мануал.


    # man netstat |grep timeout
    #

    Пустое множество подсказывает, что пора узнавать у Яндекса, Гугла и даже у DuckDuckGo. Результат поиска был примерно такой-же, но только Гугл выдал 111 тыс. вариантов пустого множества, а Яндекс лаконично ограничился 326 вариантами.


    Но мы ведь не напрасно выбрали открытое ПО, всегда можно свериться с первоисточником. В нашем случае исходный код находится в файле nertstat.c пакета Net-tools.


    Вот та часть функции int main, в которой определяется действие для показа статистики.


        case '?':
            usage(E_OPTERR);
        case 'h':
            usage(E_USAGE);
        case 's':
            flag_sta++;
    ...
        if (flag_sta) {
            if (!afname[0])
                safe_strncpy(afname, DFLT_AF, sizeof(afname));
    
            if (!strcmp(afname, "inet")) {
    #if HAVE_AFINET
                parsesnmp(flag_raw, flag_tcp, flag_udp, flag_sctp);

    Функция parsesnmp определена в файле statistics.c и парсит файлы:


    /proc/net/netstat
    /proc/net/snmp
    /proc/net/sctp/snmp

    Ясно понятно, значит можно просто заглянуть в /proc/net/snmp и увидеть, что стоит за timeout in transit.


    # cat /proc/net/snmp |grep -iw icmp
    Icmp: InMsgs InErrors InCsumErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps
    Icmp: 127 2 0 90 0 0 0 0 25 0 8 0 4 0 1763 0 1730 0 0 0 0 0 25 0 8 0 0

    Сравнивая эти значения с выводом команды netstat, можем заключить, что timeout in transit соответствует переменной InTimeExcds, а цепочка далее ведет к файлу /usr/include/linux/snmp.h, где определены все эти поля.


    /* icmp mib definitions */
    /*
     * RFC 1213:  MIB-II ICMP Group
     * RFC 2011 (updates 1213):  SNMPv2 MIB for IP: ICMP group
     */
    enum
    {
        ICMP_MIB_NUM = 0,
        ICMP_MIB_INMSGS,            /* InMsgs */
        ICMP_MIB_INERRORS,          /* InErrors */
        ICMP_MIB_INDESTUNREACHS,        /* InDestUnreachs */
        ICMP_MIB_INTIMEEXCDS,           /* InTimeExcds */
        ICMP_MIB_INPARMPROBS,           /* InParmProbs */
        ICMP_MIB_INSRCQUENCHS,          /* InSrcQuenchs */
        ICMP_MIB_INREDIRECTS,           /* InRedirects */
        ICMP_MIB_INECHOS,           /* InEchos */
        ICMP_MIB_INECHOREPS,            /* InEchoReps */
        ICMP_MIB_INTIMESTAMPS,          /* InTimestamps */
        ICMP_MIB_INTIMESTAMPREPS,       /* InTimestampReps */
        ICMP_MIB_INADDRMASKS,           /* InAddrMasks */
        ICMP_MIB_INADDRMASKREPS,        /* InAddrMaskReps */
        ICMP_MIB_OUTMSGS,           /* OutMsgs */
        ICMP_MIB_OUTERRORS,         /* OutErrors */
        ICMP_MIB_OUTDESTUNREACHS,       /* OutDestUnreachs */
        ICMP_MIB_OUTTIMEEXCDS,          /* OutTimeExcds */
        ICMP_MIB_OUTPARMPROBS,          /* OutParmProbs */
        ICMP_MIB_OUTSRCQUENCHS,         /* OutSrcQuenchs */
        ICMP_MIB_OUTREDIRECTS,          /* OutRedirects */
        ICMP_MIB_OUTECHOS,          /* OutEchos */
        ICMP_MIB_OUTECHOREPS,           /* OutEchoReps */
        ICMP_MIB_OUTTIMESTAMPS,         /* OutTimestamps */
        ICMP_MIB_OUTTIMESTAMPREPS,      /* OutTimestampReps */
        ICMP_MIB_OUTADDRMASKS,          /* OutAddrMasks */
        ICMP_MIB_OUTADDRMASKREPS,       /* OutAddrMaskReps */
        ICMP_MIB_CSUMERRORS,            /* InCsumErrors */
        __ICMP_MIB_MAX
    };

    Кому как, а для меня RFC 1213 как для химика таблица Менделеева — необходимо знать на зубок, так как, это один из краеугольных камней мониторинга сетевых устройств. Вот определение элемента из RFC 1213 пишу по памяти.


    icmpInTimeExcds OBJECT-TYPE
                  SYNTAX  Counter
                  ACCESS  read-only
                  STATUS  mandatory
                  DESCRIPTION
                          "The number of ICMP Time Exceeded messages received."
                  ::= { icmp 4 }

    Пока что создается впечатление, что все эти определение как масло масляное, не раскрывают сути, но по счастью ICMP Time Exceeded — часть определения протокола ICMP.


    Если обрабатывающий дейтаграмму шлюз видит, что поле TTL содержит нулевое значение, дейтаграмма должна быть отброшена. Шлюз может уведомить отправителя дейтаграммы с помощью сообщения time exceeded.

    Итак, мы нашли то что искали. Вывод команды netstat, в котором было это загадочное поле, означает число отброшенных ICMP пакетов с нулевым TTL. IRL[1] это означает, что в сети есть кольцо, где пакеты профукали весь TTL[2] .


    timeout in transit: 5612259

    Linux MIB


    В процессе этого погружения в дебри Linux ядра, я с удивлением обнаружил SNMP подсистему. Нет, не SNMP агента, упаси нас Alan Cox, а именно небольшой SNMP стэк. Об этом написано в комментария к файлу /usr/src/linux/include/net/snmp.h.


    /*
     *              SNMP MIB entries for the IP subsystem.
     *              Alan Cox <gw4pts@gw4pts.ampr.org>
     *
     *              We don't chose to implement SNMP in the kernel (this would
     *              be silly as SNMP is a pain in the backside in places). We do
     *              however need to collect the MIB statistics and export them
     *              out of /proc (eventually)
     */

    SNMP означает Simple Network Management Protocol, но как гласит бородатая шутка, никогда еще в аббревиатуре буква S так не лгала. Я планирую написать об этой мозгодробилке отдельно, так как именно на нем крутится весь софт мониторинга вычислительных сетей и сетевых узлов. Пока же — необходимый минимум, чтобы было понятно, откуда берутся переменные статистики netstat.




    В самом простом случае мы имеем архитектуру клиент — сервер, где в роли клиента может выступать MRTG или Munin, а серверная часть — это SNMP агент на сетевом узле. Почти все современные сетевые устройства имеют на борту SNMP агента, даже домашние WiFi роутеры. Windows имеет свой SNMP Service, а Linux и открытые Unix системы используют Net-SNMP.


    SNMP клиент и сервер обмениваются сообщениями: клиент посылает запрос, а сервер возвращает ответ. Обычно, этот обмен выгладит следующим образом.


    К. — Чебурашка, приборы!
    С. — Сорок
    К. — Что сорок?
    С. — А что приборы?

    Клиент просит выдать значение некой переменной из Великого Словаря. Сервер смотрит в ВС, находит переменную, смотрит в свой реестр и возвращает значение. Великий Словарь — это MIB[3] Database из рисунка.


    Вот как выглядит опрос системных переменных, uptime и других на man странице.


    snmpwalk -Os -c public -v 1 zeus system 
    
    sysDescr.0 = STRING: "SunOS zeus.net.cmu.edu 4.1.3_U1 1 sun4m"
    sysObjectID.0 = OID: enterprises.hp.nm.hpsystem.10.1.1
    sysUpTime.0 = Timeticks: (155274552) 17 days, 23:19:05
    sysContact.0 = STRING: ""
    sysName.0 = STRING: "zeus.net.cmu.edu"
    sysLocation.0 = STRING: ""
    sysServices.0 = INTEGER: 72

    Надо понимать, что за эвфемизмами Великого Словаря, реестра и самого протокола SNMP скрываются десятки RFC и бездна их возможных реализаций. Возвращаясь к нашему файлу snmp.h, видна лишь надводная часть айсберга:


    # grep RFC /usr/include/linux/snmp.h
    
    * RFC 1213:  MIB-II
    * RFC 2011 (updates 1213):  SNMPv2-MIB-IP
    * RFC 2863:  Interfaces Group MIB
    * RFC 2465:  IPv6 MIB: General Group
    * RFC 1213:  MIB-II ICMP Group
    * RFC 2011 (updates 1213):  SNMPv2 MIB for IP: ICMP group
    * RFC 2466:  ICMPv6-MIB
    * RFC 1213:  MIB-II TCP group
    * RFC 2012 (updates 1213):  SNMPv2-MIB-TCP
    * RFC 1213:  MIB-II UDP group
    * RFC 2013 (updates 1213):  SNMPv2-MIB-UDP
     LINUX_MIB_TCPMINTTLDROP, /* RFC 5082 */

    И если бы это было всё, расшифровка статистки netstat могла быть такой:


    переменная из netstat --> соответствующая ей строка из /proc:
    * /proc/net/snmp
    * /proc/net/netstat
    * /proc/net/sctp/snmp
    --> соответствующее RFC --> определение.

    Однако, даже такой многоступенчатой расшифровки недостаточно, так как значительную часть snmp.h занимает загадочный Linux MIB, переменные которого ни в каком RFC не определены, и в Великом Словаре — MIB Database, их тоже нет.


    /* linux mib definitions */
    enum
    {
        LINUX_MIB_NUM = 0,
        LINUX_MIB_SYNCOOKIESSENT,       /* SyncookiesSent */
        LINUX_MIB_SYNCOOKIESRECV,       /* SyncookiesRecv */
        LINUX_MIB_SYNCOOKIESFAILED,     /* SyncookiesFailed */
        LINUX_MIB_EMBRYONICRSTS,        /* EmbryonicRsts */
        LINUX_MIB_PRUNECALLED,          /* PruneCalled */
        LINUX_MIB_RCVPRUNED,            /* RcvPruned */
        LINUX_MIB_OFOPRUNED,            /* OfoPruned */
    ...
        LINUX_MIB_TCPMTUPSUCCESS,       /* TCPMTUPSuccess */
        __LINUX_MIB_MAX
    };

    Мы готовы к следующему этапу погружения, в следующей статье попытаемся выяснить, что скрывается за ошибками памяти буфера, и как в tcp коллапсируют нарушителей очереди .




    1. В реальной жизни, от английского in real life.
    2. Время жизни пакета, от английского time to live
    3. Management Information Base — структурированный набор управляющей информации объектов узла. Подробнее, тут.
    • +28
    • 16,3k
    • 9
    Поделиться публикацией
    Комментарии 9
      +1
      Отлично! Ждем следующую часть!
        +1
        Вывод команды netstat, в котором было это загадочное поле, означает число отброшенных ICMP пакетов с нулевым TTL. IRL это означает, что в сети есть кольцо, где пакеты профукали весь TTL

        Какой-то уж слишком однозначный вывод о наличии кольца.
        Возникновение TTL=0 обычная ситуация при трассировке маршрутов к узлам.

        Да и было неплохо в статье указать, что MIB — это Managment Information Base база данных информации управления, содержащая информацию обо всех объектах устройства(параметры и настройки).

        значительную часть snmp.h занимает загадочный Linux MIB, переменные которого ни в каком RFC не определены

        По определению для них отдельного RFC не должно быть, хоть в вашем тексте и есть строчка LINUX_MIB_TCPMINTTLDROP, /* RFC 5082 */
        Описание переменных можно найти в коде net-tools.
          0
          Принимаю критику насчет MIB. У меня тут профессиональное слепое пятно. Так по работе, мибка, мибка… Ставлю сноску.
            0
            Дело не в MIB.

            Этот параметр вообще сам по себе ни о чем не говорит.

            Запустите на полчасика mtr или любой другой трассировщик маршрутов и счетчик timeout in transit взлетит до небес.
              0
              Получается, что traceroute тоже обнуляет TTL дейтаграмм на сервере. Но в таком случае админ будет знать о трассировке, в то время как замкнутое кольцо — явление стихийное и вот тут как раз анализ статистики Netstat поможет.
              В любом случае это хорошо дополняет основную тему. Лучше знать все возможные причины состояния timeout in transit.
          +3
          Помнится тут недавно был спор о том, что пакет net-tools морально устарел и пора бы переходить на новые утилиты, ss например.
            0
            Так оно и есть к сожалению. Тот же statistics.h, из Net-Tools, последний коммит в 2001 г. в то время как tcp/ip в ядре Linux постоянно меняется. Хорошая и подробная документация на замеры производительности сети имеются в коммерческих продуктах, вероятно они и оттягивают на себя основные силы разработчиков.
              0
              а какие коммерческие продукты посоветуете для анализа производительности сети?
                0
                Я уже много лет работаю с этим продуктом, поэтому его и советую из коммерческих приложений. Network Node Manager i-series Ultiate, который включает в себя NNMi модули iSPI Performance for Metris, iSPI Performance for Quality Assurance и другие.
                Тем не менее, важно выжимать максимум из открытого и качественного ПО: таких как netstat или ss.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое