Найдите и закройте нежелательный путь к базе данных

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

Введение

Приложение заказов 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-соединения. Закрывая открытый путь к базе, сохраняйте законное приложение и остальные сервисы.