Симуляция сетевой связности в Linux

CompTIABeginner
Практиковаться сейчас

Введение

В этой лабораторной работе вы изучите фундаментальные принципы сетевой связности на уровне сети в среде Linux. Используя контейнеры Docker для симуляции двух отдельных узлов, вы научитесь вручную назначать статические IP-адреса с помощью команды ip. Затем вы будете использовать утилиту ping для проверки прямого пути связи между этими узлами в общей виртуальной сети.

Сначала настроив узлы в одной подсети, вы увидите успешную связность. Затем вы перенастроите один узел на другую подсеть, чтобы наблюдать предсказуемый сбой связи — ошибку «Destination Host Unreachable» (Хост назначения недоступен). Это практическое упражнение наглядно демонстрирует, как IP-подсети управляют прямой связью и почему устройства в разных логических сетях не могут соединиться без маршрутизатора.

Подготовка лабораторной среды из двух узлов

На этом этапе вы подготовите базовую среду для нашей лабораторной работы. Вместо использования полноценных виртуальных машин мы будем использовать легковесные и изолированные контейнеры Docker для симуляции двух отдельных сетевых узлов. Чтобы обеспечить связь между ними, мы сначала создадим пользовательскую сеть Docker. Эта виртуальная сеть действует как физический сетевой коммутатор, помещая оба наших узла в один общий сегмент связи.

Давайте загрузим образ Docker Ubuntu 22.04 для узлов.

docker pull ubuntu:22.04

Сначала создадим виртуальную сеть, которую будут использовать наши два узла. Мы назовем ее lab_net и назначим ей определенный диапазон IP-адресов, что будет важно на последующих этапах.

Выполните следующую команду в вашем терминале:

docker network create --subnet=192.168.56.0/24 lab_net

Эта команда указывает Docker создать новую мостовую сеть с именем lab_net и настраивает ее на использование подсети 192.168.56.0/24. В качестве вывода вы увидите длинный уникальный идентификатор сети, подтверждающий ее создание.

e8c1c2a3b4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1

Далее мы запустим наш первый узел, контейнер с именем node1, и подключим его к сети lab_net.

docker run -d --name node1 --network lab_net --cap-add=NET_ADMIN ubuntu:22.04 sleep infinity

Разберем эту команду:

  • docker run: Стандартная команда для создания и запуска нового контейнера.
  • -d: Запускает контейнер в "отсоединенном" режиме, то есть он работает в фоновом режиме.
  • --name node1: Присваивает нашему контейнеру простое, запоминающееся имя.
  • --network lab_net: Подключает контейнер к виртуальной сети, которую мы создали ранее.
  • --cap-add=NET_ADMIN: Предоставляет контейнеру возможность NET_ADMIN, которая требуется для изменения сетевых настроек, таких как добавление IP-адресов.
  • ubuntu:22.04: Образ Docker, который мы используем, предоставляющий стандартную среду Ubuntu.
  • sleep infinity: Простая команда, которая выполняется бесконечно, чтобы поддерживать контейнер активным.

Теперь запустим второй узел, node2, используя аналогичную команду:

docker run -d --name node2 --network lab_net --cap-add=NET_ADMIN ubuntu:22.04 sleep infinity

Наконец, давайте проверим, что оба наших узла работают корректно. Команда docker ps выводит список всех запущенных в данный момент контейнеров.

docker ps

Вы должны увидеть вывод, похожий на следующий, подтверждающий, что node1 и node2 запущены и работают.

CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS     NAMES
a1b2c3d4e5f6   ubuntu:22.04   "sleep infinity"         5 seconds ago    Up 4 seconds              node2
g7h8i9j0k1l2   ubuntu:22.04   "sleep infinity"         15 seconds ago   Up 14 seconds             node1

Поскольку оба узла работают в одной виртуальной сети, наша лабораторная среда готова. На следующих этапах мы настроим их IP-адреса и проверим их связность.

Настройка статического IP-адреса на первом узле с помощью ip addr

