Основы сети

TL;DR: Сеть в Linux — это стек уровней. Нижний (link) доставляет кадры между соседними устройствами по MAC-адресам. Средний (internet/network) маршрутизирует пакеты между сетями по IP-адресам. Верхний (transport) обеспечивает доставку между приложениями по портам (TCP — надёжно, UDP — быстро). Ядро Linux реализует весь стек и предоставляет интерфейсы (eth0, wlan0, lo) как точки входа в сеть.

Зачем это знать

Каждый сервер, контейнер, Pod в Kubernetes — участник сети. Без понимания основ невозможно:

  • Диагностировать «приложение не отвечает» — проблема на уровне DNS, маршрутизации, firewall или приложения?
  • Настроить firewall — какие порты открыть, что такое «входящий» vs «исходящий» трафик
  • Понять как работает Docker networking, Kubernetes Services, Ingress — все они надстройки над сетевым стеком Linux

Уровни сетевого стека

Сеть организована в уровни (layers). Каждый уровень решает свою задачу и не заботится о деталях других. На практике используется модель TCP/IP (4 уровня), а не академическая OSI (7 уровней).

Приложение (HTTP, SSH, DNS)
        │ данные
        ▼
Transport (TCP/UDP)         — доставка между приложениями (порты)
        │ сегмент
        ▼
Network / Internet (IP)     — маршрутизация между сетями (IP-адреса)
        │ пакет
        ▼
Link (Ethernet, Wi-Fi)      — передача между соседними устройствами (MAC-адреса)
        │ кадр
        ▼
Физическая среда (кабель, радио)

Инкапсуляция

Каждый уровень оборачивает данные верхнего уровня в свой «конверт» (заголовок):

[Ethernet header | IP header | TCP header | HTTP data ]
       ↑              ↑            ↑            ↑
     Link          Network    Transport    Application

При отправке — заголовки добавляются сверху вниз. При получении — снимаются снизу вверх. Каждый уровень читает только свой заголовок и передаёт содержимое наверх.

Доставка кадров (frames) между устройствами, физически подключёнными к одной сети (один Ethernet-сегмент, одна Wi-Fi-точка).

MAC-адреса

Каждый сетевой интерфейс имеет аппаратный MAC-адрес (48 бит, формат aa:bb:cc:dd:ee:ff). MAC-адрес уникален — назначается производителем.

ip link show
# 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> ...
#     link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
#                ↑ MAC-адрес

MAC-адреса работают только в пределах одного сегмента сети. Маршрутизатор (router) не передаёт кадры с оригинальными MAC — он создаёт новый кадр для следующего сегмента. Именно поэтому для связи между разными сетями нужен IP-уровень.

Сетевые интерфейсы

В Linux каждое сетевое устройство представлено интерфейсом:

ИнтерфейсОписание
loLoopback (127.0.0.1) — связь процессов на одном хосте
eth0 / enp0s3Проводной Ethernet
wlan0 / wlp2s0Wi-Fi
docker0Docker bridge
veth*Virtual Ethernet (контейнеры)
br-*Bridge (программный коммутатор)
tun0 / wg0VPN-туннель

Имена enp0s3, wlp2s0 — предсказуемое именование (Predictable Network Interface Names): en = ethernet, wl = wireless, p0s3 = PCI bus/slot. Введено systemd, чтобы имена не менялись при добавлении оборудования.

# Все интерфейсы
ip link show
 
# Поднять/опустить интерфейс
sudo ip link set eth0 up
sudo ip link set eth0 down
 
# Состояние
ip -br link
# lo      UNKNOWN   00:00:00:00:00:00
# eth0    UP        52:54:00:12:34:56
# wlan0   DOWN      aa:bb:cc:dd:ee:ff

Network layer — сетевой уровень (IP)

Маршрутизация пакетов между разными сетями. Каждое устройство получает IP-адрес — логический адрес, в отличие от аппаратного MAC.

IPv4-адреса

32 бита, записывается как четыре октета: 192.168.1.100.

ip addr show eth0
# inet 192.168.1.100/24 brd 192.168.1.255 scope global eth0
#      ↑ IP-адрес  ↑ маска подсети

Подсети и маска

