Урок 4 — Порты, TCP и UDP
У сервера один IP — но на нём работает 5 разных программ: web-сервер, SSH, БД, мониторинг. Как пакеты не путаются и попадают к нужной программе? Ответ: порты. А TCP и UDP — это два способа, которыми пакеты доставляются. Знать обязательно.
- Зачем нужны порты
- Диапазон портов: well-known, registered, ephemeral
- Сокет — IP + порт
- TCP — доставка с гарантией
- Three-way handshake
- Состояния TCP-соединения
- UDP — быстро и без гарантий
- Сравнение, когда что использовать
- Что с этим делает DevOps
- Команды и упражнения
- Чек-лист «понимаю это»
- Плейбук: «сервис не отвечает»
- Задачи с ответами
Данные летят пакетами (урок 1); IP-адрес доставляет пакет на нужный компьютер, а маска
решает, «сосед или через шлюз» (уроки 2–3). Сегодня — последний недостающий кусочек адресации:
как пакет находит нужную программу внутри компьютера. После этого урока ты сможешь
прочитать адрес вида 192.168.1.10:443 целиком.
1. Зачем нужны порты
IP-адрес говорит, на какой компьютер доставить пакет. Но на одном компьютере одновременно работают много программ — браузер, мессенджер, web-сервер, SSH. Как операционная система решает, какой из них отдать пакет?
Ответ: каждая программа «садится» на свой порт — это число от 0 до 65535. IP плюс порт — уникальный адрес конкретной программы.
Порт = номер квартиры в большом доме
Дом (IP) на улице — один. Но в нём 100 квартир. Курьер с пиццей знает не только адрес дома, но и номер квартиры. Если бы номера квартир не было — пицца бы досталась первому встречному.
Так же ОС: получила пакет на 203.0.113.10:443 — передала именно процессу, который слушает 443.
2. Диапазон портов
Портов 65 536 штук (от 0 до 65535). Они официально разделены на три группы:
| Диапазон | Название | Кто использует |
|---|---|---|
| 0 — 1023 | Well-known (общеизвестные) | Системные службы. На Linux/macOS для биндинга нужны root-права |
| 1024 — 49151 | Registered (зарегистрированные) | Конкретные приложения, выделено IANA. Например, PostgreSQL 5432 |
| 49152 — 65535 | Dynamic / ephemeral | Временные порты, которые ОС сама раздаёт клиентам |
Порты, которые нужно знать наизусть
| Порт | Протокол / служба | Описание |
|---|---|---|
| 20, 21 | FTP | Передача файлов (устаревший) |
| 22 | SSH | Удалённое управление сервером |
| 23 | Telnet | Старый удалённый шелл, без шифрования. Не использовать. |
| 25, 587, 465 | SMTP | Отправка почты |
| 53 | DNS | Резолвинг имён — урок 5 |
| 80 | HTTP | Незашифрованный веб |
| 443 | HTTPS | Зашифрованный веб (TLS) |
| 3306 | MySQL | База данных |
| 5432 | PostgreSQL | База данных |
| 6379 | Redis | Кэш / БД в памяти |
| 8080, 3000, 5000 | HTTP-приложения | Любимые порты разработчиков для локальных запусков |
| 9090, 9100 | Prometheus / node_exporter | Мониторинг |
Видишь в логе «connection refused on 5432» — сразу думаешь «постгрес недоступен», а не лезешь искать что такое 5432. Это экономит часы.
3. Сокет — IP + порт
Сокет (socket) — это пара «IP-адрес + порт». То есть конкретная точка общения. 203.0.113.10:443 — это сокет.
Чтобы соединение установилось, нужны два сокета:
# Клиентский сокет (выдан ОС динамически из ephemeral)
192.168.1.42:54321
# Серверный сокет (где живёт программа)
203.0.113.10:443
# Пара = уникальное соединение
(192.168.1.42:54321) ↔ (203.0.113.10:443)
Каждое соединение — это уникальная четвёрка: IP1+порт1+IP2+порт2. Если ты одновременно открыл 5 вкладок одного и того же сайта, у тебя 5 разных клиентских портов, и сервер видит 5 разных соединений.
4. TCP — доставка с гарантией
В уроке 1 мы говорили: данные дробятся на пакеты. Но «дробятся» — это слишком просто. Кто гарантирует, что пакеты дойдут? В правильном порядке? Без потерь? Без дубликатов?
За это отвечает TCP (Transmission Control Protocol). Это «надёжная» доставка. TCP делает три ключевые вещи:
📦 Гарантия доставки
Если пакет потерялся — TCP его переотправит. Если не дошёл ответ — повторит. Программа просто не знает о потерях.
🔢 Сохранение порядка
Каждый пакет нумеруется. Приёмник собирает их в правильной последовательности, даже если пришли вразнобой.
⚖️ Контроль перегрузки
TCP «прощупывает» канал: начинает медленно, разгоняется. Если потери — снижает скорость. Уважает другие соединения.
🔐 Установление соединения
Прежде чем слать данные, стороны «здороваются» — three-way handshake. Об этом ниже.
5. Three-way handshake
Прежде чем обмениваться данными, клиент и сервер выполняют 3-шаговое «рукопожатие». Запомни эти три шага — это любимый вопрос на собеседовании.
SYN = synchronize («синхронизировать»), ACK = acknowledge («подтверждаю»). Это специальные флаги в TCP-заголовке пакета.
Зачем такая сложность? Чтобы:
- Обе стороны точно знали, что другая жива и готова
- Согласовать «начальные номера» пакетов — для последующей проверки порядка
- Защититься от подделок (random sequence number мешает атакам)
Закрытие соединения тоже не «бац, и нет». Там 4 шага: FIN → ACK → FIN → ACK. Не нужно сейчас зубрить — главное помнить «открытие и закрытие — это процедуры, а не моментальные действия».
6. Состояния TCP-соединения
В любой момент времени соединение находится в одном из «состояний». Их можно увидеть командой ss -tan или старой netstat. Главные:
| Состояние | Что значит | DevOps-интерпретация |
|---|---|---|
LISTEN | Сервер слушает порт | Норма. Так должен выглядеть твой web-сервер на 443 |
ESTABLISHED | Соединение активно | Норма. Идёт обмен данными |
SYN_SENT | Клиент отправил SYN, ждёт SYN-ACK | Если застряло — сервер не отвечает (упал, фаервол) |
SYN_RECV | Сервер получил SYN, отправил SYN-ACK | Много таких = возможна SYN-flood атака |
TIME_WAIT | Соединение закрыто, ждём 60 сек на «застрявшие» пакеты | Много TIME_WAIT под нагрузкой — типичная боль. Решается tuning'ом ядра |
CLOSE_WAIT | Удалённая сторона закрыла, мы — нет | Растёт = баг в приложении (не закрывает сокеты). Серьёзный сигнал |
Если ты видишь сотни/тысячи CLOSE_WAIT у приложения — это утечка сокетов. Программа не закрывает соединения после получения FIN от собеседника. Это приводит к исчерпанию файловых дескрипторов и падению. Чинят в коде, не в инфраструктуре.
7. UDP — быстро и без гарантий
UDP (User Datagram Protocol) — противоположность TCP. Минимум формальностей:
- Никакого handshake — отправил и забыл
- Никаких подтверждений
- Никакого порядка
- Никаких retry
- Никакого контроля перегрузки
Звучит «плохо», но в нужных задачах — это огромный плюс. Какие задачи?
- DNS-запросы. Короткие, один пакет туда — один обратно. TCP здесь — overhead.
- VoIP, видеозвонки. Лучше потерять кадр и идти дальше, чем «застрять» в ожидании retry.
- Стриминг видео. То же.
- Игры. Состояние мира обновляется 60 раз в секунду — потерянный кадр заменится следующим.
- Метрики мониторинга. Если один datapoint потерялся — не страшно, следующий через секунду.
- QUIC и HTTP/3. Они работают поверх UDP, реализуя надёжность на более высоком уровне.
TCP = заказная посылка с уведомлением. UDP = открытка на «авось».
Заказное письмо с уведомлением — дойдёт, и ты узнаешь, что дошло. Но медленнее и дороже.
Открытку бросил в почтовый ящик — и забыл. Может дойдёт, может нет, ответа не будет. Зато бесплатно и сразу. Для «привет, поздравляю» — норм. Для «вышли мне 100 000 рублей» — категорически нет.
8. Сравнение — когда что использовать
| TCP | UDP | |
|---|---|---|
| Установка соединения | 3-way handshake | Нет — сразу слать |
| Гарантия доставки | Да | Нет |
| Порядок пакетов | Сохраняется | Не гарантируется |
| Скорость / latency | Выше overhead, выше задержка | Минимальный overhead |
| Контроль перегрузки | Есть | Нет (приложение разбирается само) |
| Заголовок пакета | 20 байт минимум | 8 байт |
| Применения | HTTP/HTTPS, SSH, БД, файлы, почта | DNS, VoIP, видео, игры, метрики, QUIC |
Правило: если ты сомневаешься, какой использовать — выбирай TCP. UDP — только когда понимаешь, зачем тебе именно он.
9. Что с этим делает DevOps
- Firewall и Security Groups. Все правила прописываются как «протокол + порт + источник/назначение». Например, «разрешить TCP 443 откуда угодно». Без понимания TCP/UDP/port — не настроишь.
- Health checks. Load balancer пингует upstream по конкретному порту. Если приложение слушает 8080 — health check тоже на 8080.
- Контейнеры. При запуске Docker'а ты пишешь
-p 8080:80— это маппинг порта хоста на порт контейнера. Без понимания «порт = программа» — это магия. - Service в Kubernetes. У сервиса есть
portиtargetPort— те же самые концепции, обёрнутые в K8s. - Диагностика. «Сервис недоступен». Первый шаг — проверить, что порт открыт и приложение слушает:
ss -tlnp | grep 443. Без этого знания — гадание. - Безопасность. Открытые лишние порты — это поверхность атаки. CKS и AWS Security Specialty проверяют это знание.
10. Команды и упражнения
Что слушает на твоём хосте
# Linux — современный инструмент
ss -tlnp # TCP + LISTEN + numeric + processes
ss -ulnp # UDP + LISTEN + numeric + processes
ss -tan # все TCP-соединения и их состояния
# Старый netstat (всё ещё работает)
netstat -tlnp
netstat -tan | grep ESTABLISHED
# Узнать, какой процесс слушает порт 443
sudo lsof -i :443
sudo ss -tlnp 'sport = :443'
Проверить, открыт ли порт удалённо
# Самый быстрый способ — netcat
nc -zv example.com 443 # -z = только сканировать, -v = вербозно
# Через nmap (если установлен)
nmap -p 22,80,443 example.com
# Через curl — если HTTP-порт
curl -v telnet://example.com:22
Сделать запрос вручную (без браузера)
# Откроем TCP-соединение и пошлём HTTP «руками»
nc example.com 80
GET / HTTP/1.1
Host: example.com
# После двух Enter сервер ответит. Это и есть «голый» HTTP
Посмотреть трёхэтапное рукопожатие в живую
# tcpdump — слушает пакеты на сетевом интерфейсе
# Запускай в одной вкладке:
sudo tcpdump -i any -nn port 80 and host example.com
# Во второй вкладке — сделай запрос:
curl http://example.com
# Увидишь SYN, SYN-ACK, ACK — в реальности
11. Чек-лист «понимаю это»
- ☐ Понимаю, зачем нужны порты (без объяснения через «номер квартиры»)
- ☐ Знаю порты: 22 (SSH), 53 (DNS), 80 (HTTP), 443 (HTTPS), 5432 (PostgreSQL)
- ☐ Объясню, что такое сокет
- ☐ Помню три шага TCP handshake: SYN → SYN-ACK → ACK
- ☐ Различаю TCP-состояния: LISTEN, ESTABLISHED, TIME_WAIT, CLOSE_WAIT
- ☐ Знаю, почему DNS использует UDP, а HTTPS — TCP
- ☐ Запустил
ss -tlnpи понял вывод - ☐ Запустил
nc -zvи проверил какой-нибудь порт
12. Плейбук: «сервис не отвечает» — первый рабочий алгоритм
Это твой первый настоящий плейбук диагностики — алгоритм, который инженеры гоняют по десять раз на дню. Ситуация: приложение должно работать на сервере на порту 8080, но клиент говорит «не открывается». Действуй по шагам, не перескакивай:
ss -tlnp | grep 8080. Есть строка со state
LISTEN — слушает, иди дальше. Нет строки — программа не запущена или упала:
смотри её логи, это не сетевая проблема.0.0.0.0:8080 — слушает всех, хорошо.
127.0.0.1:8080 — слушает только себя: снаружи никто не подключится,
хотя «у меня локально работает»! Классика — чинится конфигом приложения (bind 0.0.0.0).nc -zv адрес-сервера 8080 (или
Test-NetConnection адрес -Port 8080 в PowerShell). succeeded — сеть в
порядке, проблема выше (в самом приложении). refused — до сервера дошли, но порт
закрыт (см. шаг 1–2). timeout — пакеты не доходят вовсе: дальше.ufw status /
iptables -L), в облаке (Security Group!) или по пути. Проверь и базовую связность:
ping адрес-сервера — если и пинг не идёт, проблема ещё ниже (IP, маршруты — урок 8).13. Задачи — реши сам (ответы спрятаны)
Задача 1. В браузере открыт сайт. Какой порт у сервера? А какой у твоего браузера?
У сервера — 443 (HTTPS, well-known). У браузера — случайный эфемерный порт (обычно 49152–65535), выданный ОС на время соединения. Поэтому сервер всегда «известно где», а клиентов на одном компьютере может быть сколько угодно.
Задача 2. ss -tlnp показывает: 127.0.0.1:5432 LISTEN postgres. Коллега с соседнего сервера не может подключиться к базе. Почему?
PostgreSQL слушает только loopback (127.0.0.1) — доступен исключительно с
этой же машины. Чтобы пускать снаружи, он должен слушать 0.0.0.0 (или конкретный внешний адрес) —
параметр listen_addresses в конфиге. И не забыть про файрвол.
Задача 3. Почему DNS-запрос едет по UDP, а загрузка сайта — по TCP?
DNS-запрос — крошечный (один пакет туда, один обратно): гарантии TCP не нужны, а его handshake утроил бы время. Потерялся ответ — клиент просто переспросит. Сайт же — тысячи пакетов, где важен порядок и полнота: без TCP страница приехала бы «дырявой».
Задача 4. После перезапуска сервиса ты видишь кучу соединений в TIME_WAIT. Это авария?
Нет, это норма: TIME_WAIT — «вежливая пауза» после закрытия соединения
(ОС ждёт, чтобы опоздавшие пакеты старого соединения не попали в новое). Через минуту-две они
рассосутся сами. А вот сотни CLOSE_WAIT — плохой знак: приложение не закрывает
соединения (утечка).
Задача 5. Можно ли запустить два веб-сервера на одном компьютере?
Да — на разных портах: один на 80, второй на 8080. Один порт может занимать
только одна программа. Попытка второй сесть на занятый порт — ошибка
Address already in use (увидишь её ещё много раз!).
Задача 6. Видеозвонок подтормаживает, и часть кадров «рассыпается», но звонок не рвётся. Какой транспорт использует приложение и почему это разумно?
UDP. Для живого видео перепосылка потерянного кадра бессмысленна — он уже устарел; лучше показать следующий. TCP бы «застревал» на каждой потере, и звонок бы дёргался ещё сильнее.
ss -tan расскажут, что происходит с твоими соединениями.
Теперь ты знаешь полный адрес: IP + порт. Но постой — ты же никогда не набираешь
142.250.74.14:443. Ты набираешь google.com. Кто и как превращает
удобное имя в IP-адрес? Это работа DNS — «телефонной книги интернета», одной из самых
недооценённых и самых ломающихся систем. Следующий урок — про неё.