Статьи

Настройка сетевого фильтра firewalld в CentOS


До сравнительно недавнего времени администраторы Linux использовали для настройки сетевого фильтра Iptables.
Однако последний немного неудобен для использования, и разработчики начали придумывать более лояльные к пользователю продукты
Debian-системы обзавелись очень удобной системой UFW (лично мне она нравится больше всех).
Redhat-системы (в т.ч. CentOS и Fedora) разработали свою систему, firewalld.
Про неё и пойдёт речь в этой статье.
Существенное отличие firewalld от iptables в том, что тут используются зоны и службы (сервисы).
В зону firewalld могут входить интерфейсы, ip-адреса или подсети.
Службы — уже готовые именованные наборы портов. Примеры служб: http, ssh, ftp

Простота достигается за счёт добавления необходимых IP-адресов в нужную зону, а также добавления на зону правила открытия/закрытия сервиса (а если его не предопределено, то порта).


УСТАНОВКА И ЗАПУСК


В подавляющем большинстве случаев firewalld уже установлен в системе.
Если этого вдруг не оказалось, то установить его необходимо с помощью команды:

yum install firewalld

далее добавляем сервис в автозапуск при старте системы:

systemctl enable firewalld

и запускаем службу:

systemctl start firewalld


УПРАВЛЕНИЕ


Для управления firewalld используется консольная утилита firewall-cmd

Полное руководство по утилите можно найти на сайте производителя либо командами:

firewall-cmd --help
man firewall-cmd

Тут я опишу список самых часто используемых опций.

Посмотреть состояние сервиса:

firewall-cmd --state

Применить внесённые настройки:

firewall-cmd --reload

Посмотреть созданные правила:

firewall-cmd --list-all


УПРАВЛЕНИЕ ЗОНАМИ


Как я уже писал выше, для управления используются зоны. Посмотреть список всех зон можно командой:

firewall-cmd --get-zones

по умолчанию в системе используется 9 зон:
block dmz drop external home internal public trusted work

в подавляющем большинстве случаев для настройка хватает трёх зон:
public — зона по умолчанию, в ней прописываются правила доступа для всех адресов.
drop — зона, в которую заносятся нежелательные IP-адреса
trusted — зона, в которую заносятся IP-адреса, которые имеют доступ без ограничений.

по каждой из них можно посмотреть информацию и правила (в примере мы смотрим зону trusted):

firewall-cmd --list-all --zone=trusted

добавить адрес в зону:

firewall-cmd --permanent --zone=drop --add-source=8.8.8.8

Примечание: тут и далее при добавлении правила мы будем использовать опцию --permanent, которая сразу сохраняет правило. В противном случае после рестарта сервиса правило удалится.

удалить адрес из зоны:

firewall-cmd --permanent --zone=drop --remove-source=8.8.8.8

Примечание: один и тот же адрес не может быть в двух зонах. чтобы добавить его в другую зону, необходимо его удалить из той, в которой он находится.


УПРАВЛЕНИЕ СЛУЖБАМИ


Как я уже писал выше, очень удобно открывать не порт, а сразу всю службу. Для некоторых служб в системе прописано сразу несколько

Вывести список доступных служб:

firewall-cmd --get-services

Вывести информацию о конкретной службе. Пример информации о службе openvpn:

firewall-cmd --info-service openvpn

Создать собственную службу.
Вообще-то в firewalld по умолчанию прописаны очень большое количество служб. Закрыты почти все используемые службы.
Но бывает ситуация, когда мы вешаем службу на нестандартный порт. Или являемся разработчиками.
К примеру, мы разработали приложение с названием my_app, которое слушает порты 7856/TCP и 3878/UDP/
добавим его в список служб и привязываем необходимые порты:

firewall-cmd --permanent --new-service=my_app
firewall-cmd --permanent --service=my_app --add-port=7856/tcp
firewall-cmd --permanent --service=my_app --add-port=3878/udp

и применяем изменения:

firewall-cmd --reload

без выполнения последней команды правило не появится в системе. Далее в тексте эта команда будет уже без объяснения.


УПРАВЛЕНИЕ ПРАВИЛАМИ


тут мы научимся создавать правила доступа.

Примечание: ниже не указывается зона, в которую добавляется правило. в этом случае правило добавляется в зону по умолчанию (public, если она не была изменена руками). Правило можно применить для любой другой зоны. Для этого необходимо добавить в команду --zone=*имя зоны*


разрешить созданную нами выше службу:

firewall-cmd --permanent --add-service=my_app
firewall-cmd --reload

удалить службу из разрешённых:

firewall-cmd --permanent --remove-service=my_app
firewall-cmd --reload

разрешить порт:

firewall-cmd --permanent --add-port=6956/tcp
firewall-cmd --reload

удалить порт:

firewall-cmd --permanent --remove-port=6956/tcp
firewall-cmd --reload

проброс порта на другой порт на локальной машине:

firewall-cmd --add-forward-port=port=22 892:proto=tcp:toport=22
firewall-cmd --reload

настроить сеть NAT:

sudo firewall-cmd --add-masquerade
firewall-cmd --reload

после настройки NAT можно пробросить порт на другую машинку в сети:

firewall-cmd --add-forward-port=port=22 892:proto=tcp:toport=22:toaddr=172.21.0.7
firewall-cmd --reload


РАСШИРЕННЫЕ ПРАВИЛА


опция -rich-rule позволяет создавать правила с условиями.

Например, разрешаем службу http для подсети 172.20.0.0:

firewall-cmd --permanent --add-rich-rule 'rule family="ipv4" source address="172.20.0.0/24" service name="http" accept'

Или для конкретного порта:

firewall-cmd --permanent --add-rich-rule 'rule family="ipv4" source address="172.20.0.0/24" port port="3694" protocol="tcp" accept'

Список правил с условиями можно отобразить командой:

firewall-cmd --list-rich-rules


ВОЗМОЖНЫЕ ПРОБЛЕМЫ


Ошибка: "firewall-cmd: command not found"
Причина: не установлен пакет firewalld
Решение: установить пакет firewalld и запустить службу:
yum install firewalld
systemctl start firewalld



Проблема: Не применяются правила
Причина: не была применена новая конфигурация после внесения изменений.
Решение: применить конфигурацию:
firewall-cmd --reload



Ошибка при добавлении IP-адреса в зону: Error: ZONE_CONFLICT:
Причина: IP-адрес уже состоит в другой зоне.
Решение: сначала удалить адрес из зоны, в которой он состоит с помощью команды:
firewall-cmd --permanent --zone=*зона с IP* --remove-source=*IP*