Маршрутизация — routing tables, default gateway и longest prefix
Пакет, идущий от вашего ноутбука к github.com, проходит через 15-25 устройств — роутеров разных уровней, от вашего домашнего модема до магистральных коммутаторов AS GitHub. Каждый из этих роутеров делает ровно одно решение: «куда отправить этот пакет дальше?». Это и есть маршрутизация.
В этом уроке разберём, как работает routing table, что такое default gateway, как роутер выбирает маршрут по правилу longest prefix match. Это базовый mental model сетевика и DE — без него вы не понимаете, почему один пакет идёт в одну сторону, другой в другую, и почему ip route показывает именно то, что показывает.
Что такое маршрутизация
Маршрутизация (routing) — это процесс выбора пути для пакета между сетями. Внутри одной сети (одного broadcast domain) пакеты передаёт свитч — по MAC-адресам. Между разными сетями работает роутер — по IP-адресам.
Каждое устройство, у которого есть IP, имеет routing table. Это таблица «куда отправлять пакет, если его IP назначения такой-то». Алгоритм для каждого исходящего пакета:
- Взять dst IP пакета.
- Найти в routing table запись, которая «покрывает» этот IP.
- Отправить пакет на указанный next-hop через указанный интерфейс.
Главная идея: роутер выбирает next-hop, а не конечный пункт. Каждый роутер видит только следующий шаг — куда передать. Следующий роутер сделает то же самое для своего следующего шага. И так до места назначения.
Это похоже на эстафету: каждый бегун не знает, кто последний, только — кому передать палочку.
Memory hierarchy — регистры, cache, RAM, disk и latencyСтруктура routing table
Routing table — это набор записей. Каждая запись:
- Destination network (prefix). Какие IP покрывает (например,
10.0.0.0/8). - Next-hop / gateway. Через кого передать (IP следующего роутера).
- Interface. Через какой свой интерфейс отправить.
- Metric (опционально). Стоимость маршрута — для выбора при нескольких путях.
Посмотреть routing table в Linux:
ip route show
# default via 192.168.1.1 dev eth0 proto dhcp src 192.168.1.42 metric 100
# 169.254.0.0/16 dev eth0 scope link metric 1000
# 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.42 metric 100
Разбор:
default— это0.0.0.0/0, покрывает все IP. Для всего, что не подошло другим записям.via 192.168.1.1— next-hop. IP домашнего роутера.dev eth0— exit interface.192.168.1.0/24 ... scope link— локальная сеть, прямо подключена. Не нужен next-hop, отправляем напрямую через ARP.proto kernel— запись создана автоматически (ядром приip addr add).proto dhcp— запись пришла из DHCP-ответа (default route обычно).
На macOS:
netstat -nr -f inet
# Destination Gateway Flags Netif Expire
# default 192.168.1.1 UGScg en0
# 127 127.0.0.1 UCS lo0
# 192.168.1 link#5 UCS en0
# 192.168.1.1/32 link#5 UCS en0
В Windows:
route print
Default gateway — куда идут «все остальные» пакеты
Особая запись default (она же 0.0.0.0/0) покрывает все IP. Это самая общая (самая короткая по префиксу) запись — срабатывает, если ни одна другая не подошла.
Пример сценария:
Ваш IP 192.168.1.42, gateway 192.168.1.1. Routing table:
192.168.1.0/24— localdefaultvia192.168.1.1
Когда вы пингуете 192.168.1.50 (сосед в локалке):
- Первая запись подходит (
192.168.1.50в192.168.1.0/24). - ARP — получили MAC. Шлём напрямую.
- Никакого next-hop, никакого роутера.
Когда вы пингуете 8.8.8.8:
- Первая запись не подходит.
defaultподходит.- Шлём через next-hop
192.168.1.1(роутер). - Роутер дальше сам разбирается.
Без default gateway машина общается только в локалке. Интернет недоступен. Это популярный симптом «у меня IP есть, но интернета нет» — часто проблема в неправильном или отсутствующем default route.
# Узнать default gateway:
ip route show default
# default via 192.168.1.1 dev eth0
# или (старый стиль):
route -n | head
# Destination Gateway Genmask Flags Metric Ref Use Iface
# 0.0.0.0 192.168.1.1 0.0.0.0 UG 100 0 0 eth0
# 192.168.1.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
Flags UG: U = up, G = gateway (через next-hop). U без G = direct route (локальная сеть).
Longest prefix match — как роутер выбирает маршрут
Когда несколько записей подходят — роутер выбирает самую специфичную, то есть с самым длинным префиксом. Это правило называется longest prefix match (LPM).
Пример. Routing table:
0.0.0.0/0 via 192.168.1.1 (default)
10.0.0.0/8 via 10.20.0.1 (route ко всему 10/8)
10.5.0.0/16 via 10.5.0.1 (более специфичный)
10.5.42.0/24 via 10.5.42.100 (ещё более специфичный)
Логика проста: чем длиннее префикс, тем более специфичный (точный) маршрут. Если есть точная запись /32 для конкретного IP — победит даже над /31.
LPM позволяет иметь общие «catch-all» правила (default) и специфичные исключения. Например, «весь трафик — через VPN-туннель, но исключения для DNS и corporate-сетей — напрямую».
Виды маршрутов
Маршрутизация бывает разных типов:
1. Прямой (directly connected). Маршрут на свою же подсеть. Не нужен next-hop — хост в этой подсети, ARP даст MAC. Создаётся автоматически когда вы делаете ip addr add 192.168.1.42/24 — ядро добавляет 192.168.1.0/24 dev eth0.
2. Static route. Маршрут, прописанный руками админом или конфигом. Не меняется автоматически. Пример: ip route add 10.99.0.0/16 via 192.168.1.5.
3. Dynamic route. Маршрут, выученный по протоколу маршрутизации (OSPF, BGP). Обновляется автоматически при изменении топологии. Об этом отдельный урок.
4. Default route. 0.0.0.0/0, специальный case — покрывает всё.
5. Black hole. Специально настроенный маршрут «отправлять пакеты в никуда». Используется для DDoS защиты, изоляции.
# Добавить static route (нужен root):
sudo ip route add 10.99.0.0/16 via 192.168.1.5 dev eth0
# Black hole (пакеты для 10.99.0.0/16 дропаются):
sudo ip route add blackhole 10.99.0.0/16
# Удалить маршрут:
sudo ip route del 10.99.0.0/16
# Сделать постоянным -- редактируйте /etc/network/interfaces или nmcli connection modify
ECMP — несколько равных маршрутов
Если у вас в routing table несколько записей с одинаковым префиксом и метрикой — роутер может распределять трафик между ними. Это называется ECMP (Equal-Cost Multi-Path).
ip route show 10.0.0.0/8
# 10.0.0.0/8 proto bgp
# nexthop via 10.20.0.1 dev eth0 weight 1
# nexthop via 10.20.0.2 dev eth0 weight 1
Для каждого нового потока (определяемого по src IP / dst IP / src port / dst port — hash) выбирается один из next-hop. Это даёт:
- Load balancing. Трафик равномерно распределяется по нескольким каналам.
- Резервирование. Если один линк упал — остальные продолжают работать.
ECMP — стандарт в дата-центрах spine-leaf, где между каждой парой свитчей идёт 4-8 равноценных линков, и трафик хэшируется между ними.
Прохождение пакета — пример
Соберём всё вместе. Сценарий: ваш ноутбук (192.168.1.42) пингует Google DNS (8.8.8.8).
-
Ваш ноутбук. Routing table:
192.168.1.0/24— localdefault via 192.168.1.1- Lookup
8.8.8.8-> подходитdefault. Next-hop =192.168.1.1. - ARP for
192.168.1.1-> MAC00:1c:42:00:00:18. - Ethernet frame:
[dst MAC = 00:1c:42:...] [src MAC = ваш] [IP: src=192.168.1.42, dst=8.8.8.8].
-
Домашний роутер. Получает кадр на LAN-интерфейс.
- Распаковывает Ethernet (берёт IP-пакет).
- Routing table:
192.168.1.0/24— LAN (eth0)<провайдерский пул>/N— WAN (eth1)default via 10.X.Y.1(провайдер) на eth1
- Lookup
8.8.8.8-> default. Next-hop = провайдерский роутер. - NAT! src IP меняется с
192.168.1.42на публичный IP домашнего роутера. - Новый Ethernet-кадр на WAN-интерфейсе с MAC провайдера.
-
Провайдерский роутер. Получает.
- Routing table огромная (BGP — сотни тысяч записей).
- Lookup
8.8.8.8. Подходит запись8.0.0.0/8 via <магистраль>или ещё более специфичная. - Передаёт next-hop.
-
Магистральный роутер. То же самое, пока пакет не доберётся до AS Google.
-
Google AS roter. Lookup
8.8.8.8. Это уже внутри Google. -
Сервер 8.8.8.8. Принимает ICMP echo, отвечает echo reply.
Обратный путь — зеркальный. Каждый раз каждый роутер на своём уровне ищет в своей routing table запись для dst IP пакета.
Asymmetric routing — путь туда и обратно разный
В реальной жизни путь пакета туда и обратно может быть разный. Это нормально:
- Ваш пакет идёт через провайдера A (потому что у него лучший маршрут до Google).
- Ответ Google идёт через провайдера B (потому что у Google лучший маршрут к вам через B).
Никакого протокола, говорящего «отвечай тем же путём», нет. Каждый роутер решает локально.
Это становится проблемой когда:
- NAT. Если пакет ушёл через NAT-роутер A, ответ должен прийти на A (там в NAT-таблице связки). Если ответ пошёл на B — B не знает, кому это, дропает. Решение: NAT на одной точке либо session sync между routers.
- Stateful firewall. Видит SYN на одном пути, SYN-ACK на другом — бьёт тревогу, дропает. Решение: routing симметрично, либо синхронизация состояний.
В дата-центрах большие команды борются с asymmetric routing. На пользовательском уровне — редко мешает.
Запись в routing table — что значит каждое поле
Пример Linux:
default via 192.168.1.1 dev eth0 proto dhcp src 192.168.1.42 metric 100
default— destination prefix.default=0.0.0.0/0.via 192.168.1.1— next-hop IP.dev eth0— exit interface.proto dhcp— источник записи. Бываетkernel(автоматическая),static(руками),dhcp(от DHCP-сервера),bgp/ospf(от dynamic routing),boot(при загрузке).src 192.168.1.42— какой src IP использовать в пакетах, идущих по этому маршруту. Полезно когда у машины несколько IP.metric 100— стоимость маршрута. Если есть несколько маршрутов до одной цели — выбирается меньшая метрика.
# Посмотреть routing table детально:
ip -d route show
ip route show table all # все таблицы, включая main, local, default
# Linux может иметь несколько routing tables (для policy-based routing):
ip rule list
# 0: from all lookup local
# 32766: from all lookup main
# 32767: from all lookup default
local — маршруты к собственным IP (loopback, своим интерфейсам). main — обычные маршруты (то что показывает ip route show). default — последний по приоритету.
Policy-based routing (PBR) — продвинутая тема. Например, «трафик из src 192.168.1.50 — через VPN, остальной — напрямую». Реализуется через ip rule + дополнительные таблицы.
Попробуй сам
# 1. Посмотреть routing table:
ip route show
netstat -nr -f inet # macOS
# 2. Узнать, куда пойдёт пакет:
ip route get 8.8.8.8
# 8.8.8.8 via 192.168.1.1 dev eth0 src 192.168.1.42 uid 1000
# 3. Узнать MTU маршрута:
ip route get 8.8.8.8 | grep -o 'mtu [0-9]*'
# 4. Симулировать трассу:
traceroute -n 8.8.8.8
# 1 192.168.1.1 1.234 ms
# 2 10.0.0.1 5.678 ms (gateway провайдера)
# 3 87.123.45.6 12.345 ms (магистраль)
# ...
# 5. Добавить временный маршрут (нужен root):
sudo ip route add 192.0.2.0/24 via 192.168.1.5 dev eth0
ip route show 192.0.2.0/24
sudo ip route del 192.0.2.0/24
# 6. Удалить default gateway и посмотреть, что произойдёт:
# СТОП -- это сломает интернет! Делайте только если знаете, как восстановить:
sudo ip route del default
ping -c 1 8.8.8.8 # "Network unreachable"
# Восстановить:
sudo ip route add default via 192.168.1.1 dev eth0
# 7. Посмотреть таблицы local и main:
ip route show table local
ip route show table main
# 8. Узнать source IP для пакета к конкретному hostу:
ip route get 8.8.8.8 | grep -o 'src [0-9.]*'
# Это полезно для приложений, биндящихся на конкретный IP