На этом этапе вы назначите статический IP-адрес нашему первому контейнеру, node1. Статический IP-адрес — это адрес, который настраивается вручную и не меняется, в отличие от динамического IP-адреса, который часто автоматически назначается DHCP-сервером. Для нашей симуляции использование статических IP-адресов дает нам точный контроль над сетевой конфигурацией.

Все действия мы будем выполнять из вашего основного терминала на хост-машине, используя команду docker exec для выполнения команд внутри контейнера node1.

Сначала базовый образ ubuntu:22.04 очень минималистичен. Нам нужно установить необходимые сетевые инструменты. Давайте начнем с обновления списка пакетов внутри контейнера node1:

docker exec node1 apt-get update

Вы увидите вывод по мере того, как контейнер получает информацию о последних пакетах.

Затем установите пакет iproute2 (который предоставляет команду ip) и iputils-ping (который предоставляет команду ping, которую мы будем использовать позже).

docker exec node1 apt-get install -y iproute2 iputils-ping

Теперь, когда инструменты установлены, давайте проверим текущую сетевую конфигурацию node1. Сетевой интерфейс внутри стандартного контейнера Docker обычно называется eth0.

docker exec node1 ip addr show eth0

В выводе будут показаны детали интерфейса eth0. Вы можете увидеть IP-адрес, уже назначенный внутренним DHCP-сервером Docker (например, 192.168.56.2). Мы собираемся добавить наш собственный статический IP-адрес.

9: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:c0:a8:38:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.56.2/24 brd 192.168.56.255 scope global eth0
       valid_lft forever preferred_lft forever

Теперь давайте назначим статический IP-адрес 192.168.56.10 для node1. /24 — это CIDR-нотация для маски подсети 255.255.255.0, определяющая размер сети.

docker exec node1 ip addr add 192.168.56.10/24 dev eth0

Эта команда не должна выдавать никакого вывода в случае успеха. Чтобы подтвердить изменение, снова выполните команду ip addr show eth0:

docker exec node1 ip addr show eth0

Теперь вы должны увидеть ваш новый статический IP-адрес, перечисленный рядом с исходным, помеченный как secondary (вторичный). Это подтверждает, что node1 теперь настроен с адресом 192.168.56.10.

9: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:c0:a8:38:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.56.2/24 brd 192.168.56.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet 192.168.56.10/24 scope global secondary eth0
       valid_lft forever preferred_lft forever

Настройка статического IP-адреса на втором узле в той же подсети

На этом этапе мы настроим наш второй узел, node2, со статическим IP-адресом. Чтобы два устройства могли напрямую общаться без маршрутизатора, они должны находиться в одной логической подсети. Мы назначим node2 IP-адрес из той же подсети 192.168.56.0/24, которую мы использовали для node1. Эта настройка логически имитирует два ПК, соединенных кроссоверным кабелем, где оба являются частью одной локальной сети.

Сначала, как мы делали для node1, нам нужно установить необходимые сетевые инструменты внутри контейнера node2. Начните с обновления списка пакетов:

docker exec node2 apt-get update

Затем установите пакеты iproute2 и iputils-ping на node2:

docker exec node2 apt-get install -y iproute2 iputils-ping

После установки инструментов мы можем назначить статический IP-адрес для node2. Мы будем использовать 192.168.56.11, который находится в той же подсети, что и node1 (192.168.56.10), но является уникальным адресом.

docker exec node2 ip addr add 192.168.56.11/24 dev eth0

Эта команда добавляет IP-адрес 192.168.56.11 с маской подсети /24 к сетевому интерфейсу eth0 контейнера node2. Если команда выполнена успешно, она не выдаст никакого вывода.

Чтобы убедиться, что IP-адрес был назначен правильно, давайте проверим сетевую конфигурацию node2:

docker exec node2 ip addr show eth0

В выводе теперь должен отображаться недавно добавленный статический IP-адрес, помеченный как secondary (вторичный). Это подтверждает, что node2 правильно настроен и готов к следующему шагу, где мы проверим связность.

