Что мы уже умеем и что теперь будет
До сих пор мы работали внутри одной машины. Мы создавали файлы, запускали процессы, управляли службами, читали журналы. Даже когда система обращалась к диску или запускала программу по расписанию, всё происходило локально. Теперь наступает момент, когда наш компьютер перестаёт быть изолированным ящиком.
Сетевой блок начинается не с команд, а с понятий. Нам нужно сначала разобраться, как компьютеры находят друг друга, как данные доходят от одной программы до другой и почему в этом процессе столько разных участников. Мы хотим понимать, что именно мы видим в выводе и что именно проверяем.
Мы начнём с адресов, маршрутов и портов. Затем посмотрим на протоколы TCP и UDP и на роли клиента и сервера. Всё это — слова, которые вы наверняка уже слышали. Задача урока — вдохнуть в них конкретный смысл и связать между собой.
Адрес в сети — не прописка, а билет на поезд
Когда два компьютера обмениваются данными по сети, каждому из них нужен адрес. В сетях TCP/IP, которые нас и интересуют, таким адресом служит IP-адрес. Для IPv4 он выглядит как четыре числа от 0 до 255, разделённые точками: например, 192.168.50.10.
Может показаться, что IP-адрес — это что-то вроде домашнего адреса, который намертво прикреплён к компьютеру. Но это не так. IP-адрес описывает не сам компьютер, а его подключение к конкретной сети в конкретный момент. Один и тот же ноутбук дома может иметь адрес 192.168.1.20, а в кафе — 10.0.0.45. Если сетевой интерфейс переподключить или перезапустить, адрес может смениться. Поэтому нельзя думать об IP как о постоянном идентификаторе машины. Адрес может назначаться автоматически или задаваться вручную и оставаться неизменным долгое время. Его возможное постоянство не делает его идентификатором самого устройства.
Если уж проводить аналогию с адресом дома, то представьте, что адрес нанесён не на дом, а на билет на поезд: он говорит, куда доставить данные сейчас, в этой поездке. Завтра билет может быть другим, хотя пассажир — тот же.
Префикс: где заканчивается сеть
Адрес сам по себе не говорит, где начинается наша сеть, а где уже чужая. Допустим, у нас есть адрес 192.168.50.10. Какая часть из четырёх чисел описывает сеть, а какая — конкретный узел внутри неё? Сам по себе адрес на этот вопрос не отвечает. Нужен второй элемент — префикс.
Запись с префиксом для нас — это просто способ компактно сказать, какая часть адреса общая для всех машин нашей сети, а какая часть может меняться. Для /24 это означает: первые три числа закреплены, последнее число — наше. Сеть — это 192.168.50.0, а внутри неё могут существовать адреса от 192.168.50.1 до 192.168.50.254. Адрес 192.168.50.0 зарезервирован как адрес самой сети, а 192.168.50.255 — как широковещательный. Поэтому конкретным машинам их не выдают.
Маска — то же самое, но другими словами
Рядом с префиксом вы можете встретить и другое представление той же идеи — маску подсети. Для /24 маска выглядит как 255.255.255.0. Если наложить эту маску на IP-адрес, станет видно, какая часть описывает сеть, а какая — узел. В маске единицы в двоичном виде там, где сеть, и нули там, где узел. Число 255 — это все восемь битов, заполненные единицами. Три таких числа подряд и ноль в конце — это и есть /24.
Не нужно заучивать таблицу соответствия всех префиксов и масок. Для наших уроков важен принцип: префикс и маска — это два способа записать одно и то же разграничение. /24 означает сеть из трёх фиксированных чисел, /16 — сеть из двух фиксированных чисел, а /8 — только первое число фиксировано. Чем меньше префикс, тем больше адресов может быть в сети. Чем больше префикс, тем меньше возможных узлов, но тем точнее мы описываем небольшую группу.
Конкретный пример из наших уроков будет таким: машина А имеет адрес 192.168.50.10/24, а машина Б — 192.168.50.20/24. Смотрим на первые три числа: у обеих они 192.168.50. Значит, они находятся в одной сети. Им не нужен посредник, чтобы обменяться данными, если они подключены к одному сегменту сети.
Маршрут по умолчанию
А что делать, если нужно доставить данные на адрес, который не лежит в нашей сети? Допустим, наша машина 192.168.50.10/24 хочет обратиться к машине с адресом 203.0.113.20 (условный адрес на схеме, не сервер для подключения). Первые три числа совсем другие. Значит, адрес вне нашей сети 192.168.50.0/24. Наша машина не знает, как доставить данные напрямую. Ей нужен выход — маршрут.
Обычно в сети есть устройство, которое знает, как передавать данные дальше, в другие сети. Дома это часто роутер, который соединяет домашнюю сеть с сетью провайдера. В настройках машины такой выход называется маршрутом по умолчанию. Его адрес — это адрес шлюза, то есть устройства, которому в этой схеме передаём пакеты за пределы своей сети.
Маршрут по умолчанию выбирается, когда нет более конкретного подходящего маршрута. В нашей простой схеме адреса своей сети доступны напрямую, а остальные — через шлюз. В более сложной конфигурации для отдельных сетей могут быть заданы собственные маршруты. Роль маршрутизатора может выполнять и обычный компьютер с настроенной пересылкой пакетов.
Локальный адрес 127.0.0.1
Есть один адрес, который занимает особое место. Это 127.0.0.1. Он всегда означает «эта же машина». Данные, отправленные на 127.0.0.1, не покидают компьютер. Для них используется внутренний маршрут через loopback; внешний шлюз и внешняя сеть не нужны. Операционная система обрабатывает такой трафик внутри себя.
Зачем это нужно? Очень полезно, когда мы хотим проверить, работает ли сетевая программа, не подключаясь к другой машине. Можно запустить на компьютере сервер и обращаться к нему по 127.0.0.1. С точки зрения программы, это полноценное сетевое соединение, хотя данные физически не выходят за пределы машины. Адрес 127.0.0.1 ещё называют loopback-адресом. В следующих уроках мы используем его для учебных задач, и важно с самого начала понимать: это не проверка связи с другой машиной, это проверка работы сетевого стека и программы на самой машине.
Клиент и сервер — это роли
Теперь перейдём от адресов к участникам обмена. Когда две программы общаются по сети, они делают это в разных ролях. Одна из них — сервер. Это программа, которая ждёт входящих подключений. Она запускается, занимает определённый порт и слушает. Клиент — это программа, которая инициирует соединение. Она знает адрес сервера и порт, на котором тот слушает, и стучится туда.
Слово «сервер» в Linux мы уже встречали в другом значении — как компьютер, который предоставляет ресурсы. Теперь добавилось второе значение: серверная программа. В обычной речи они смешиваются, но для понимания сетей их полезно различать. На одном компьютере может работать несколько серверных программ, каждая на своём порту. Компьютер, который мы называем сервером, чаще всего просто выполняет роль сервера для других машин, но сам по себе он не перестаёт быть компьютером.
Клиент и сервер — это именно роли, а не типы машин. Одна и та же программа может быть клиентом в одной ситуации и сервером в другой. Ваш браузер — клиент, когда обращается к веб-сайту. Но если на машине запустить SSH-сервер, эта же машина будет играть роль сервера для тех, кто к ней подключается.
Порты: как найти нужную программу
Когда данные приходят на IP-адрес, они достигают машины. Но на машине одновременно работает много программ, и все они используют сеть. Как понять, какой программе предназначены эти данные? Для этого и существуют порты.
Номер порта — это число от 0 до 65535; номер 0 зарезервирован и обычно не используется как порт сервиса. Порт вместе с IP-адресом и транспортным протоколом помогает определить адресата данных на машине. IP-адрес доставляет данные до машины, порт доставляет их до конкретной программы. Если вернуться к аналогии с домом: IP-адрес — это адрес дома, а порт — это квартира или даже конкретная дверь внутри дома. Данные попадают не просто в здание, а к определённому адресату внутри.
Как и аналогия с домашним адресом, эта картинка не должна уводить нас слишком далеко. IP-адрес не прибит к дому навсегда, он может меняться. А порт — это не физическая дверь, а число, которое операционная система связывает с конкретным сетевым соединением или слушающей программой. Но для понимания роли портов образ домов и дверей работает хорошо: адрес — куда идти, порт — к кому именно.
Некоторые порты закреплены за известными службами по договорённости. Например, веб-серверы обычно слушают порт 80 для HTTP и 443 для HTTPS. SSH по умолчанию использует порт 22. Эти номера не обязательны — программа может слушать и другой порт, — но общепринятые значения помогают клиентам не угадывать каждый раз, куда подключаться.
TCP и UDP: два способа доставки
Данные между клиентом и сервером могут передаваться разными способами. Два самых известных протокола — TCP и UDP. Оба работают поверх IP и используют порты, но ведут себя по-разному.
TCP — это протокол с установлением соединения и подтверждением доставки. Прежде чем передать данные, клиент и сервер обмениваются служебными сообщениями и договариваются о соединении. После этого данные передаются по порядку. Если часть данных потерялась, TCP замечает это и запрашивает повторную отправку. Поэтому TCP подходит для задач, где важна целостность: веб-страницы, файлы, SSH-подключения.
UDP — протокол без установления соединения и без гарантии доставки. Отправитель просто отправляет данные по адресу и порту. Сам UDP не подтверждает получение и не повторяет потерянные данные, хотя приложение может реализовать это самостоятельно. У него меньше собственных служебных механизмов, но это не означает, что любая передача по UDP обязательно быстрее TCP. UDP подходит для задач, где важнее скорость, чем идеальная полнота, например для потокового видео или онлайн-игр.
Важно не делать из этого вывод, что TCP автоматически гарантирует успех приложения. TCP гарантирует, что доставленные байты будут полными и в правильном порядке. Но он не гарантирует, что соединение вообще установится, что сервер ответит и что приложение на другом конце обработает данные так, как мы ожидаем. Если сервер выключен, TCP-соединение просто не установится. Если приложение написано с ошибкой, оно может отправить по TCP неверные данные, и они придут в целости. Протокол отвечает за доставку, а не за осмысленность.
Собираем картину вместе
Теперь у нас есть все элементы одной картины. Когда вы набираете в браузере адрес веб-сайта, браузер играет роль клиента. Он определяет IP-адрес сервера, а затем устанавливает TCP-соединение на порт 443, если сайт использует HTTPS поверх TCP; здесь рассматриваем именно этот вариант. На вашей машине у этого соединения тоже есть порт, но он выделяется автоматически из свободных номеров. При прямом соединении без преобразования адресов сервер видит ваш IP-адрес и этот временный порт, и по ним понимает, куда отправлять ответ.
Если сайт находится в вашей локальной сети, данные уходят напрямую. Если нет — они передаются шлюзу по маршруту по умолчанию. На каждом этапе IP-адреса доставляют пакеты между машинами, а порты — между программами. TCP заботится о том, чтобы данные пришли целиком и по порядку. Сам UDP не предоставляет таких механизмов доставки.
Это не значит, что мы теперь готовы лезть в настройки сети и менять маршруты. Мы готовы к следующему шагу — научиться смотреть на сеть. В следующих уроках мы будем выполнять команды, которые показывают адреса, проверяют достижимость, читают маршруты и диагностируют порты. Но каждая такая команда будет опираться на понятия из этого урока. Мы сможем понять, что означает адрес с префиксом, почему пакет уходит через шлюз и какого ответа ждать от TCP или UDP.
IP-адрес относится к сетевому подключению, а не постоянная характеристика компьютера. Префикс вида /24 показывает, какая часть адреса описывает сеть, а какая — узел. Для 192.168.50.10/24 сеть — это 192.168.50.0, а конкретным машинам принадлежат адреса от 192.168.50.1 до 192.168.50.254. Маска 255.255.255.0 — это та же идея в другой записи. Машины 192.168.50.10/24 и 192.168.50.20/24 находятся в одной сети и могут общаться напрямую. Данные для адресов вне своей сети передаются шлюзу по маршруту по умолчанию. Особый адрес 127.0.0.1 всегда означает «эта же машина», и данные на него не покидают компьютер.
В сетевом обмене программы играют роли клиента и сервера. Сервер слушает порт и ждёт подключений, клиент инициирует соединение. IP-адрес доставляет данные до машины, порт — до конкретной программы. TCP устанавливает соединение и гарантирует целостность доставки, UDP не устанавливает такое соединение и сам не подтверждает доставку. TCP не гарантирует, что соединение установится и что приложение сработает правильно, — он отвечает только за полную и упорядоченную доставку тех данных, которые удалось передать.
В теории мы разобрали, как адреса, префиксы, маршруты и порты складываются в одну картину. Теперь потренируемся читать конкретные наблюдения и рассуждать о том, куда уйдёт пакет и что именно показывает проверка. Задания идут от выбора маршрута к разбору отдельных записей и к пределам локальной проверки.
Куда уйдёт пакет
У машины есть адрес с префиксом и таблица маршрутов. Нужно решить, какой маршрут сработает для конкретного адреса назначения.
На машине с адресом 192.168.50.10/24 таблица маршрутов выглядит так:
default via 192.168.50.1 dev eth0
192.168.50.0/24 dev eth0 scope link src 192.168.50.10
Машина отправляет пакет на адрес 192.168.50.20. Куда уйдёт пакет?
Что означает каждая запись
Перед вами несколько строк из разных команд просмотра сети. Нужно соотнести каждую запись с её смыслом.
Сопоставьте каждое наблюдение из вывода сетевых команд с его смыслом. Каждое наблюдение используется один раз.
Наблюдения:
- default via 192.168.50.1 dev eth0
- eth0 UP 192.168.50.10/24
- LISTEN 127.0.0.1:631 (TCP)
- 192.168.50.0/24 dev eth0 scope link
- 0.0.0.0:68 (UDP)
Что показывает loopback
Ученик запустил пару проверок на своей машине и сделал вывод о всей сети. Нужно объяснить, что подтверждает такая проверка, а чего она не подтверждает.
На новой учебной машине мы запустили две команды и получили такой вывод:
$ ping -c 4 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.045 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.038 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.041 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.039 ms
--- 127.0.0.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss
$ ss -ltn
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 127.0.0.1:8080 0.0.0.0:*
Ученик смотрит на этот вывод и говорит: «Значит, сеть настроена правильно и связь с другими машинами точно работает».
Объясните своими словами, что такое loopback-адрес и что именно показывает эта проверка, а чего она не показывает. Ответьте связным текстом, примерно 4–6 предложений.