Русский
Русский
English
Статистика
Реклама

Сетевики нужны и вот почему


Картинка взята из телнет-видео Звёздных войн: telnet towel.blinkenlights.nl

Недавно был пост о том, нужны ли сетевики. До тех пор, пока проверка доступности tcp/ip порта кажется чем-то сложным даже для администраторов БД и AD, сетевики несомненно нужны. Они особенно полезны в тех случаях, когда необходимо понять почему так плохо работает некое клиент-серверное приложение ценой в пароход.
Иногда мало знать ping и traceroute для того, чтобы понять и устранить проблему в сети. Необходимо понимать как работают все звенья в цепи, а сделать это может лишь сетевик. Рассмотрим несколько таких примеров.

Чем Netcat лучше telnet?


Практически всегда, если речь идет о проверке TCP/UDP порта стараются сделать это через telnet и приходится всякий раз просить поставить Netcat. Есть несколько причин, по которым telnet сильно проигрывает. Вот основные причины.

  • telnet не умеет различать причины недоступности порта. Все, или ничего connect, либо fail. Netcat может подсказать, в чем проблема. В этом случае все просто, такого порта в состоянии LISTENING нет.
  • Не умеет в UDP, SCTP и прочие, ничего кроме TCP.
  • Не имеет опций тайм-аута соединения -w и проверки без подключения -z

Теперь не говорите, что вы не знали и закопайте поглубже telnet.

