tg-me.com/DevOPSitsec/1495
Last Update:
🌐 Задача-ловушка: Пропавший трафик после настройки iptables
Условие:
На сервере настроен простой iptables-фильтр для блокировки всего входящего трафика, кроме SSH:
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
После применения этих правил вы проверяете, что SSH соединения работают нормально (локально и удалённо). Сервер отвечает на пинги, всё ок.
На следующий день вы добавляете локальный контейнер (например, Docker), запускаете его с пробросом порта:
docker run -d -p 8080:80 nginx
❗ Проблема: Снаружи контейнер не доступен. В браузере или curl получаете
Connection refused
. Но в ss -tlnp
порт 8080 виден и слушает.Дополнительно, если выполнить:
curl http://localhost:8080
— сервер отвечает нормально. Но с других машин — нет.
❓ Вопрос:
Почему порт 8080 недоступен извне? В чём подвох с iptables? Как починить проблему?
🔍 Подсказка:
Docker использует nat таблицы и
PREROUTING`/`FORWARD
цепочки для проброса портов.✅ Разбор:
💥 Ловушка:
Ваш iptables-правила:
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
запрещают ВСЁ, кроме SSH. Вы думаете, что входящие соединения через Docker должны идти через
INPUT
, но это не так!Когда Docker пробрасывает порт с хоста (например, 8080), схема такая:
- Входящий пакет попадает в цепочку
PREROUTING (nat)
- Потом через
FORWARD
, если пакет не адресован хосту напрямую, а перенаправлен внутрь контейнераИ тут главная ловушка: даже если контейнер слушает порт на 0.0.0.0, Docker обрабатывает проброс трафика через FORWARD, а у вас политика по умолчанию:
iptables -P FORWARD DROP
Поэтому трафик до контейнера блокируется именно на этапе FORWARD.
🔧 Как проверить:
Запустить:
iptables -L -v -n
Вы увидите, что счётчик пакетов в
FORWARD
показывает дропы.🛠 Как починить:
Добавить правило разрешения проброса пакетов для Docker:
iptables -A FORWARD -o docker0 -j ACCEPT
Или (более строго):
iptables -A FORWARD -i eth0 -o docker0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i docker0 -o eth0 -j ACCEPT
✅ Вывод:
• В Linux iptables цепочки работают по строгой логике:
- INPUT — для пакетов к хосту
- FORWARD — для пакетов, которые переходят через хост (например, контейнеры или маршрутизаторы)
• Даже если кажется, что контейнер слушает на 0.0.0.0, проброс портов Docker работает через
FORWARD
, а не напрямую через INPUT
.💡 Бонус-вопрос:
Что изменится, если вы запустите контейнер с флагом
--network=host
? Какие цепочки будут задействованы тогда?BY DevOps
Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283
Share with your friend now:
tg-me.com/DevOPSitsec/1495