Введение
Приложение заказов Corner Shop читает и создаёт записи в частной базе PostgreSQL. Страница работает, но Visitor тоже может обращаться к базе напрямую. Работа приложения сама по себе не доказывает безопасность сетевой границы.
Вы сравните реальные соединения, ограничите пересылку на подготовленном Gateway и сохраните заказы и публичный сервис состояния. Нужны только базовые навыки терминала. Люди и записи вымышлены. Три узла терминала — контейнеры с отдельными сетевыми пространствами имён и общим ядром одного экземпляра, а не независимые виртуальные машины.
Проследите заказ и его сетевой путь
На этом шаге вы создадите настоящий заказ и сравните два пути к базе. Приложение — программа для клиента, база — хранилище записей. Откройте Order Page, найдите seed: Green tea, введите practice-1 в Order reference и нажмите Create tea order. Новая строка сохраняется в PostgreSQL, а не просто отображается на странице.
Схема показывает IP-адрес каждого узла — идентификатор сетевого назначения. Порт определяет сервис по этому адресу. PostgreSQL слушает 172.28.20.10:5432, отдельный публичный сервис использует 8001. App Client (172.28.10.20) нужна база, Visitor (172.28.10.30) — только публичное состояние.
Перейдите в App Client. Подготовленная программа tcp-probe открывает реальное TCP-соединение и ждёт не более трёх секунд. Аргументы — адрес назначения и порт:
tcp-probe 172.28.20.10 5432
Ожидается TCP OPEN. Это доказывает достижимость, но не право чтения. psql — клиент запросов PostgreSQL. Команда передаёт учебный пароль только этой программе. Строка соединения в кавычках объединяет сервер, порт, пользователя, базу и трёхсекундный тайм-аут подключения. -c выполняет SQL в кавычках; SELECT читает указанные столбцы из orders, ORDER BY сортирует результат. Точка с запятой завершает SQL.
PGPASSWORD=training-only psql "host=172.28.20.10 port=5432 user=shopapp dbname=shop connect_timeout=3" -c "SELECT id, item FROM orders ORDER BY id;"
Найдите practice-1 и Green tea. Намеренно известные учебные реквизиты останутся прежними, чтобы отдельно наблюдать изменение сети.
Перейдите в Visitor и повторите обе команды:
tcp-probe 172.28.20.10 5432
PGPASSWORD=training-only psql "host=172.28.20.10 port=5432 user=shopapp dbname=shop connect_timeout=3" -c "SELECT id, item FROM orders ORDER BY id;"
Обе успешны: нежелательный клиент может подключаться и читать синтетические заказы. Неверный пароль дал бы ошибку аутентификации уже после достижения PostgreSQL; сетевой порт остался бы открытым.
Маршрут говорит узлу, куда отправлять пакеты. Посмотрите подготовленный маршрут Visitor к базе:
ip route get 172.28.20.10
Важны via 172.28.10.254 (Gateway) и src 172.28.10.30 (Visitor). App Client использует тот же шлюз с другим источником. Обратный маршрут базы указывает на второй интерфейс Gateway, 172.28.20.254. Ни у одного клиента нет интерфейса непосредственно в сети базы. Маршруты относятся к готовой инфраструктуре: не меняйте их. Результат шага проверяется по реальному заказу, отчёт не требуется.
Разрешите доступ к базе только приложению
На этом шаге вы отфильтруете пакеты, проходящие через Gateway. Перейдите в Gateway. iptables меняет правила пакетного фильтра ядра. Цепочка — упорядоченный список: действует первое совпавшее решение. FORWARD обрабатывает проходящий через узел трафик, INPUT — адресованный самому узлу. Среда соединяет FORWARD с учебной цепочкой LAB_FORWARD; её начальное разрешающее правило допускает лишний доступ.
Посмотрите правила. -n сохраняет числовые адреса, -v добавляет счётчики, -L выводит указанную цепочку:
iptables -nvL LAB_FORWARD
Меняйте только LAB_FORWARD в этом терминале. Сохраните правила хоста, маршруты, реквизиты и сервисы. Изменения действуют сразу и сохраняются в этой сессии. Заменим общее разрешение четырьмя решениями. Подготовленная родительская цепочка запрещает всё, что не совпало с правилами.
-F очищает указанную цепочку. Пересылаемые сервисы ненадолго блокируются, пока вы добавляете правила; терминал и интерфейс Order Page доступны. При опечатке снова выполните очистку и все четыре правила ниже.
iptables -F LAB_FORWARD
Ответы тоже должны возвращаться. Например, ответ базы идёт к App Client, и его назначением уже не является порт базы. -A добавляет правило в конец, -m conntrack использует отслеживание соединений, а --ctstate ESTABLISHED,RELATED определяет ответы и связанный трафик уже разрешённых соединений. -j ACCEPT пропускает совпавший пакет:
iptables -A LAB_FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Теперь разрешите новые соединения приложения. -s задаёт источник, -d назначение, -p tcp выбирает TCP, --dport — порт назначения. Один адрес означает именно этот узел:
iptables -A LAB_FORWARD -s 172.28.10.20 -d 172.28.20.10 -p tcp --dport 5432 -j ACCEPT
После исключения для приложения разместите общий запрет базы. Без -s он охватывает другие источники. REJECT --reject-with tcp-reset явно отвергает TCP-соединение, вместо того чтобы молча ждать тайм-аута:
iptables -A LAB_FORWARD -d 172.28.20.10 -p tcp --dport 5432 -j REJECT --reject-with tcp-reset
Наконец, сохраните отдельный публичный порт для обоих клиентов. Разрешение этого сервиса не открывает порт базы:
iptables -A LAB_FORWARD -d 172.28.20.10 -p tcp --dport 8001 -j ACCEPT
Выведите результат:
iptables -nvL LAB_FORWARD
Порядок: ответы, доступ приложения к базе, общий запрет базы, публичное состояние. Запрет выше исключения заблокировал бы и магазин. Счётчики растут, только когда соответствующий трафик действительно проходит Gateway; наличие правила не доказывает успех. Обновите Order Page: App Client должен показать OPEN, Visitor — BLOCKED, публичный сервис — PUBLIC STATUS OK, а заказы должны загружаться.
Повторно проверьте безопасность и магазин
На этом шаге вы проверите матрицу соединений и создадите ещё один реальный заказ. В App Client откройте новое соединение:
tcp-probe 172.28.20.10 5432
Ожидается TCP OPEN. Повторите чтение с прежними реквизитами:
PGPASSWORD=training-only psql "host=172.28.20.10 port=5432 user=shopapp dbname=shop connect_timeout=3" -c "SELECT id, item FROM orders ORDER BY id;"
Перейдите в Visitor:
tcp-probe 172.28.20.10 5432
Ожидаются TCP BLOCKED и пояснение об отказе подключения. Команда намеренно возвращает ошибку. Молчаливое отбрасывание вызовет тайм-аут; оба варианта мешают новому соединению, но один тайм-аут не устанавливает причину. Если App Client тоже не работает, проверьте порядок и обработку ответов в Gateway.
curl получает веб-ресурс. --max-time 4 ограничивает весь запрос четырьмя секундами; -f считает HTTP-ошибки неуспехом, -s скрывает прогресс, -S сохраняет сообщения об ошибках. Из Visitor проверьте другой публичный сервис:
curl --max-time 4 -fsS http://172.28.20.10:8001/status.txt
Ожидается PUBLIC STATUS OK. Блокировка всей пересылки нарушила бы это требование, даже закрыв путь к базе.
Откройте Order Page, создайте practice-2 и убедитесь, что видны оба учебных заказа. Это использует настоящее соединение приложения с базой после исправления. Обновите ещё раз: Visitor должен остаться заблокированным. Счётчики помогают искать расхождения, но реальное доказательство — успешный заказ и проверки разрешённых и запрещённых соединений. Не останавливайте PostgreSQL и не меняйте пароль, чтобы выдать сбой запроса посетителя за устранение сетевой проблемы.
Резюме
Вы проследили заказ до PostgreSQL, сравнили два маршрутизируемых клиента, применили упорядоченные правила пересылки и проверили безопасность и доступность. Ошибка пароля отличается от заблокированного TCP-соединения. Закрывая открытый путь к базе, сохраняйте законное приложение и остальные сервисы.



