[Из песочницы] Пользовательские правила iptables для docker на примере zabbix

?v=1

Задача: Закрыть все входящие соединение, кроме определенных ip адресов.

Имеется тестовая среда, состоящий из linux и трех windows c статическими ip адресами. На linux установлен docker образами zabbix, redmine. А на двух windows машинах установлены и настроены агенты от zabbix, в одном только просмотр zabbix. Нужно ограничить пользователей от zabbix сервера.
Все команды выполняются от имени root.

В официальной документации говорится о правиле iptables DOCKER-USER. Следует только это правило менять. Сперва смотрим какие правила есть, акцентируем внимание только на некоторых правилах.

Видно, что в правиле FORWARD первым стоит правило с target DOCKER-USER. Поэтому следует только его изменить.

iptables -L FORWARD -n -v
Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
 421K  169M DOCKER-USER  all  --  *      *       0.0.0.0/0            0.0.0.0/0
 419K  167M DOCKER-ISOLATION-STAGE-1  all  --  *      *       0.0.0.0/0            0.0.0.0/0


Из таблицы правил DOCKER можно увидеть какие порты и открыты и внутренние ip адреса контейнеров.

iptables -L DOCKER -n -v
Chain DOCKER (4 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     tcp  --  !docker_redmine docker_redmine  0.0.0.0/0            172.16.237.2         tcp dpt:3000
    0     0 ACCEPT     udp  --  !br-c56432fe07cc br-c56432fe07cc  0.0.0.0/0            172.16.238.2         udp dpt:162
    0     0 ACCEPT     tcp  --  !br-c56432fe07cc br-c56432fe07cc  0.0.0.0/0            172.16.238.3         tcp dpt:10051
    0     0 ACCEPT     tcp  --  !br-c56432fe07cc br-c56432fe07cc  0.0.0.0/0            172.16.238.4         tcp dpt:443
    5   248 ACCEPT     tcp  --  !br-c56432fe07cc br-c56432fe07cc  0.0.0.0/0            172.16.238.4         tcp dpt:80


В правиле DOCKER-USER нет особенных правил, все соединение пропускает через себя.

iptables -L DOCKER-USER -n -v
Chain DOCKER-USER (1 references)
 pkts bytes target     prot opt in     out     source               destination
 4180 1634K RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0


Первую очередь разберемся с сетью zabbix, а именно установим постоянную имя сети. Чтоб при пересоздании docker-compose имя не сменился. Из нынешнего состояния сети zabbix имеет сеть под именем br-c56432fe07cc, что не очень хорошо, трудно запомнить. В файле *.yaml добавим одну строку отвечающее за имя сети zbx_net_frontend: «com.docker.network.bridge.name: «docker_zabbix».

Часть конфигурации:

networks:
  zbx_net_frontend:
    driver: bridge
    driver_opts:
      com.docker.network.enable_ipv6: "false"
      com.docker.network.bridge.name: "docker_zabbix"


После пересоздаем сеть. Следует заменить на вашу *.yaml.

docker-compose -f docker-compose_v3_ubuntu_mysql_latest.yaml down
docker-compose -f docker-compose_v3_ubuntu_mysql_latest.yaml up -d


Cмотрим правило DOCKER.

iptables -L DOCKER -n -v
Chain DOCKER (4 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     tcp  --  !docker_redmine docker_redmine  0.0.0.0/0            172.16.237.2         tcp dpt:3000
    0     0 ACCEPT     udp  --  !docker_zabbix docker_zabbix  0.0.0.0/0            172.16.238.2         udp dpt:162
    0     0 ACCEPT     tcp  --  !docker_zabbix docker_zabbix  0.0.0.0/0            172.16.238.3         tcp dpt:10051
    0     0 ACCEPT     tcp  --  !docker_zabbix docker_zabbix  0.0.0.0/0            172.16.238.4         tcp dpt:443
    5   252 ACCEPT     tcp  --  !docker_zabbix docker_zabbix  0.0.0.0/0            172.16.238.4         tcp dpt:80


Осталось добавить правило в таблицу DOCKER-USER. Первом делом ведем правило DROP для всех подключений в сеть docker_zabbix из внешнего интерфейса (у меня eth0).

iptables -I DOCKER-USER -i eth0 -o docker_zabbix -j DROP


Сейчас все соединение запрещены в сеть docker_zabbix. Разрешим соединение для одного ip адреса, точнее сказать пакет может продолжить путь дальше по FORWARD.

iptables -I DOCKER-USER -i eth0 -s 192.168.43.55 -j RETURN


Здесь явным образом не указали сеть docker_zabbix. Проверяем доступность zabbix от хоста 192.168.43.55 с помощью powershell.

tnc 192.168.43.136 -port 8081
ComputerName     : 192.168.43.136
RemoteAddress    : 192.168.43.136
RemotePort       : 8081
InterfaceAlias   : vEthernet (Swich_in)
SourceAddress    : 192.168.43.55
TcpTestSucceeded : True


8081 порт открыт для zabbix docker. Чтоб удостовериться в том, что zabbix принадлежит 8081 порт.

docker ps
CONTAINER ID        IMAGE                                             COMMAND                  CREATED             STATUS                       PORTS                                           NAMES
c047f18a4445        zabbix/zabbix-web-nginx-mysql:ubuntu-4.2-latest   "docker-entrypoint.sh"   About an hour ago   Up About an hour (healthy)   0.0.0.0:8081->80/tcp, 127.0.0.1:8443->443/tcp   zabbix_zabbix-web-nginx-mysql_1


Но следует учесть, что в правилах надо указывать порт 80, а не 8081. Если указать порт 8081, то не откроется доступ к zabbix. Для второго хоста команда.

iptables -I DOCKER-USER -i eth0 -p tcp --dport 80 -s 192.168.43.10 -j RETURN


Для треьего хоста откроем только порт 10051, на этом хосте используется активный агент.

iptables -I DOCKER-USER -i eth0 -p tcp --dport 10051 -s 192.168.43.13 -j RETURN


Еще одна проблема, не можем из контейнеров выйти в внешний мир. Не работают скрипты оповещение и не может проверить доступность сайтов. Осталось еще одна команда для разрешение уже имеющих соединений.

iptables -I DOCKER-USER -i eth0 -o docker_zabbix -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT


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

© Habrahabr.ru