Маска подсети определяет, какая часть адреса — сеть, а какая — хост.

IP:     192.168.1.100
Маска:  255.255.255.0  (или /24 — 24 бита для сети)

Сеть:   192.168.1.0    (первые 24 бита)
Хост:            .100  (последние 8 бит)

Устройства с одинаковой сетевой частью — в одной подсети и могут общаться напрямую (через link layer). Для связи с другой подсетью — нужен маршрутизатор.

CIDRМаскаКол-во хостовТипичное применение
/32255.255.255.2551Один хост (loopback, point-to-point)
/24255.255.255.0254Типичная локальная сеть
/16255.255.0.065 534Большая корпоративная сеть
/8255.0.0.0~16 млнКласс A (10.0.0.0/8)

Частные адреса (RFC 1918)

Не маршрутизируются в интернете — только внутри локальных сетей:

ДиапазонCIDRТипичное применение
10.0.0.010.255.255.25510.0.0.0/8Облачные VPC, крупные сети
172.16.0.0172.31.255.255172.16.0.0/12Docker default bridge (172.17.0.0/16)
192.168.0.0192.168.255.255192.168.0.0/16Домашние/офисные сети

Для выхода в интернет — NAT (Network Address Translation) на маршрутизаторе подменяет частный адрес на публичный.

Специальные адреса

АдресНазначение
127.0.0.1Loopback — сам хост (localhost)
0.0.0.0«Все интерфейсы» (при bind) или «маршрут по умолчанию»
255.255.255.255Broadcast — всем в сети
x.x.x.0Адрес сети (не назначается хостам)
x.x.x.255 (при /24)Broadcast подсети

Маршрутизация

Когда хост отправляет пакет, ядро решает куда его направить по таблице маршрутизации:

  1. IP назначения в моей подсети? → отправить напрямую через link layer (ARP → MAC → кадр)
  2. Не в моей подсети? → отправить на gateway (маршрутизатор по умолчанию)
ip route
# default via 192.168.1.1 dev eth0              ← gateway (всё, что не попало в другие маршруты)
# 192.168.1.0/24 dev eth0 proto kernel scope link ← моя подсеть (напрямую)
# 172.17.0.0/16 dev docker0 proto kernel scope link ← Docker-сеть
Хост A (192.168.1.100)                  Хост B (10.0.0.50)
     │                                       ↑
     │ пакет: src=192.168.1.100              │
     │         dst=10.0.0.50                 │
     ▼                                       │
 Router / Gateway (192.168.1.1)──────────────┘
     Знает маршрут в сеть 10.0.0.0/24
# Проверить маршрут до конкретного адреса
ip route get 8.8.8.8
# 8.8.8.8 via 192.168.1.1 dev eth0 src 192.168.1.100
 
# Трассировка — через какие маршрутизаторы идёт пакет
traceroute 8.8.8.8

Transport layer — транспортный уровень

Доставка данных между приложениями на разных (или одном) хостах. Адресация — порт (число 0–65535).

TCP vs UDP

TCPUDP
СоединениеДа (handshake: SYN → SYN-ACK → ACK)Нет
НадёжностьГарантирует доставку, порядок, повтор потерянныхНе гарантирует
СкоростьМедленнее (overhead на подтверждения)Быстрее
ПрименениеHTTP(S), SSH, SMTP, базы данныхDNS, видео/аудио, игры, VPN

Порты

Порт — число, идентифицирующее приложение на хосте. Соединение однозначно определяется четвёркой: src_ip:src_port → dst_ip:dst_port.

ДиапазонНазваниеОписание
0–1023Well-knownСистемные, требуют root (или CAP_NET_BIND_SERVICE)
1024–49151RegisteredЗарегистрированные за приложениями
49152–65535EphemeralДинамические, назначаемые ядром клиентам

Частые порты:

ПортПротоколСервис
22TCPSSH
53TCP/UDPDNS
80TCPHTTP
443TCPHTTPS
5432TCPPostgreSQL
6379TCPRedis
3306TCPMySQL
# Кто слушает порты
ss -tlnp                   # TCP listening
ss -ulnp                   # UDP listening
 
# Проверить конкретный порт
ss -tlnp | grep :80

Как всё работает вместе: путь пакета