(1:1004)$ ncat -v -w3 -z some.server 1111Ncat: Version 7.80 ( https://nmap.org/ncat )Ncat: Connection refused.

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

(1:1005)$ ncat -v -w3 -z another.server 1521Ncat: Version 7.80 ( https://nmap.org/ncat )Ncat: No route to host.

Бытует мнение, что на Windows нет альтернативы telnet, однако это неверно. Существует штатная утилита Test-NetConnection, которую можно запустить из PowerShell.

Test-NetConnection -ComputerName "www.contoso.com" -Port 80

Linux MIB в помощь


Если ваш сервер вдруг перестал реагировать на внешние раздражители и клиентские запросы стали провисать, не всегда причина в выдернутом сетевом кабеле, или зависших сервисах JBoss/Tomcat. Прежде, чем заводить кейс в тех-поддержку проверьте Linux MIB. Есть множество программ, выдающих статистику ядра Linux по внутренним счетчикам SNMP. Самая распространенная из них все еще netstat.

(1:1008)$ netstat -s |grep prune873 packets pruned from receive queue because of socket buffer overrun(1:1009)$ nstat -s |grep PruneTcpExtPruneCalled   873 0.0

Если сервер не справляется с сетевой нагрузкой и буфер сокета перманентно переполнен, тогда ядро будет просто сбрасывать все новые пакеты и счетчик будет расти на глазах. Чтобы исправить эту ситуацию, можно добавить некоторые настраиваемые параметры в файле sysctl.conf. Текущие значения можно увидеть из файловой системы /proc.

(1:1010)$ cat /proc/sys/net/ipv4/tcp_rmem4096    16384   4194304(1:1011)$ cat /proc/sys/net/ipv4/wcp_rmem4096    16384   4194304(1:1012)$ grep -e tcp_rmem -e tcp_wmem /etc/sysctl.confnet.ipv4.tcp_rmem = 4096 87380 16777216net.ipv4.tcp_wmem = 4096 65536 16777216

Три значения параметра tcp_rmem/tcp_wmem обозначает соответственно минимальное, пороговое и максимальное значение. По умолчанию величины выставлены довольно разумно, поэтому менять их без веских оснований не стоит. Чаще всего такая ситуация может возникнуть на сети с пропускной способностью 10 GiB/s. После сохранения изменений в файле sysctl.conf следует выполнить systcl -p. Эта команда запускает системный вызов setsockopt (SO_RCVBUF).
Следует отметить, что буфер setsockopt(SO_RCVBUF), установленный в приложении, будет ограничен значениями, установленными в net.core.rmem_default и net.core.rmem_max и если приложение имеет буфер размером 1 мб, но net.core.rmem_max составляет всего 256 кб, то буфер сокета приложения будет ограничен этим значением.

Диагностика сети с помощью системных вызовов


Для любого сетевика WireShark абсолютно необходимый инструмент отладки, иногда главный. Не раз и не два только благодаря WireShark удавалось спасти проект в очень сложной ситуации. Но бывают случаи, когда только в системных вызовах ядра можно увидеть сетевую проблему.
В частности отброшенные пакеты нельзя будет увидеть в tcpdump, или WireShark. Зато можно их увидеть в режиме реального времени с помощью tcpdrop из сета bcc-tools. У команды нет никаких опций, просто выполните tcpdop. Вывод состоит из сокета, статусе соединения и флагах TCP. Далее идет трассировка стека ядра, которая привела к этому сбросу пакета.

(1:1013)$ /usr/share/bcc/tools/tcpdropTIME     PID    IP SADDR:SPORT  > DADDR:DPORT  STATE (FLAGS)16:31:07 3103   4  93.184.216.34:443       > 192.168.11.32:36222   ESTABLISHED (PSH|ACK)b'tcp_drop+0x1'b'tcp_data_queue+0x1e7'b'tcp_rcv_established+0x1df'b'tcp_v4_do_rcv+0x131'b'tcp_v4_rcv+0xad3'b'ip_protocol_deliver_rcu+0x2b'b'ip_local_deliver_finish+0x55'b'ip_local_deliver+0xe8'b'ip_rcv+0xcf'b'__netif_receive_skb_core+0x429'b'__netif_receive_skb_list_core+0x10a'b'netif_receive_skb_list_internal+0x1bf'b'netif_receive_skb_list+0x26'b'iwl_pcie_rx_handle+0x447'b'iwl_pcie_irq_handler+0x4d5'b'irq_thread_fn+0x20'b'irq_thread+0xdc'b'kthread+0x113'b'ret_from_fork+0x35'

В bcc-tools имеется еще одна очень полезная утилита tcplife, которая показывает параметры TCP соединение, в том числе, длительность сеанса. У этой команды есть некоторые опции.

(1:1014)$ /usr/share/bcc/tools/tcplife -h...examples:    ./tcplife           # trace all TCP connect()s    ./tcplife -T        # include time column (HH:MM:SS)    ./tcplife -w        # wider columns (fit IPv6)    ./tcplife -stT      # csv output, with times & timestamps    ./tcplife -p 181    # only trace PID 181    ./tcplife -L 80     # only trace local port 80    ./tcplife -L 80,81  # only trace local ports 80 and 81    ./tcplife -D 80     # only trace remote port 80

Просмотр сессий выглядит так.

# ./tcplife -D 80PID   COMM       LADDR           LPORT RADDR           RPORT TX_KB RX_KB MS27448 curl       100.66.11.247   54146 54.154.224.174  80        0     1 263.8527450 curl       100.66.11.247   20618 54.154.164.22   80        0     1 243.6227452 curl       100.66.11.247   11480 54.154.43.103   80        0     1 231.1627454 curl       100.66.11.247   31382 54.154.15.7     80        0     1 249.95

Может так случится, что между клиентом и сервером расположен межсетевой экран, либо IPS/IDS с набором правил по обрыву длительности TCP сессии по прошествии определенного времени, или достижении некоего объёма трафика. В этом случае диагностика подобного кейса может затянутся неопределенно долго, так как находится в слепой зоне, как со стороны клиентского, так и со стороны серверного приложения. Единственный способ понять в чему тут дело, это использовать инструменты bcc-tools.

Недооцененный резолвинг


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

getnameinfo(getaddrinfo(HOSTNAME)) = HOSTMANE

ункции getnameinfo и getaddrinfo являются заменой устаревших gethostbyname и gethostbyaddr соответственно.

int getnameinfo(const struct sockaddr *addr, socklen_t addrlen,    char *host, socklen_t hostlen,    char *serv, socklen_t servlen, int flags);int getaddrinfo(const char *node, const char *service,    const struct addrinfo *hints, struct addrinfo **res);

Положительный пример lib.ru

(1:1015)$ host lib.rulib.ru has address 81.176.66.163...(1:1016)$ host 81.176.66.163163.66.176.81.in-addr.arpa domain name pointer lib.ru.Отрицательный пример - example.com.(1:1017)$ host example.comexample.com has address 93.184.216.34(1:1018)$ host 93.184.216.34Host 34.216.184.93.in-addr.arpa. not found: 3(NXDOMAIN)


Если бы IP 93.184.216.34 указывал не на example.com, а на иной хост, то и это было бы ошибкой. Только тождество результат двустороннего разрешения имен гарантирует отсутствие ошибок настройки.
Вообще-то используя утилиту host следует помнить, что она так же, как dig и nslookup используют лишь DNS для разрешения имён хостов и игнорируют записи в файле /etc/hosts. По этой причине целесообразнее использовать команду getent.

(1:1019)$ strace -f -e trace=openat host my.router 2>&1 |grep -e "^openat" -e addressopenat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/usr/lib64/libcrypto.so.1.1", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/usr/lib64/libuv.so.1", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/usr/lib64/libidn2.so.0", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/lib64/libz.so.1", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/usr/lib64/libunistring.so.2", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/proc/self/task/7164/comm", O_RDWR) = 3(1:1020)$ strace -f -e trace=openat getent ahosts my.router openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/usr/lib64/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/usr/lib64/gconv/gconv-modules.cache", O_RDONLY) = 3openat(AT_FDCWD, "/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/etc/host.conf", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/etc/hosts", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/usr/lib64/libidn2.so.0", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/usr/lib64/libunistring.so.2", O_RDONLY|O_CLOEXEC) = 3openat(AT_FDCWD, "/usr/lib64/charset.alias", O_RDONLY|O_NOFOLLOW) = -1 ENOENT (No such file or directory)192.168.10.10    STREAM my.router192.168.10.10    DGRAM  192.168.10.10    RAW    +++ exited with 0 +++


Из вывода видно, что host не обращается к файлу /etc/hosts и по этой причине не в состоянии определить IP адрес маршрутизатора. Напротив, getent ищет в этом файле и находит соответствующую запись.

Использованные материалы






Источник: habr.com
К списку статей
Опубликовано: 30.10.2020 12:22:53
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Блог компании ruvds.com

Настройка linux

Системное администрирование

*nix

Сети

Netcat

Telnet

Linux

Системные вызовы

Tcp

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru