Давайте дружить в Телеграме: рассказываем про новые фичи, общаемся в комментах, прислушиваемся к вашим идеям Подписаться

Настройка firewalld в CentOS

Команда Timeweb Cloud
Команда Timeweb Cloud
Наши инженеры, технические писатели, редакторы и маркетологи
29 апреля 2022 г.
1856
13 минут чтения
Средний рейтинг статьи: 5

New Documentation

Firewalld — инструмент управления фаерволом, предустановленный в большинстве RHEL-based дистрибутивов. В этой статье мы рассмотрим настройку брандмауэра с помощью firewalld на сервере под управлением CentOS, используя утилиту firewall-cmd

Настройка Firewalld В Cent Os (1)

Назначение брандмауэра

Межсетевой экран (брандмауэр/фаервол) — это программа для обеспечения контроля доступа на сетевом уровне. Основываясь на прописанных правилах, брандмауэр определяет, какие устройства имеют доступ к участкам сети. Иными словами, какой-то трафик разрешить, остальное заблокировать. В Linux эти функции выполняет программа netfilter, встроенная в ядро.

Брандмауэр в Linux

Как мы уже поняли, netfilter работает на уровне ядра. Для настройки фаервола нужны инструменты в пользовательском пространстве. В качестве фреймворков для управления netfilter используются ip_tables/nf_tables, реализованные в виде модулей ядра. А поверх них на уровне пользователя работают соответственно или iptables (одноименная утилита командной строки), или nft.

Опытные администраторы знают, что вручную прописывать правила для iptables или nft не так просто. Особенно, когда нужно настроить крупную сеть или перенести правила на другую систему. Поэтому были придуманы более дружелюбные и многофункциональные надстройки. Например, в Ubuntu такой надстройкой является инструмент с говорящим названием ufw (Uncomplicated Firewall). А в семействе RedHat дистрибутивов (CentOS, Alma, Fedora, RHEL, OpenSUSE, SUSE Linux Enterprise) — firewalld.

Основы работы

Для управления firewalld существует две программы: firewall-cmd для работы в терминале и графический firewall-config. В данной статье мы будем работать с firewalld в CentOS и использовать firewall-cmd.

Арендовать собственный сервер для тестирования и экспериментов можно здесь

Установка

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

sudo systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2022-04-28 11:11:29 MSK; 2min 24s ago
     Docs: man:firewalld(1)
 Main PID: 484 (firewalld)
   CGroup: /system.slice/firewalld.service
           └─484 /usr/bin/python2 -Es /usr/sbin/firewalld --nofork --nopid

В RHEL-based дистрибутивах firewalld предустановлен, однако никто не мешает поставить его вручную на вашем любимом дистрибутиве. Просто скачайте пакет и запустите сервис. Например, в Ubuntu это делается так:

sudo apt install firewalld
sudo systemctl enable firewalld --now

Только не забудьте отключить ufw — использовать одновременно два фронтенда для iptables/nftables не рекомендуется.

Активные правила

Узнаем активные правила (что разрешено и запрещено, к чему относится разрешения и т.д.):

sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources: 
  services: dhcpv6-client ssh
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules:

Заметьте, что нам необходимы привилегии суперпользователя, поэтому залогиньтесь от рута, либо используйте sudo/su.

В выводе команды мы видим много различных параметров. Разберем их по порядку.

Настройка портов

Поле ports в выводе предыдущей команды показывает порты, по которым разрешено соединение. Продемонстрируем настройку на примере: поменяем прослушиваемый порт демона OpenSSH с 22-го на 3333-й (файл /etc/ssh/sshd_config):

Port 3333
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
sudo systemctl restart sshd

Выведем порты, прослушиваемые sshd:

sudo ss -nl4p | grep sshd
tcp    LISTEN     0      128       *:3333                  *:*                  users:(("sshd",pid=7602,fd=3))

Видим, что теперь прослушивается порт 3333. Текущий сеанс не прервался, но если попробуем заново подключиться по стандартному или новому порту, то ничего не получится:

