Модуль 05 — TCP, UDP и порты

Как данные попадают не просто на сервер, а в нужную программу

Прогресс курса Модуль 5 из 9

Что вы освоите в этом модуле

01

Порты и сокеты

IP-адрес доставляет пакет до машины, но на ней работают десятки программ. Какой из них отдать данные, решает порт — число от 0 до 65535 в заголовке TCP или UDP. Пара «адрес и порт» называется сокетом, а соединение однозначно задаётся четвёркой: адрес и порт отправителя, адрес и порт получателя.

192.168.116.10:54159  ──────────▶  192.168.116.34:22
   клиент, временный порт               сервер SSH, известный порт
ДиапазонНазваниеКто использует
0–1023Системные (well-known)Стандартные службы; открыть их для приёма может только root
1024–49151ЗарегистрированныеПриложения: PostgreSQL 5432, альтернативный HTTP 8080
49152–65535 (в Linux с 32768)Временные (эфемерные)Клиентская сторона: система выдаёт порт на время соединения
$ grep -E '^(ssh|smtp|domain|http|ntp|https|postgresql)\b' /etc/services
ssh		22/tcp				# SSH Remote Login Protocol
smtp		25/tcp		mail
domain		53/tcp				# Domain Name Server
domain		53/udp
http		80/tcp		www		# WorldWideWeb HTTP
ntp		123/udp				# Network Time Protocol
https		443/tcp				# http protocol over TLS/SSL
https		443/udp				# HTTP/3
postgresql	5432/tcp	postgres	# PostgreSQL Database

Номер порта — договорённость, а не закон: SSH можно запустить на 2222, веб-сервер — на 8080. Клиент в этом случае должен знать нестандартный порт.

02

UDP и TCP

UDPTCP
СоединениеНет: каждая датаграмма сама по себеУстанавливается перед обменом и закрывается после
ДоставкаНе гарантирована: потеря молчаГарантирована: подтверждения и повторная отправка
ПорядокНе гарантированВосстанавливается по номерам
Заголовок8 байт20–60 байт
Скорость реакцииСразуПосле рукопожатия, с регулировкой скорости
ГдеDNS, NTP, DHCP, голос и видео, игры, QUIC (HTTP/3)HTTP/1.1 и HTTP/2, SSH, почта, базы данных

UDP выбирают, когда опоздавшие данные бесполезны (кадр видеозвонка), когда запрос-ответ укладывается в один пакет (DNS) или когда надёжность приложение обеспечивает само (QUIC). TCP — когда важно получить всё и по порядку: файл, страницу, транзакцию.

03

Тройное рукопожатие

TCP-соединение начинается с обмена тремя сегментами. Захватим его с помощью tcpdump при подключении к SSH на этой же машине:

$ sudo tcpdump -i lo -nn 'tcp port 22'
IP 127.0.0.1.58100 > 127.0.0.1.22: Flags [S], seq 1056504289, win 65495, length 0
IP 127.0.0.1.22 > 127.0.0.1.58100: Flags [S.], seq 2580490338, ack 1056504290, win 65483, length 0
IP 127.0.0.1.58100 > 127.0.0.1.22: Flags [.], ack 1, win 512, length 0
IP 127.0.0.1.58100 > 127.0.0.1.22: Flags [F.], seq 1, ack 1, win 512, length 0
IP 127.0.0.1.22 > 127.0.0.1.58100: Flags [.], ack 2, win 512, length 0
IP 127.0.0.1.22 > 127.0.0.1.58100: Flags [P.], seq 1:42, ack 2, win 512, length 41: SSH: SSH-2.0-OpenSSH_10.0p2 Debian-7+deb13u4

Первые три строки — рукопожатие. Клиент здесь только проверял порт и сразу начал закрывать соединение ([F.]), а сервер подтвердил это и всё равно успел отправить приветствие с версией SSH — по одному соединению TCP данные идут в обе стороны независимо.

Флаг в tcpdumpНазваниеСмысл
[S]SYNКлиент: «хочу соединиться, мой начальный номер такой-то»
[S.]SYN + ACKСервер: «согласен, подтверждаю твой номер, мой такой-то»
[.]ACKКлиент подтверждает — соединение установлено
[P.]PUSH + ACKДанные: сервер SSH представился версией
[F.]FIN«Я закончил передавать» — начало закрытия
[R]RSTСброс: на этом порту никто не слушает или соединение оборвано

Номера seq и ack — счётчики байтов: так TCP понимает, что дошло, а что нужно отправить повторно. win — окно: сколько данных получатель готов принять, не подтверждая. В Wireshark тот же обмен виден с расшифровкой каждого поля — откройте файл, записанный tcpdump -w capture.pcap.

По рукопожатию быстро диагностируется проблема: ответ [R] на [S] — порт закрыт, служба не запущена; нет ответа вовсе — пакеты отбрасывает межсетевой экран или узел недоступен; рукопожатие прошло, а данные не идут — проблема в приложении.
04

Состояния соединений: ss

