Диагностика сетевого обмена существенно облегчает решение разнообразных задач, связанных с эксплуатацией или, разработкой сетевых приложений. К сетевым диагностическим специальным средствам относят анализаторы пакетов и сетевые сканеры, которые применяются самостоятельно или вместе с трассировщиками системных и библиотечных вызовов.
Содержимое
Анализаторы пакетов tcpdump и tshark
Анализаторы пакетов предназначены для перехвата данных, поступающих из сети на сетевые интерфейсы или отправляющиеся в сеть с сетевых интерфейсов. Современные анализаторы пакетов кроме, собственно, захвата пакетов осуществляют их детальный протокольный разбор, а также позволяют отфильтровывать подлежащие анализу пакеты по ряду критериев.
В листинге ниже показан пример использования наиболее распространенного, «классического» анализатора пакетов tcpdump, анализирующего пакеты на интерфейсе (-i, interface) wlan0, адресованные порту port 53.
Анализатор пакетов tcpdump
pts/1
lumpy@ubuntu:~$ host 2x2tv.ru
2x2tv.ru has address 178.63.2.134
2x2tv.ru mail is handled by 20 relay2.tnt-tv.ru.
2x2tv.ru mail is handled by 30 relay3.tnt-tv.ru.
2x2tv.ru mail is handled by 10 mx.tnt-tv.ru.
pts/2
lumpy@ubuntu:~$ sudo tcpdump -i wlanO port 53
tcpdump: verbose output suppressed, use -v or -w for full protocol decode
listening on wlan0, link-type EN10MB (Ethernet), capture size 65535 bytes
tcpdump: verbose output suppressed, use -v or -w for full protocol decode
listening on wlanO, link-type EN10MB (Ethernet), capture size 65535 bytes
15:11:32.139394 IP ubuntu.local.40694 > 192.1£8.100.1.donaUi: 27739» A? 2x2tv.ru. 26)
15:11:32.144674 IP 192.168.100.1.donain > ubuntu.local.40694: 27739 1/0/0 A 178.63.2.134 (42)
15:11:32.145260 IP ubuntu.local.22022 > 192.1£8.100.1.dcnaln: 37673» AAAA? 2x2tv.ru. (26)
15:11:32.147959 IP 192.168.100.1.domain > ubuntu.local.48132: 41476 NXDomain 0/0/0 (44)
15:11:32.149187 IP ubuntu.local.58056 > 192.m 100.1.domain: 62332+ MX? 2x2tv.ru. (26)
15:11:32.154191 IP 192.168.100.1.domain > ubuntu.local.58056: 62332 3/0/2 MX mx.tnt-tv.ru. 10, … (130)
^C
6 packets captured
6 packets received by filter
0 packets dropped by kernel
Анализу подвергается работа DNS-клиента host, отображающего имя домена 2x2tv.ru на IP-адрес и имена его почтовых адресов (MX-записи DNS). В результате анализа захваченных пакетов наблюдаются запросы и ответы DNS-протокола к локальному кэширующему серверу 192.168.100.1, который на вопрос А? адреса IPv4, соответствующего имени 2x2tv.ru, отвечает адресом а 178.63.2.134, а на вопрос AAAA? адреса IPv6 отвечает NXDomain (отсутствует такая DNS-запись).
Терминальный1 анализатор пакетов tshark, позволяющий проводить детальный анализ прикладных протоколов, таких как SSH, HTTP, FTP, NFS и пр., проиллюстрирован в листинге ниже. Здесь анализируется работа пользовательского агента curl, запрашивающего Web-pecypc по адресу http://iplnfo.io/ctty.
В результате захвата пакетов на интерфейсе (-i, interface) wlan0, адресованных порту port 80, просматриваются (-R, read filter) пакеты, содержащие http-запросы, при этом детальному анализу (-V, view) подвергается только (-O, only) их http-содержимое.
В результате анализа, например, можно сделать вывод о программном обеспечении Web-сервера, обслуживающего сайт http://ipinfi.io.
Анализатор пакетов wireshark
pts/1
lumpy@ubuntu:~$ curl http://ipinfo.io/city
Saint Petersburg
lumpy@ubuntu:~$ sudo tshark -i wlanO port 80 -V -0 http,data-text-lines -R http
tshark: Lua: Error during loading:
[string «/usr/share/wireshark/init.lua»]:45: dofile has been disabled
Running as user «root» and group «root». This could be dangerous.
Capturing on wlan0
Frame 38: 229 bytes on wire (1832 bits), 229 bytes captured (1832 bits)
Ethernet II, Src: Intelcor_а2:28:4е (b8:03:05:a2:28:4е), Dst: 9c:37:f4:76:c5:S8 (9c:37:f4:76:c5:58)
Internet Protocol Version 4, Src: 192.168.100.5 (192.168.100.5), Dst: S2.28.249.93 (52.28.249.93)
Transmission Central Protocol, Src Port: 43564 (43564), Dst Port: http ($0), Seq: 1, Ack: 1, Len: 163
Hypertext Transfer Protocol
GET /city HTTP/1.1\r\n
[Expert Info (Chat/Seqgence): GET /city HTTP/1.1\r\n]
[Message: GET /city HTTP/1.1\r\n]
[Sa/erity level: Chat]
[Group: Sequence]
Request Method: GET
Request URI: /city
Request Version: HTTP/1.1
User-Agent: curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 GpenSSL/1.0.1 zlib/1.2.3.4 libidn/1-23 …
Host: ipinfo.io\r\n
Accept: */*\r\n
[Full request URI: http://ipinfo.io/city]
Frame 54: 313 bytes on wire (2504 bits), 313 bytes captured (2504 bits)
Ethernet II, Src: 9c:37:f4:76:c5:58 (9c:37:f4:76:c5:58), Dst: IntelCor_a2:28:4e (b8:03:05:a2:28:4e)
Internet Protocol Version 4, Src: 52.28.249.93 (52.28.249.93), Dst: 192.168.100.5 (192.168.100.5)
Transmission Control Protocol, Src Port: http (80), Dst Port: 43564 (43564), Seq: 1, Ack 164, Len: 247
Hypertext Transfer Protocol
HTTP/1.1 200 OK\r\n
[Expert Info (Chat/Sequence): HTTP/1.1 200 OK\r\n]
[Message: HTTP/1.1 200 OK\r\n]
[Severity level: Chat]
[Group: Sequence]
Request Version: HTTP/1.1
Status Code: 200
Response Phrase: OK
Assess Control-Allow-Origin: *\r\n ,
Content-Type: text/html; charset=utf-8\r\n
Date: Sun, 13 Mar 2018 12:37:31 CMT\r\n
Server: ngirx/1.6.2\r\n
Set-Cookie: first_referrer=; Path=/\r\n
Content-length: 17\r\n
[Content length: 17]
Connection: keep-alive\r\n
\r\n
Line-based text data: text/html
Saint Petersburg\n
^C2 packets captured
Сетевой сканер nmap
Сетевой сканер W:[nmap] предназначен для поиска служб по их открытым портам на указанных узлах сети. В примере из листинга ниже показан процесс и результаты сканирования узла 192.168.190.1 (беспроводной маршрутизатор, арендованный у провайдера Интернета).
Сканирование выполнялось способом TCP connect scan т. е. предпринималась попытка установить соединение TCP с каждым из 1000 «популярных» портов. В результате оказывается, что на узле открыты 7 портов, 3 из которых недоступны (вероятно, отфильтрованы по IP-адресу), а оставшиеся 4 (в частности, порты 53/DNS и 80/WWW) доступны для присоединения.
Сетевой сканер nmap
lumpy@ubuntu:~$ nmap -n -vvv —reason 192.168.100.1
Starting Nmap 5.21 ( http://nnap.org ) at 2018-04-03 17:48 MSK
Initiating Ping Scan at 17:48
Scanning 192.168.100.1 [2 ports]
Completed Ping Scan at 17:48, 0.00s elapsed (1 total hosts)
Initiating Connect Scan at 17:48
Scanning 192.168.100.1 [1000 ports]
Discovered open port 80/tcp on 192.168.100.1
Discovered open port 53/tcp on 192.168.100.1
Discovered open port 49152/tcp on 192.168.100.1
Discovered open port 49153/tcp on 192.168.100.1
Completed Connect Scan at 17:48, 1.58s elapsed (1000 total ports)
Nmap scan report for 192.168.100.1
Host is up, received conn-refused (0.055s latency).
Scanned at 2018-04-03 17:48:53 MSK for 2s
Not shown: 993 closed ports
Reason: 993 conn-refused
PORT STATE SERVICE REASON
21/tcp filtered ftp no-response
22/tcp filtered ssh no-response
23/tcp filtered telnet no-response
53/tcp open domain syn-ack
80/tcp open http syn-ack
49152/tcp open unknown syn-ack
49153/tcp open unknown syn-ack
Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 1.63 seconds
Мониторинг сетевых соединений процессов
Интерфейс сокетов в целом является продолжением идеи «файлов», специально предназначенных для межпроцессного взаимодействия, некоторым развитием «файловой» природы простейших именованных и неименованных каналов.
Таким образом, сокеты сетевых семейств ip, ipv6 и пр. обладают «файловыми» свойствами точно так же, как и локальные сокеты unix. Например, каждый сетевой сокет идентифицируется при помощи файлового дескриптора в таблице открытых файлов процесса, что проиллюстрировано в листинге ниже при помощи lsof и ss.
Файловые дескрипторы сетевых сокетов
lumpy@ubuntu:~$ pgrep lftp
8715
lumpy@ubuntu:~$ lsof -t :5900
COMMAND PID USER FD TYPE DEVICE SIZE/OF NODE NAME
lftp 8715 lumpy cwd DIR 252,0 4096 20430868 /home/lumpy
lftp 8715 lumpy rtd DIR 252,0 4096 2 /
lftp 8715 lumpy txt REG 252,0 905324 3811570 /usr/bin/lftp
lftp 8715 lumpy 0u CHR 136,1 0t0 4 /dev/pts/1
lftp 8715 lumpy 1u CHR 136,1 0t0 4 /dev/pts/1
lftp 8715 lumpy 2u CHR 136,1 0t0 4 /dev/pts/1
lftp 8715 lumpy 3r DIR 252,0 4096 20430868 / home/lumpy
lftp 8715 lumpy 4u IPv4 16686880 0t0 TCP ubuntu.local:35561>mirror.yandex.ru:ftp (ESTAB..
lumpy@ubuntu:~$ sudo ss -p dport = :21
State Recv-Q Send-Q Local Address:Port Peer Address: Port
ESTAB 0 0 192.168.100.5:35561 213.180.204.183: ftp users:((«lftp»,8715,4^))
Более детально проследить за жизненным циклом сетевого сокета позволяет трассировка «сокетных» системных вызовов socket, connect, bind, listen, accept, send и recv.
В примере из листинга ниже показана трассировка «клиентского» сокета пользовательского агента curl, загружающего Web-pecypc http://www.gnu.org/graphlcs/ agnuheadterm-xterm.txt.
Системный вызов socket создает потоковый сокет семейства ip, которому назначается первый свободный файловый дескриптор FD=3, после чего системный вызов connect инициирует установку соединения этого сокета с портом 80 узла 208.118.235.148. После установки соединения системный вызов send отсылает Web-серверу команду W: [HTTP] протокола GET на получение запрашиваемого ресурса, а несколько системных вызовов recv получают запрошенный ресурс.
Сетевой клиент: системные вызовы socket, connect, send и recv
lumpy@ubunu:~$ straсe -fe traсe=network curl http://ww.gru.org/graphics/agnuheadterm-xterm.txt
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
setsockopt(3, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
connect(3, {sa_farrlly=AF_INET, sin_port=htons(80), sin_addr=inet_addr(«208.118.235.148»)},
16) = -1 EINPROGRESS (Operation now in progress)
getsod<cpt(3, SOL_SOCKET, S0_ERROR, [0], [4]) = 0
getpeername(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr( «208.138.235.148»)}, [16]) = 0 getsockname(3, (sa_family=AF_INET, sin_port=htons(51090), sin_addr=inet_addr(«192.168.100.4»)}, [16]) = 0 send(3, «GET /graphics/agnuheadterm-xtem»…, 192, MSG_NOSIGNAL) = 192
recv(3, «HTTP/1.1 200 OK\r\nDate: Wed, 06 3″…, 16384, 0) = 1400
recv(3, «m\342\226\204\33[48;5;242n\33[38;5;244n\342\226\204\33[4″…, 14770, 0) = 1400
recv(3, 5; 59m\342\226\200\33[38; 5;240n\342\226\204\33[48; 5; 24″…, 13370, 0) = 7000
recv(3, » \33[48;5;251n \33[48;5;231m 6370, 0) = 1400
recv(3, «8; 5; 242n\33[38; 5;237m\342\226\204\33[48; 5; 16m’…, 4970, 0) = 4970
Жизненный цикл «серверных» сокетов чуть более сложен и предполагает использование одного «слушающего» сокета для клиентских подключений и по одному «обслуживающему» сокету на каждого подключенное клиента.Жизненный цикл «серверных» сокетов чуть более сложен и предполагает использование одного «слушающего» сокета для клиентских подключений и по одному «обслуживающему» сокету на каждого подключенное клиента.
В примере из листинга ниже показана трассировка простейшего Web-сервера, реализованного модулем SinpleHTTPServer языка программирования W:[python]. Web-сервер запускается из «рабочего» каталога /usr/share/doc и предоставляет Web-доступ ко всем файлам этого каталога, используя «нестандартный» порт 8000.
Для начала при помощи socket создается потоковый сокет семейства ip, которому назначается первый свободный файловый дескриптор FD = 3. Этот сокет и будет выступать в роли «слушающего», т. е. принимающего клиентские соединения, поэтому ему «привязывается» адрес 0.0.0.0 и порт 8000 (куда и будут поступать клиентские соединения) при помощи системного вызова bind, а сам сокет переводится в слушающее состояние системным вызовом listen.
Все входящие клиентские соединения ставятся в очередь «слушающего» сокета и изымаются из нее системным вызовом accept, который создает для каждого клиентского соединения, собственный сокет (клонируя слушающий).. При поступлении клиентского соединения был создан новый «обслуживающий» сокет с файловым дескриптором FD = 4, используя который посредством recv была получена W:[HTTP] команда get на доступ к «корневому» ресурсу сервера, а с помощью нескольких системных вызовов send в ответ был направлен сформированный HTML-список файлов в каталоге /usr/share/doc.
Сетевой сервер: системные вызовы socket, bind, listen, accept, send и recv
lumpy@ubuntu:~$ cd /usr/share/doc
lumpy@ubuntu:/usr/share/doc$ strace —fe trace=network python -n SimpLeHTTPServer
socket(PF_INET, SOCK_STREAM, IPPROTO) = 3
setsockopt(3, SOL_SOCKET, 90_REUSEADDR, [1], 4) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(8800), sin_addr=inet_addr( «0.0.0.0»)}, 16) = 0
getsockname(3, {sa_family=AF_INET, sin_port=htons(8000), sin_addr=inet_addr(«0.0.0.0,’)}, [16]) = 0 getsockname(3, {sa_family=AF_INET, sin_port=htons(8000), sin_addr=inet_addr(«0.0.0.0,’)}, [16]) = 0
listen(3, 5) = 0
getsockname(3, {sa_family=AF_INET, sin_port=htons(8000), sin_addr=inet_addr(«0.0.0.0»)}, [16]) = 0
Serving HTTP on 0.0.0.0 port 8000 …
accept(3, {sa_family=AF_INET, sin_port=htons(5S094), sin_addr=inet_addr(«127.0.0.1»)}, [16]) = 4
recv(4 «GET / HTTP/1. 1\r\nUser-Agent: Wget»…, 8192, 0) = 111
localhost — — [03/Apr/2018 19:52:14] «GET / HTTP/1.1″ 200 —
send(4 ‘HTTP/1.0 200 CK\r\n», 17, 0) = 17
send(4, «Server: SimpleHTTP/0.6 Python/2.»…, 37, 0) = 37
send(4, «Date: Sun, 03 Apr 2016 16:52:14 «…, 37, 0) = 37
send(4, «Content-type: text/html; charset»…, 40, 0) = 40
send(4, «Content-length: 140946\r\n», 24, 0) = 24
send(4, «\r\n», 2, 0) = 2
send(4, «<!DOCTYPE html PUBLIC \»-/W3C/D)»…, 8192, 0) = 8192
send(4, «video-qxl/</a>\n<li><a href=\»xser»…, 1682, 0) = 1682
shutdown(4, 1 /* send */) = 0^C
lumpy@ubuntu:~$ wget http://ubuntu: 8000
—2018-04-03 19:52:14- http://ubuntu: 8000/
Распознаётся ubuntu (ubuntu).., 127.0.1.1
Подключение к ubuntu (ubuntu)|127.0.1.1|:8000… соединение установлено.
HTTP-запрос отправлен. Ожидание ответа… 200 OK
Длина: 140946 (138К) [text/html]
Сохранение в: «index.html.1»
100%[ =======================>] 140 946 -K/s за 0,003s
2018-04-03 19:52:14 (51,0 MB/s) — «index.htnl. 1» сохранён [140946/140946]