ssh user1@37.46.131.83
ssh: connect to host 37.46.131.83 port 22: Connection refused
ssh user1@37.46.131.83 -p 3333
ssh: connect to host 37.46.131.83 port 3333: No route to host

Необходимо добавить разрешающее правило в firewalld, позволяющее подключаться по 3333/tcp:

sudo firewall-cmd --add-port=3333/tcp

или

sudo firewall-cmd --add-port=3333/tcp --permanent
sudo firewall-cmd --reload

В первом случае изменения активно только в текущем runtime, и при перезапуске машины или сервиса все сбрасывается. Во втором случае изменение делается постоянным. Ключ --permanent указывает, что меняются настройки, а не рантайм, поэтому нужно перезапустить фаервол (опция --reload).

Проверим, какие порты теперь разрешены:

sudo firewall-cmd --list-ports
3333/tcp

Теперь все работает:

ssh user1@37.46.131.83 -p 3333
user1@37.46.131.83's password: 
Last login: Thu Apr 28 11:13:39 2022

Внимательный читатель задастся вопросом, как мы могли подключаться по SSH раньше, ведь вначале поле ports в выводе политик было пустым. Дело в том, что настройки были заданы с помощью описания сервисов.

Настройка сервисов

Сервисы в firewalld представляют собой описания служб, делающие настройку более удобной и централизованной. Посмотрим текущие сервисы и информацию о них:

sudo firewall-cmd --list-services
dhcpv6-client ssh
sudo firewall-cmd --info-service=ssh
ssh
  ports: 22/tcp
  protocols: 
  source-ports: 
  modules: 
  destination:

Заметим, что в SSH все также 22-й порт. Дело в том, что собственные параметры демонов никак не связаны с их описаниями в firewalld. Попробуем убрать стандартный порт и добавить 3333-й в описание сервиса ssh (не забудем удалить порт 3333/tcp из политик):

sudo firewall-cmd --service=ssh --remove-port=22/tcp --permanent
sudo firewall-cmd --remove-port=3333/tcp --permanent
sudo firewall-cmd --service=ssh --add-port=3333/tcp --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --info-service=ssh
ssh
  ports: 3333/tcp
  protocols: 
  source-ports: 
  modules: 
  destination:    

Попробуем удалить и добавить какой-нибудь сервис:

sudo firewall-cmd --list-services
dhcpv6-client ssh
sudo firewall-cmd --remove-service=dhcpv6-client
sudo firewall-cmd --add-service=mysql
sudo firewall-cmd --runtime-to-permanent

sudo firewall-cmd --list-services
mysql ssh

Опция --runtime-to-permanent делаем рантайм постоянными — можно не указывать --permanent после каждой команды, а выполнить набор команд и только после этого сделать настройки постоянными (не всегда работает, так как некоторые команды требуют ключ --permanent).

Файлы с предопределенными сервисами расположены по пути /lib/firewalld/services. Выведем их список:

sudo firewall-cmd --get-services
RH-Satellite-6 RH-Satellite-6-capsule amanda-client amanda-k5-client amqp amqps apcupsd audit bacula bacula-client bgp bitcoin bitcoin-rpc bitcoin-testnet bitcoin-testnet-rpc ceph ceph-mon cfengine condor-collector ctdb dhcp dhcpv6 dhcpv6-client distcc dns docker-registry docker-swarm dropbox-lansync elasticsearch etcd-client etcd-server finger freeipa-ldap freeipa-ldaps freeipa-replication freeipa-trust ftp ganglia-client ganglia-master git gre high-availability http https imap imaps ipp ipp-client ipsec irc ircs iscsi-target isns jenkins kadmin kerberos kibana klogin kpasswd kprop kshell ldap ldaps libvirt libvirt-tls lightning-network llmnr managesieve matrix mdns minidlna mongodb mosh mountd mqtt mqtt-tls ms-wbt mssql murmur mysql nfs nfs3 nmea-0183 nrpe ntp nut openvpn ovirt-imageio ovirt-storageconsole ovirt-vmconsole plex pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy proxy-dhcp ptp pulseaudio puppetmaster quassel radius redis rpc-bind rsh rsyncd rtsp salt-master samba samba-client samba-dc sane sip sips slp smtp smtp-submission smtps snmp snmptrap spideroak-lansync squid ssh steam-streaming svdrp svn syncthing syncthing-gui synergy syslog syslog-tls telnet tftp tftp-client tinc tor-socks transmission-client upnp-client vdsm vnc-server wbem-http wbem-https wsman wsmans xdmcp xmpp-bosh xmpp-client xmpp-local xmpp-server zabbix-agent zabbix-server