11: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:c0:a8:38:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.56.3/24 brd 192.168.56.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet 192.168.56.11/24 scope global secondary eth0
       valid_lft forever preferred_lft forever

Проверка прямой связи между узлами с помощью ping

На этом этапе вы проверите сетевую связность между node1 и node2. Теперь, когда оба узла имеют IP-адреса в одной подсети, они должны иметь возможность общаться напрямую. Мы будем использовать команду ping — фундаментальную сетевую утилиту, которая отправляет небольшой пакет данных (ICMP Echo Request) на целевой хост и ожидает ответа. Успешный ответ подтверждает наличие сетевого пути между двумя устройствами.

Этот успешный тест аналогичен подключению двух ПК кроссоверным кабелем, когда оба устройства находятся в одной локальной сети и могут видеть друг друга напрямую.

Сначала попробуем выполнить ping до node2 с node1. Мы выполним команду ping внутри контейнера node1, нацеливаясь на IP-адрес node2, 192.168.56.11.

docker exec node1 ping -c 4 192.168.56.11

Разберем эту команду:

  • docker exec node1: выполняет следующую команду внутри контейнера node1.
  • ping: утилита для проверки связности.
  • -c 4: флаг, который указывает ping отправить ровно 4 пакета и затем остановиться. Без этого ping будет работать бесконечно.
  • 192.168.56.11: IP-адрес назначения node2.

Вы должны увидеть успешный вывод с полученными ответами от node2.

PING 192.168.56.11 (192.168.56.11) 56(84) bytes of data.
64 bytes from 192.168.56.11: icmp_seq=1 ttl=64 time=0.123 ms
64 bytes from 192.168.56.11: icmp_seq=2 ttl=64 time=0.087 ms
64 bytes from 192.168.56.11: icmp_seq=3 ttl=64 time=0.091 ms
64 bytes from 192.168.56.11: icmp_seq=4 ttl=64 time=0.085 ms

--- 192.168.56.11 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3074ms
rtt min/avg/max/mdev = 0.085/0.096/0.123/0.015 ms

Строка "4 received, 0% packet loss" подтверждает, что соединение работает. Теперь проверим соединение в обратном направлении, выполнив ping до node1 с node2.

docker exec node2 ping -c 4 192.168.56.10

Опять же, вы должны увидеть успешную серию ответов, подтверждающую, что связь двунаправленная.

PING 192.168.56.10 (192.168.56.10) 56(84) bytes of data.
64 bytes from 192.168.56.10: icmp_seq=1 ttl=64 time=0.099 ms
64 bytes from 192.168.56.10: icmp_seq=2 ttl=64 time=0.088 ms
64 bytes from 192.168.56.10: icmp_seq=3 ttl=64 time=0.092 ms
64 bytes from 192.168.56.10: icmp_seq=4 ttl=64 time=0.089 ms

--- 192.168.56.10 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3081ms
rtt min/avg/max/mdev = 0.088/0.092/0.099/0.004 ms

Успех! Оба узла могут общаться друг с другом, как если бы они были двумя компьютерами в одном сегменте локальной сети.

Перенастройка второго узла на другую подсеть

На этом шаге мы намеренно нарушим прямую связь между нашими двумя узлами. Мы сделаем это, перенастроив node2 на совершенно другую IP-подсеть, отличную от node1. Это имитирует сценарий, когда два устройства физически соединены, но логически разделены на разные сети.

В настоящее время node1 находится в подсети 192.168.56.0/24. Теперь мы переместим node2 в подсеть 192.168.58.0/24. Поскольку третье число (октет) отличается (56 против 58), они считаются отдельными подсетями.

Чтобы гарантировать полную изоляцию node2 в новой сети, мы должны сначала удалить все существующие IP-адреса с его интерфейса eth0. Это включает как статический IP-адрес, который мы добавили ранее, так и исходный IP-адрес, назначенный Docker автоматически. Команда ip addr flush — правильный инструмент для этой задачи.

docker exec node2 ip addr flush dev eth0