Когда curl https://example.com отправляет запрос:

1. DNS-резолвинг
   Приложение → resolver → DNS-сервер (UDP:53)
   example.com → 93.184.216.34

2. TCP handshake (установка соединения)
   [SYN]     192.168.1.100:49832 → 93.184.216.34:443
   [SYN-ACK] 93.184.216.34:443  → 192.168.1.100:49832
   [ACK]     192.168.1.100:49832 → 93.184.216.34:443

3. TLS handshake (шифрование)

4. HTTP-запрос (данные)
   [Ethernet | IP | TCP | TLS | "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"]
       ↑       ↑     ↑     ↑
     Link    Network Transport  Application

5. Маршрутизация на каждом хопе
   Хост → Gateway → ISP router → ... → сервер example.com
   (на каждом хопе: IP header сохраняется, Ethernet header меняется)

6. Ответ идёт обратно по тому же принципу

Конфигурация сети в Linux

Ядро хранит состояние сети: интерфейсы, IP-адреса, таблицу маршрутов, ARP-кеш. Утилита ip (пакет iproute2) — основной инструмент.

# Интерфейсы и IP
ip addr show               # полная информация
ip -br addr                # краткая: интерфейс, состояние, IP
 
# Назначить IP (временно, до reboot)
sudo ip addr add 192.168.1.100/24 dev eth0
sudo ip addr del 192.168.1.100/24 dev eth0
 
# Маршруты
ip route show
sudo ip route add 10.0.0.0/24 via 192.168.1.1 dev eth0
sudo ip route del 10.0.0.0/24
 
# ARP-кеш (IP → MAC маппинг)
ip neigh show

Постоянная конфигурация — через NetworkManager (nmcli), netplan, или systemd-networkd. Подробнее: configure-network.

DNS-резолвинг

Порядок резолвинга имён определяется /etc/nsswitch.conf (строка hosts:):

# /etc/nsswitch.conf
hosts: files dns
#      ↑     ↑
#      |     DNS-серверы из /etc/resolv.conf
#      /etc/hosts (локальные записи, проверяются первыми)
# /etc/resolv.conf — какие DNS-серверы использовать
nameserver 8.8.8.8
nameserver 1.1.1.1
 
# /etc/hosts — локальные записи (приоритет над DNS)
127.0.0.1   localhost
192.168.1.50 db.local

В современных системах с systemd-resolved /etc/resolv.conf часто указывает на локальный stub-резолвер (127.0.0.53), который кеширует запросы и перенаправляет на настроенные серверы.

Диагностика по уровням

Когда «сеть не работает» — проверяй уровень за уровнем, снизу вверх:

# 1. Link: интерфейс поднят?
ip link show eth0
# Ожидаем: state UP
 
# 2. Network: IP назначен?
ip addr show eth0
# Ожидаем: inet 192.168.1.x/24
 
# 3. Network: gateway доступен?
ping -c 2 192.168.1.1
 
# 4. Network: интернет доступен по IP?
ping -c 2 8.8.8.8
 
# 5. DNS: имена резолвятся?
ping -c 2 google.com
# Если ping по IP работает, а по имени нет — проблема DNS
 
# 6. Transport: порт доступен?
nc -zv example.com 443
curl -I https://example.com
 
# 7. Application: сервис отвечает корректно?
curl https://example.com

Подводные камни

ПроблемаСимптомРешение
ping по IP работает, по имени нетping 8.8.8.8 OK, ping google.com failПроблема DNS: проверить /etc/resolv.conf, resolvectl status
Connection refusedTCP RST от хостаПорт закрыт или сервис не запущен. ss -tlnp | grep PORT
No route to hostICMP unreachableНет маршрута. ip route get <IP>, проверить gateway
Network is unreachableНет default routeip route — должен быть default via ...
Connection timed outНет ответа (пакеты дропаются)Firewall на пути. Проверить iptables -L, ufw status
Приложение слушает на 127.0.0.1, не на 0.0.0.0Доступно только локальноНастроить bind address на 0.0.0.0 (все интерфейсы)
Предсказуемые имена интерфейсовenp0s25 вместо eth0Это нормально (systemd). ip link покажет реальные имена

Связанные материалы