Вы можете создавать собственные сервисы. Для этого создайте файл в формате xml в директории /etc/firewalld/services. Для удобства можно скопировать какой-нибудь конфиг из /etc/firewalld/services и внести соответствующие изменения. После перезапустите фаервол ключом --reload.

ICMP, протоколы и таргеты

В выводе --list-all есть следующие любопытные поля:

sudo firewall-cmd --list-all | grep -E '(target|icmp|protocols)'
 target: default
 icmp-block-inversion: no
 protocols: 
 icmp-blocks:

В firewalld можно настраивать не только сервисы и порты, но и протоколы. Допустим, мы настраиваем фаервол на маршрутизаторе. Тогда имеет смысл указать перечень разрешенных протоколов. Для иллюстрации разрешим протокол динамической маршрутизации OSPF:

sudo firewall-cmd --add-protocol=ospf
sudo firewall-cmd --list-protocols
ospf

Поля icmp-blocks и icmp-blocks-inversion содержат параметры для протокола ICMP. Его функции — тестирование сети и оповещение об ошибках. Программы ping и traceroute используют его в своей работе.

С помощью icmp-blocks можно заблокировать определенные ICMP-сообщения. Icmp-blocks-inversion делает инверсию логики — перечисленные типы сообщений становятся разрешенными, остальные блокируются. Такой функционал можно использовать, чтобы скрыть информацию о сети, так как многие механизмы сканирования используют ICMP. Давайте протестируем блокировку с помощью утилиты ping.

Запрещаем все типы ICMP-сообщений (так как в icmp-block ничего не перечислено, все сообщения становятся запрещенными):

sudo firewall-cmd --add-icmp-block-inversion

Теперь попробуем пропинговать сервер:

ping -c 3 37.46.131.83
PING 37.46.131.83 (37.46.131.83) 56(84) bytes of data.
From 37.46.131.83 icmp_seq=1 Destination Host Prohibited
From 37.46.131.83 icmp_seq=2 Destination Host Prohibited
From 37.46.131.83 icmp_seq=3 Destination Host Prohibited

--- 37.46.131.83 ping statistics ---
3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2004ms

Машина не пингуется. Такой метод часто используют провайдеры, чтобы скрыть адреса маршрутизаторов. Однако по ошибкам понятно, что на целевых устройствах пакеты фильтруются брандмауэром. Чтобы скрыть компьютер, нужно использовать таргеты.

Таргет — это действие, которое необходимо сделать с пакетом, если сработало какое-то из правил. Наиболее используемые: DROP, ACCEPT, REJECT. В примере выше таргетом был REJECT, т.е. возвращалась причина ошибки. Чтобы выбросить пакет, ничего не отправляя, нужно использовать DROP:

sudo firewall-cmd --set-target=DROP --permanent
sudo firewall-cmd --reload

Снова пропингуем сервер:

ping -c 3 37.46.131.83
PING 37.46.131.83 (37.46.131.83) 56(84) bytes of data.
^C
--- 37.46.131.83 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2050ms

Зоны