Эта команда удаляет всю IP-конфигурацию с eth0, обеспечивая чистый старт. Если она выполнена успешно, она не должна выдавать никакого вывода.

Теперь добавим новый IP-адрес, 192.168.58.11, который принадлежит новой подсети.

docker exec node2 ip addr add 192.168.58.11/24 dev eth0

Чтобы подтвердить изменения, давайте снова проверим сетевую конфигурацию node2.

docker exec node2 ip addr show eth0

Вы увидите, что все старые IP-адреса исчезли, и существует только новый (192.168.58.11). Это подтверждает, что node2 больше не находится в подсети 192.168.56.0/24.

11: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:c0:a8:38:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.58.11/24 scope global eth0
       valid_lft forever preferred_lft forever

Поскольку node1 находится в подсети 192.168.56.0/24, а node2 — в подсети 192.168.58.0/24, они теперь логически изолированы.

Тестирование связи и наблюдение за сбоем

На этом заключительном этапе мы снова попытаемся выполнить команду ping между узлами. Поскольку node2 теперь полностью изолирован в новой подсети, мы ожидаем сбоя связи, но двумя разными и важными способами, которые демонстрируют работу сетевых уровней.

Сначала попробуем выполнить ping до нового IP-адреса node2 (192.168.58.11) с node1.

docker exec node1 ping -c 4 192.168.58.11

Наблюдайте за выводом. Команда завершится по таймауту, что приведет к 100% потере пакетов.

PING 192.168.58.11 (192.168.58.11) 56(84) bytes of data.

--- 192.168.58.11 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3076ms

Этот таймаут происходит потому, что node1 все еще имеет маршрут к сети Docker, поэтому он отправляет пакет ping. Сеть перенаправляет его на node2. Однако, поскольку node2 больше не находится в этой сети и не имеет обратного маршрута, он не может отправить ответ. Ping с node1 никогда не получает ответа.

Далее протестируем другое направление. Попробуем выполнить ping до node1 с node2.

docker exec node2 ping -c 4 192.168.56.10

На этот раз вы почти сразу увидите другое сообщение об ошибке.

ping: connect: Network is unreachable

Сообщение ping: connect: Network is unreachable является значимым. Это немедленный ответ от операционной системы на node2. Это означает, что ОС проверила свою таблицу маршрутизации, увидела, что назначение 192.168.56.10 находится в сети, к которой у нее нет пути, и отказалась даже пытаться отправить пакет. Это прямой результат использования ip addr flush, который очистил все маршруты, полностью изолировав контейнер от других сетей.

Эта лабораторная работа успешно продемонстрировала критическую роль IP-подсетей и маршрутизации. Когда устройства находятся в одной подсети, они могут общаться напрямую. Когда они находятся в разных подсетях, для перенаправления трафика между ними требуется устройство уровня 3, такое как маршрутизатор с соответствующими маршрутами.

Резюме

В этой лабораторной работе вы научились моделировать сетевое окружение из двух узлов, используя контейнеры Docker, подключенные к пользовательской мостовой сети (bridge network). Вы отработали важный навык работы в Linux по настройке статических IP-адресов на сетевых интерфейсах с помощью команды ip addr. Назначив IP-адреса из одной подсети обоим узлам, вы успешно проверили прямую связность на уровне 3 (Layer 3) между ними с помощью утилиты ping, продемонстрировав фундаментальное требование для связи в сегменте локальной сети.

Лабораторная работа далее проиллюстрировала критически важную сетевую концепцию, перенастроив один узел с IP-адресом из другой подсети после полного сброса его исходной сетевой конфигурации. Последующие попытки связи через ping завершились двумя различными результатами: таймаутом в одном направлении и ошибкой «Destination Host Unreachable» (пункт назначения недоступен) в другом. Этот результат наглядно показал, что узлы в разных логических подсетях не могут общаться напрямую без маршрутизатора, и подчеркнул, как таблицы маршрутизации и конфигурация интерфейсов влияют на сетевую связность.