iptables Linux или нужно писать скрипты?
У меня есть сервера, которые находятся в приватной сети: 10.17.0.0/16. Я решил разбить эту сеть по 18-ой маске. 10.17.0.0/18 -- ПРОД сервера. В этой подсети машины общаются друг с другом без ограничений.
Остальные диапазоны (10.17.64.0/18, 10.17.128.0.0/18...) не могут обращаться на эти сервера.
Практически все приложения у меня крутятся в docker. Я настроил правила фаервола (iptables) для INPUT и OUTPUT и в целом все работает. Однако у меня возникает следующая проблема:
Докер при старте добавляет собственные правила в цепочку FORWARD. Эти правила разрешают проход любого трафика внутрь приватной сети docker. Таким образом все машины из всех подсетей могут обращаться к моим приложениям (стоит добавить, что у каждой машины есть белый IP).
Я добавил в цепочку FORWARD правило (на 1 место):
iptables -I FORWARD 1 ! -s 10.17.0.0/18 -m conntrack --ctstate NEW -j DROP
И в целом это работает. Я сохраняю правила (service netfilter-persistent save
) и перезапускаю машину. И после подключения вижу следующее:
DOCKER-USER all -- anywhere anywhere
DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
DROP all -- !10.17.0.0/18 anywhere ctstate NEW
То есть мое правило сдвинулось вниз и теперь не работает нормально! Я сделал небольшую хитрость: Я добавил в /etc/bash.bashrc команду выше и теперь правило добавляется правильно. Но это ужасный костыль, совсем не расширяемо и не похоже на гуд-практик (теперь при каждом подключении к машине добавляется это правило и что если я захочу добавить пару специфичных правил?..)
Прошу, подскажите в какую сторону смотреть, что изучить, чтобы избежать написания скриптов в bash и чтобы мои правила были приоритетнее правил докера..
--- UPDATED ---
У меня есть контейнер Kafka (с Kraft). Я добавил следующие правила в DOCKER-USER:
iptables -I DOCKER-USER 1 -s 10.17.64.0/18 -j RETURN
iptables -I DOCKER-USER 2 -s 172.0.0.0/8 -j RETURN
iptables -I DOCKER-USER 3 -j DROP
Эти правила я добавляю на сервер с контейнером Kafka.
Я использую 10.17.64.0/18
потому что экспериментирую в другом контуре.
Когда я добавляю эти правила соединение с моим kafka из приложения (на другом хосте в той же подсети(10.17.64.0/18
)) не работает...
P.S.
Я использую чистые правила iptables с docker. Из всех моих изменений в этом контуре только те, что написал выше
P.S.S.
Примечательно то, что в остальном это работает. Я поднимаю контейнер nginx и доступ к нему есть только из приватной сети, попытка обращения через ext-ip обрывается с таймаут. Но именно kafka с этими правилами перестает работать:(
Ответы (2 шт):
Пока что решил проблему следующим образом:
Сделал файл скрипта, в котором очищаю правила
INPUT
иOUTPUT
.FORWARD
не трогаю (так как docker должен будет положить свои правила):#!/bin/bash iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT # FLUSH OUTPUT and INPUT iptables -F INPUT iptables -F OUTPUT # INPUT iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT iptables -A INPUT -s 10.17.0.0/18 -j ACCEPT # FORWARD iptables -I FORWARD 1 -s 172.0.0.0/8 -j ACCEPT iptables -I FORWARD 2 -s 172.0.0.0/8 -d 172.0.0.0/8 -j ACCEPT iptables -I FORWARD 3 ! -s 10.17.0.0/18 -j DROP iptables -P INPUT DROP
Далее добавил файл сервиса, который будет запускать этот скрипт после
docker.service
(WantedBy
для активации скрипта)[Install] WantedBy=multi-user.target [Unit] Description=Settings Iptables Rules After=docker.service [Service] Type=oneshot ExecStart={{ iptables_script_file }}
Закинул это в
ENV
для скрипта и Ansible-плейбуком раскатываю:--- - name: Setting Firewall hosts: dmz become: true gather_facts: false pre_tasks: - name: Include Settings include_vars: "{{ playbook_dir }}/secrets/dmz-firewall.yml" tags: - always tasks: - name: Create directory for script file: path: "{{ iptables_script_dir }}" state: directory - name: Save Script From Variable shell: "echo '{{ iptables_script }}' > {{ iptables_script_file }}" - name: Set script as Executable file: path: "{{ iptables_script_file }}" mode: 0550 - name: Create directory for service file: path: "{{ iptables_service_dir }}" state: directory - name: Save Service From Variable shell: "echo '{{ iptables_service }}' > {{ iptables_service_file }}" - name: Systemd Daemon Reload systemd_service: daemon_reload: true - name: Enable and Restart Service systemd_service: name: "{{ iptables_service_filename }}" enabled: true state: restarted
P.S. Добавляю это сюда, чтобы может быть помочь кому-то.
P.P.S. Не уверяю в 100%-ой правильности, у меня сделано так, и это работает.
Если у кого-то есть решение лучше, прошу, дайте другой ответ.
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A FORWARD -o br-9373f0a8d417 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o br-9373f0a8d417 -j DOCKER
-A FORWARD -i br-9373f0a8d417 ! -o br-9373f0a8d417 -j ACCEPT
-A FORWARD -i br-9373f0a8d417 -o br-9373f0a8d417 -j ACCEPT
-A DOCKER-USER -j RETURN
Выша проблема надуманна. Вот стандартные правили докера. В них разрешается выход наружу, общение внутри бриджа между сервисами. Добавить ПОСЛЕ правил для запретов достаточно. Разрешений заходить внутрь тут не вижу.
Если хотите добавить правила спереди, то добавьте эти правила в цепочку DOCKER-USER
. Она выполнится перед этими ацептами. Докер не перетирает эту цепочку при рестарте.
Используй команду iptables-save
- в ней видно что происходит. Вместе с iptables-restore
эти команды удобны для хранения и накатывания "своих" правил.