При работе с firewalld часто используются зоны. На машине может иметься несколько интерфейсов. Допустим, один из них «смотрит» в интернет, другой — в LAN, третий — в dmz. Разные сети имеют разный уровень доверия, соответственно, поступающий из них трафик должен контролироваться различными правилами брандмауэра. Для этого в firewalld используются зоны — наборы правил, применяемых к различным фрагментам сети. 

Все действия выше мы применяли для зоны public (по умолчанию):

sudo firewall-cmd --get-default-zone
public

В firewalld изначально прописаны несколько зон. Однако можно создавать и свои зоны. Выведем список имеющихся зон:

sudo firewall-cmd --get-zones
block dmz drop external home internal public trusted work

Опция --zone позволяет устанавливать и смотреть правила для конкретной зоны (без него, все применяется к зоне по умолчанию). Посмотрим политики для зоны drop:

sudo firewall-cmd --list-all --zone=drop
drop
  target: DROP
  icmp-block-inversion: no
  interfaces: 
  sources: 
  services: 
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules:

В нашем случае единственный интерфейс eth0, через который осуществляется доступ в интернет, смотрит в зону public. Значит для входящего трафика применяются политики зоны public. Для добавления интерфейса в другую зону используется ключ --change-interface. Переместим наш eth0 в зону home:

sudo firewall-cmd --change-interface=eth0 --zone=home
sudo firewall-cmd --list-interfaces --zone=home
eth0

Может возникнуть задача, когда необходимо настроить правила не для всего входящего на интерфейс трафика, а для конкретного адреса. Делается это так:

sudo firewall-cmd --zone=drop --add-source=192.168.3.1
sudo firewall-cmd --zone=drop --list-all
drop (active)
  target: DROP
  icmp-block-inversion: no
  interfaces: 
  sources: 192.168.3.1
  services: 
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

Теперь, даже если пакеты с адреса 192.168.3.1 придут на интерфейс eth0, то будут применяться правила не для зоны, в которой расположен интерфейс, а для заданной нами вручную зоны (drop). 

Настройка NAT

NAT — это технология трансляции интернет-адресов. Существует два вида NAT — source и destination. В первом случае маршрутизатор подменяет домашние IP-адреса на свой внешний, т.е. изменяется адрес отправителя (отсюда и название source). В Linux это называется маскарадингом (masquerade). Во втором случае заменяется адрес получателя (проброс портов). Например, на порт маршрутизатора приходит пакет, а роутер пересылается пакет на какой-нибудь другой порт.

Допустим, имеется задача настроить фаервол на роутере. Разрешим source nat:

sudo firewall-cmd --add-masquerade
sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources: 
  services: mysql ssh
  ports: 
  protocols: 
  masquerade: yes
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

Проброс портов на машине:

sudo firewall-cmd --add-forward-port=port=3333:proto=tcp:toport=22
sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources: 
  services: mysql ssh
  ports: 
  protocols: 
  masquerade: yes
  forward-ports: port=3333:proto=tcp:toport=22:toaddr=
  source-ports: 
  icmp-blocks: 
  rich rules:

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

Rich rules

Мы разобрали, как в firewalld использовать разные правила к разным областям сети (интерфейсы, IP адреса). Но иногда возникает задача создания точечных правил: разрешить подключение с конкретного адреса на конкретный порт, используя такие-то протоколы и т.д. Конечно, можно создать собственную зону, однако лучше использовать rich-rules. 

У rich-rules в firewall centos отдельный синтаксис, подробности можно посмотреть в манах:

man firewalld.richlanguage

Image1

Там же есть множество примеров:

Image2

Добавить вручную прописанное правило:

sudo firewall-cmd --add-rich-rule=’правило’

Заключение

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

Зарегистрируйтесь и начните пользоваться
сервисами Timeweb Cloud прямо сейчас

15 лет опыта
Сосредоточьтесь на своей работе: об остальном позаботимся мы
165 000 клиентов
Нам доверяют частные лица и компании, от небольших фирм до корпораций
Поддержка 24/7
100+ специалистов поддержки, готовых помочь в чате, тикете и по телефону