$ ss -tan
State     Recv-Q Send-Q  Local Address:Port    Peer Address:Port
LISTEN    0      200         127.0.0.1:5432         0.0.0.0:*
LISTEN    0      128           0.0.0.0:22           0.0.0.0:*
ESTAB     0      80     192.168.116.34:22    192.168.116.10:54159
TIME-WAIT 0      0      192.168.116.34:33744 146.75.122.132:80
TIME-WAIT 0      0      192.168.116.34:33756 146.75.122.132:80
СостояниеЧто значит
LISTENСлужба ждёт подключений на порту
SYN-SENTКлиент отправил SYN, ждёт ответа. Много таких — назначение недоступно или фильтруется
ESTABСоединение установлено, идёт обмен
TIME-WAITСоединение закрыто, сторона, закрывшая первой, ещё ~60 с помнит его, чтобы поздние пакеты не попали в новое соединение. Это нормально
CLOSE-WAITДругая сторона закрыла, а наша программа — ещё нет. Копится — ошибка в приложении

Recv-Q и Send-Q у установленного соединения — байты, ещё не прочитанные программой и ещё не подтверждённые другой стороной. Постоянно растущий Send-Q говорит, что получатель не успевает или сеть теряет пакеты. Полезные фильтры: ss -tn state established, ss -tn dst 192.168.116.10, ss -tlnp — кто слушает (модуль 08 курса Linux).

05

nc: швейцарский нож для портов

nc (netcat) открывает TCP- или UDP-соединение и передаёт по нему стандартный ввод. Это лучший способ проверить, доступен ли порт, без установки клиента нужной службы. В Debian ставьте вариант из пакета netcat-openbsd — примеры ниже для него.

$ nc -zv -w2 nevabit.ru 443 80 22           # -z: только проверить, -v: подробно
Connection to nevabit.ru (188.120.235.218) 443 port [tcp/https] succeeded!
Connection to nevabit.ru (188.120.235.218) 80 port [tcp/http] succeeded!
nc: connect to nevabit.ru (188.120.235.218) port 22 (tcp) timed out: Operation now in progress
$ nc -zv 127.0.0.1 23
nc: connect to 127.0.0.1 port 23 (tcp) failed: Connection refused

Разница между «refused» и «timed out» важна: отказ пришёл от узла — он доступен, но порт закрыт (ответ RST); тайм-аут — ответа нет совсем, пакеты отбрасываются по дороге или на узле межсетевым экраном. Порт 22 на сайте курса закрыт именно экраном.

Два терминала — и у вас простейший сервер и клиент:

# терминал 1: слушать порт 5001
$ nc -l 127.0.0.1 5001
данные от клиента

# терминал 2: подключиться и отправить
$ echo "данные от клиента" | nc -N 127.0.0.1 5001

Протокол HTTP можно «набрать руками» — это текст:

$ printf 'GET / HTTP/1.1\r\nHost: nevabit.ru\r\nConnection: close\r\n\r\n' | nc -w3 nevabit.ru 80
HTTP/1.1 301 Moved Permanently
Server: nginx
Content-Type: text/html
Content-Length: 162
Connection: close
С UDP проверка «открыт ли порт» ненадёжна: echo test | nc -u -w1 127.0.0.1 5999 завершится с кодом 0, хотя порт никто не слушает. Подтверждений в UDP нет, поэтому доступность UDP-службы проверяют её собственным клиентом: DNS — dig, NTP — ntpdate -q.
06

tcpdump

tcpdump показывает пакеты, проходящие через интерфейс. Нужен sudo. Главное — фильтр: без него на загруженном сервере вывод не прочитать.

$ sudo tcpdump -i ens18 -nn -c 4 'udp port 53'      # 4 пакета DNS
IP 192.168.116.34.38947 > 192.168.116.1.53: 18255+ AAAA? nevabit.ru. (28)
IP 192.168.116.1.53 > 192.168.116.34.38947: 18255 0/1/0 (80)
IP 192.168.116.34.60184 > 192.168.116.1.53: 16902+ AAAA? nevabit.ru.localdomain. (40)
IP 192.168.116.1.53 > 192.168.116.34.60184: 16902 NXDomain 0/1/0 (115)
Опция или фильтрЗначение
-i ens18, -i anyИнтерфейс, все интерфейсы
-nnНе переводить адреса и порты в имена — быстрее и точнее
-c 10Остановиться после 10 пакетов
-w file.pcapЗаписать в файл для Wireshark
host 10.0.0.5, port 443, tcp, icmpФильтры, объединяются and, or, not
'tcp[tcpflags] & tcp-syn != 0'Только пакеты с флагом SYN — попытки соединений

Захват выше — наглядный пример UDP: запрос и ответ по одному пакету, без рукопожатия. Видно и то, как система, не найдя AAAA-запись, пробует дописать к имени домен поиска localdomain.

Захват трафика показывает содержимое незашифрованных протоколов: пароли HTTP, FTP, telnet. Перехватывать чужой трафик без разрешения владельца сети незаконно; в курсе захват — только на своей машине и в своей лаборатории.

Ключевые выводы модуля

Запомните главное

  • Порт выбирает программу на узле; соединение — четвёрка адресов и портов
  • UDP — быстро и без гарантий, TCP — соединение, подтверждения, порядок
  • Рукопожатие TCP: SYN → SYN-ACK → ACK; RST — порт закрыт, тишина — фильтр
  • ss -tan: LISTEN, ESTAB, TIME-WAIT (норма), CLOSE-WAIT (ошибка приложения)
  • nc -zv — проверка порта: «refused» и «timed out» означают разное
  • tcpdump -nn с фильтром — что на самом деле идёт по сети
Практические задания — на учебном портале. Задания, критерии оценивания, сдача работ и оценки преподавателя — в курсе на portal.nevabit.ru. Учётную запись выдаёт преподаватель.
Модуль 04: Маршрутизация Все модули Модуль 06: DNS и DHCP