Основы сети: минимальный ликбез перед Linux-командами
Это не курс по сетям. Полноценные сети — это отдельная большая тема: модели OSI/TCP-IP, маршрутизация, NAT, DNS, TLS, балансировка, сетевые правила доступа, BGP, overlay-сети, Kubernetes networking и много других деталей. По-хорошему этому нужно посвящать отдельный большой курс.
Но дальше в Linux Advanced мы будем смотреть на ip addr, ip route, ss, curl, traceroute, SSH и сетевую диагностику. Без минимальной базы эти команды выглядят как набор случайных строк. Поэтому здесь только самое необходимое: что такое IP-адрес, порт, маршрут, DNS, localhost и как запрос примерно проходит от команды curl до процесса на сервере.
С чего вообще начинается сеть
Компьютеры редко работают совсем сами по себе. Браузер открывает сайт, телефон получает сообщения, сервер скачивает пакет, приложение обращается к базе, kubectl ходит в Kubernetes API. Во всех этих случаях одна программа хочет передать данные другой программе и получить ответ.
Самая простая модель такая:
клиент -> запрос -> сервер
клиент <- ответ <- сервер
Клиент — это тот, кто начинает разговор. Сервер — тот, кто ждёт запросы и отвечает на них.
Например:
| Клиент | Сервер | Что происходит |
|---|---|---|
| Браузер | сайт | браузер просит HTML-страницу |
apt |
репозиторий пакетов | сервер отдаёт список пакетов или .deb-файл |
docker pull |
registry | registry отдаёт слои образа |
kubectl |
Kubernetes API | API принимает команды и возвращает состояние кластера |
curl |
HTTP-сервер | сервер возвращает HTTP-ответ |
curl — это просто программа, которая умеет отправлять сетевые запросы из терминала. Чаще всего её используют для HTTP и HTTPS: проверить сайт, API, healthcheck, заголовки ответа, код 200/404/500, время ответа.
То есть curl не является "магической сетевой командой". Это маленький клиент. Он делает примерно то же, что браузер, но без красивого интерфейса: отправляет запрос и печатает ответ в терминал.
Браузер показывает пользовательское представление сайта: отрисованный HTML, стили, кнопки и layout. curl показывает инженерное представление того же ответа: тело, заголовки, статус-код, время запроса. Поэтому в лабораторных можно открыть Web Preview, чтобы увидеть страницу глазами пользователя, но в реальной диагностике часто быстрее начать с curl: он работает прямо в SSH-сессии, легко сохраняется в файл и хорошо подходит для автоматических проверок.
Чтобы отправить запрос, нужны адрес и правила
Перед тем как клиент сможет что-то спросить у сервера, он должен понять несколько вещей:
- Куда идти: какой IP-адрес у сервера.
- В какой сервис попасть: какой порт слушает нужная программа.
- Как туда добраться: через какой сетевой интерфейс и gateway отправить пакет.
- На каком "языке" разговаривать: HTTP, HTTPS, SSH, DNS, PostgreSQL protocol и так далее.
Можно думать так:
IP -> на какую машину
порт -> в какую программу на этой машине
протокол -> как именно общаться
Если ты открываешь https://example.com/api,
там уже спрятано несколько решений:
example.com— имя сервера, его надо превратить в IP через DNS;https— протокол HTTPS;- порт явно не указан, значит по умолчанию будет
443; /api— путь, который клиент попросит у HTTP-сервера.
Если написать http://localhost:8080/health,
то смысл другой:
localhost— эта же машина;http— обычный HTTP без TLS;8080— конкретный порт;/health— путь проверки здоровья приложения.
IP, порт и MAC: разные адреса на разных уровнях
В сети одновременно используются разные адреса. Для начала важно не смешивать три вещи:
| Что | Как думать | Пример |
|---|---|---|
| IP-адрес | до какой машины или узла надо добраться | 93.184.216.34 |
| порт | в какую программу на этой машине попасть | 443 |
| MAC-адрес | какому соседнему устройству в этой локальной сети отдать данные сейчас | 52:54:00:12:34:56 |
IP-адрес нужен для пути до конечного узла. Порт нужен уже на конечной машине, чтобы попасть в правильный процесс: nginx, sshd, PostgreSQL и так далее.
MAC-адрес нужен для ближайшего шага внутри текущей локальной сети: от ноутбука до домашнего роутера, от VM до виртуального роутера, от одного маршрутизатора до следующего. Твоя машина не отправляет данные "сразу в интернет". Если сервер далеко, она сначала отдаёт данные ближайшему роутеру, а для этого ей нужен MAC-адрес этого роутера.
Упрощённо:
HTTP-запрос -> что попросили у приложения
порт -> в какую программу попасть
IP -> к какому конечному адресу идти
MAC -> кому отдать данные на этом ближайшем шаге
Почему не хватает одного IP? Во-первых, частные IP-адреса повторяются в разных сетях. Например, 192.168.1.10 может быть у тебя дома, в офисе и внутри виртуальной лаборатории. Это разные машины в разных локальных сетях. Внутри одной локальной сети IP тоже должен быть уникальным; если два устройства получили один IP, это уже конфликт.
Во-вторых, даже когда IP назначения известен, устройству всё равно нужно понять, кому физически отдать данные прямо сейчас: соседнему компьютеру или ближайшему роутеру.
Когда пакет идёт через маршрутизаторы, IP-адрес назначения обычно остаётся адресом конечного сервера. А MAC-адрес назначения меняется на каждом участке: сначала MAC ближайшего роутера, потом MAC следующего роутера, потом MAC сервера. IP отвечает за путь "в целом", а MAC — за один ближайший шаг.
Запрос и ответ на примере HTTP
В вебе чаще всего используется HTTP. В HTTP клиент отправляет запрос, а сервер возвращает ответ.
У запроса есть метод и путь, например GET /api.
GET означает "получить данные". Путь /api говорит серверу, какую часть приложения попросили.
Кроме метода и пути, в HTTP-запросе есть заголовки. Они передают служебную информацию: какое имя сайта запросил клиент, какой клиент отправил запрос, какие форматы ответа он принимает, есть ли cookie или авторизация.
Упрощённый запрос выглядит так:
GET /api HTTP/1.1
Host: example.com
User-Agent: curl/8.5.0
Accept: */*
Host — один из самых важных заголовков. Он отвечает на вопрос "какой сайт хотел открыть клиент?". Это не всегда то же самое, что IP-адрес подключения. На одном IP и порту могут жить несколько сайтов или приложений, и сервер выбирает нужный virtual host именно по Host.
Когда ты открываешь https://example.com/api в браузере, браузер сам отправляет Host: example.com. Когда ты запускаешь curl https://example.com/api, curl делает то же самое. Вручную Host обычно задают только для диагностики:
curl -H "Host: app.internal" http://127.0.0.1/api
Так можно подключиться к локальному IP, но проверить, как приложение поведёт себя для имени app.internal.
У ответа есть статус:
200 OK
404 Not Found
500 Internal Server Error
Это очень важная идея для диагностики:
- если нет DNS, клиент даже не узнает IP сервера;
- если нет маршрута, пакет не доедет;
- если порт закрыт, соединение не откроется;
- если HTTP отвечает
500, сеть уже сработала, но приложение сломалось внутри; - если HTTP отвечает
404, сервер жив, но такого пути нет.
Поэтому DevOps-инженер не просто спрашивает "сайт работает?". Он раскладывает проблему на уровни: имя, IP, маршрут, порт, процесс, протокол, приложение.
Что происходит, когда ты пишешь curl
Представь команду:
curl https://example.com/api
Теперь эта команда уже читается понятнее: curl как клиент хочет отправить HTTPS-запрос на сервер example.com и попросить путь /api.
Очень упрощённо происходит такая цепочка:
- Система должна понять, какой IP-адрес стоит за именем
example.com. - Для этого она делает DNS-запрос:
example.com -> 93.184.216.34. - Затем Linux смотрит таблицу маршрутов: через какой интерфейс и шлюз отправлять пакет к этому IP.
- Клиент открывает TCP-соединение к IP и порту. Для HTTPS это обычно порт
443, для HTTP —80. - Если это HTTPS, поверх TCP начинается TLS: клиент и сервер договариваются о шифровании.
- Потом уже идёт HTTP-запрос:
GET /api. - На сервере какой-то процесс слушает нужный порт и отвечает.
Если что-то сломалось, проблема может быть на любом шаге: DNS не резолвит имя, нет маршрута, доступ к порту запрещён, процесс не слушает, приложение отвечает 500, TLS-сертификат не подходит.
IP-адрес: куда подключаемся
IP-адрес — это адрес узла в сети. В Linux ты часто увидишь IPv4-адреса вроде:
192.168.1.20
10.0.2.15
172.17.0.2
127.0.0.1
Частные адреса 10.x.x.x, 172.16.x.x-172.31.x.x, 192.168.x.x обычно живут внутри локальных сетей, облачных VPC, Docker-сетей и домашних роутеров. Они не уникальны во всём интернете: один и тот же 192.168.1.10 может существовать в тысячах разных локальных сетей.
127.0.0.1 — это localhost. Он всегда означает "эта же машина". Если сервис слушает только 127.0.0.1:8080, к нему можно подключиться с этой машины, но нельзя напрямую с другой машины.
Маска сети: кто рядом
IP-адрес сам по себе не всегда говорит, кто находится "рядом" с машиной в той же локальной сети. Поэтому адрес часто пишут вместе с маской, например 192.168.1.20/24.
192.168.1.20 — это адрес машины. /24 — это маска сети. Она говорит: первые три части адреса, 192.168.1, считаются номером локальной сети. Последняя часть — номер конкретного устройства внутри этой сети.
В практическом виде 192.168.1.20/24 означает, что локальная сеть примерно охватывает адреса 192.168.1.0–192.168.1.255.
То есть 192.168.1.50 находится рядом, а 192.168.2.50 уже не рядом.
Зачем это нужно Linux:
- Если адрес назначения в той же локальной сети, можно отправить данные напрямую этому устройству.
- Если адрес назначения не в той же локальной сети, нужно отправить данные на шлюз, то есть ближайший роутер.
Пример:
IP твоей машины: 192.168.1.20/24
сосед в той же сети: 192.168.1.50
другая сеть: 192.168.2.50
интернет-адрес: 8.8.8.8
К 192.168.1.50 можно идти напрямую через локальный интерфейс. К 192.168.2.50 и 8.8.8.8 напрямую нельзя: Linux отправит данные на шлюз, а дальше уже роутеры будут передавать их по маршруту.
Если маску поменять, граница "кто рядом" тоже поменяется:
| Адрес на машине | Кто считается рядом |
|---|---|
192.168.1.20/24 |
обычно 192.168.1.x |
192.168.1.20/16 |
обычно 192.168.x.x |
Поэтому маска отвечает не на вопрос "какой у меня IP?", а на вопрос "какая часть адресов считается моей локальной сетью?". Без неё Linux не смог бы уверенно решить, куда отправлять данные: напрямую соседу или через шлюз.
Порт: в какой процесс попадаем
IP-адрес отвечает на вопрос "на какую машину". Порт отвечает на вопрос "в какой сервис на этой машине".
Примеры:
| Порт | Частое назначение |
|---|---|
22 |
SSH |
80 |
HTTP |
443 |
HTTPS |
5432 |
PostgreSQL |
6379 |
Redis |
8080 |
HTTP-приложения, тестовые сервисы |
На одном IP может быть много процессов, если они слушают разные порты:
192.168.1.20:22 -> sshd
192.168.1.20:80 -> nginx
192.168.1.20:5432 -> postgres
Когда говорят "сервис недоступен", всегда уточняй адрес и порт. host доступен по ping и порт 8080 открыт — это разные проверки.
TCP и UDP: разные типы соединений
Для начала достаточно помнить:
| Протокол | Как думать |
|---|---|
| TCP | соединение с подтверждениями: SSH, HTTP, PostgreSQL |
| UDP | отправка отдельных сообщений без постоянного соединения: DNS, часть VPN, метрики |
Когда мы смотрим ss -tlnp, флаг -t означает TCP. Для UDP будет ss -ulnp.
DNS: имя превращается в IP
Людям удобно помнить имя api.example.com.
Сетевому стеку нужен IP, например 203.0.113.10.
DNS — это система, которая отвечает на вопрос "какой IP у этого имени?". В Linux это можно проверить командами:
dig example.com
dig +short example.com
nslookup example.com
Если DNS не работает, curl https://example.com может упасть ещё до попытки подключения к серверу. При этом curl http://203.0.113.10 может работать, потому что DNS уже не нужен.
Есть ещё локальный файл /etc/hosts. Это маленькая таблица на самой машине: какое имя к какому IP привязать без запроса к DNS.
Пример:
127.0.0.1 localhost
192.168.1.10 myapp.local
Если в /etc/hosts есть строка 192.168.1.10 myapp.local, то команда:
curl http://myapp.local
пойдёт на 192.168.1.10, даже если настоящий DNS сказал бы другой IP.
Зачем это нужно:
- дать локальное имя тестовому серверу;
- проверить новый сервер до изменения DNS;
- временно направить домен на нужный IP во время диагностики.
Важно: /etc/hosts действует только на этой машине. Если ты поменял его у себя, это не меняет DNS для других людей и серверов. Поэтому при странной проблеме с именем полезно проверить не только DNS, но и локальный /etc/hosts.
Маршрут и шлюз: куда отправить пакет
Linux хранит таблицу маршрутов. Она отвечает на вопрос: "если пакет идёт к такому IP, через какой интерфейс его отправить?"
Типичная идея такая:
адреса моей локальной сети -> отправить напрямую через eth0
всё остальное -> отправить на gateway
Gateway, или шлюз, — это следующий узел, которому Linux отдаёт пакет, если адрес не находится в локальной сети. В домашней сети это обычно роутер. В облаке — виртуальный маршрутизатор VPC.
Команда:
ip route
покажет эти правила. Важная строка обычно начинается с default: это маршрут "для всего, что не подошло под более точные правила".
127.0.0.1, 0.0.0.0 и внешний IP
Эти адреса часто путают.
127.0.0.1 — только эта машина, например 127.0.0.1:8080.
Сервис доступен локально, но не снаружи.
0.0.0.0 в выводе слушающих портов означает "все IPv4-интерфейсы", например 0.0.0.0:8080.
Сервис принимает подключения на всех адресах машины, если маршруты и настройки доступа это разрешают.
Внешний или локальный адрес интерфейса:
192.168.1.20:8080
10.0.2.15:8080
Сервис слушает конкретный сетевой адрес.
Минимальная модель диагностики
Когда приложение не отвечает, удобно идти снизу вверх:
- Есть ли IP-адрес на интерфейсе?
ip addr - Есть ли маршрут к нужному адресу?
ip route,ip route get IP - Резолвится ли имя?
dig domain - Слушает ли процесс нужный порт?
ss -tlnp - Есть ли сетевой путь до хоста?
ping,traceroute - Отвечает ли HTTP-уровень?
curl -v,curl -I - Что говорит приложение и его логи?
Главная мысль: не делай вывод по одной команде. ping может работать, а HTTP — нет. DNS может быть исправен, но порт закрыт. Порт может слушать, но приложение внутри отдаёт 500.
Что запомнить перед следующей статьёй
- IP отвечает на вопрос "куда".
- Порт отвечает на вопрос "в какой сервис".
- DNS превращает имя в IP.
- Маршрут говорит Linux, через какой интерфейс и шлюз отправить пакет.
127.0.0.1— только локальная машина.0.0.0.0у слушающего сервиса — слушать все IPv4-интерфейсы.curlпроверяет прикладной HTTP-уровень, а не просто "есть ли сеть".
В следующей статье мы будем смотреть, как эти понятия видны в реальном выводе Linux-команд.
