Я настроил firewalld на CentOS7, чтобы он блокировал все исходящие соединения. Только необходимые соединения заносятся в белый список путем добавления некоторых правил. Также я добавил правила для включения регистрации заблокированных соединений (исходящее направление).
Текущие правила firewalld (некоторые IP-адреса, которые я маскирую с помощью «xxx»):
/> firewall-cmd --permanent --direct --get-all-rules
фильтр ipv4 ВЫВОД 1 -p udp -m udp --dport=53 -d 185.12.64.1 -j ПРИНЯТЬ
фильтр ipv4 ВЫВОД 1 -p udp -m udp --dport=53 -d 185.12.64.2 -j ПРИНЯТЬ
фильтр ipv4 ВЫВОД 1 -p udp -m owner --uid-owner root --dport 67:68 -j ПРИНЯТЬ
ipv4 filter ВЫВОД 1 -p icmp --icmp-type 8 -m state --state NEW,ESTABLIS -m owner -- uid-owner root -j ACCEPT
фильтр ipv4 ВЫВОД 1 -p tcp -m tcp --dport=25 -d 193.111.XXX.XXX -j ПРИНЯТЬ
фильтр ipv4 ВЫВОД 1 -p tcp --dport=58443 -d 10.254.XXX.XXX -j ПРИНЯТЬ
фильтр ipv4 ВЫВОД 1 -p tcp --dport=58443 -d 193.111.XXX.XXX -j ПРИНЯТЬ
фильтр ipv4 ВЫВОД 1 -p tcp --dport=5667 -d 10.254.XXX.XXX -j ПРИНЯТЬ
фильтр ipv4 ВЫВОД 1 -p udp -m udp --dport=1194 -d 193.111.XXX.XXX -j ПРИНЯТЬ
фильтр ipv4 ВЫВОД 1 -m owner --uid-owner root -p tcp -m tcp --dport=443 -j ПРИНЯТЬ
фильтр ipv4 ВЫВОД 1 -m owner --uid-owner root -p tcp -m tcp --dport=80 -j ПРИНЯТЬ
фильтр ipv4 ВЫВОД 0 -m состояние --state УСТАНОВЛЕНО, СВЯЗАННО -j ПРИНЯТЬ
фильтр ipv4 ВЫВОД 1 -m owner --uid-owner clamupdate -p tcp -m tcp --dport=443 -j ACCEPT
фильтр ipv4 ВЫХОД 2 -j DROP
фильтр ipv4 ВЫВОД 1 -j LOG_OUTPUT
фильтр ipv4 ВЫВОД 1 -m owner --uid-owner chrony -p udp -m udp --dport=123 -j ACCEPT
фильтр ipv6 ВЫВОД 1 -p udp -m owner --uid-owner root --dport 67:68 -j ПРИНЯТЬ
ipv6 filter ВЫВОД 1 -p icmpv6 --icmpv6-type 8 -m state --state NEW,ESTABLIS -m owner --uid-owner root -j ПРИНЯТЬ
фильтр ipv6 ВЫВОД 1 -p tcp -m tcp --dport=25 -d 2001:4ba0:XXXX:XX::X -j ПРИНЯТЬ
фильтр ipv6 ВЫВОД 1 -p tcp -m tcp --dport=58443 -d 2001:4ba0:XXXX:XX::X -j ПРИНЯТЬ
фильтр ipv6 ВЫВОД 1 -p tcp --dport=5667 -d fe80::bf18:c142:XXXX:XXXX -j ПРИНЯТЬ
фильтр ipv6 ВЫВОД 1 -p udp -m udp --dport=1194 -d 2001:4ba0:XXXX:XX::X -j ПРИНЯТЬ
фильтр ipv6 ВЫВОД 1 -m owner --uid-owner root -p tcp -m tcp --dport=443 -j ПРИНЯТЬ
фильтр ipv6 ВЫВОД 1 -m owner --uid-owner root -p tcp -m tcp --dport=80 -j ПРИНЯТЬ
фильтр ipv6 ВЫВОД 0 -m состояние --state УСТАНОВЛЕНО, СВЯЗАННО -j ПРИНЯТЬ
фильтр ipv6 ВЫВОД 1 -m owner --uid-owner clamupdate -p tcp -m tcp --dport=443 -j ACCEPT
фильтр ipv6 ВЫХОД 2 -j DROP
фильтр ipv6 ВЫВОД 1 -m owner --uid-owner chrony -p udp -m udp --dport=123 -j ACCEPT
фильтр ipv4 LOG_OUTPUT 1 -m limit --limit 3/мин --limit-burst 10 -j LOG --log-prefix 'FINAL_REJECT: '
Соответствующие правила iptable (кому-то больше нравится iptable как firewalld...):
/> iptables -S
-P ВВОД ПРИНЯТЬ
-P ВПЕРЕД ПРИНЯТЬ
-P ВЫВОД ПРИНЯТЬ
-N FORWARD_IN_ZONES
-N FORWARD_IN_ZONES_SOURCE
-N FORWARD_OUT_ZONES
-N FORWARD_OUT_ZONES_SOURCE
-N FORWARD_direct
-N FWDI_public
-N FWDI_public_allow
-N FWDI_public_deny
-N FWDI_public_log
-N FWDI_XXXX
-N FWDI_XXXX_разрешить
-N FWDI_XXXX_запретить
-N FWDI_XXXX_log
-N FWDO_public
-N FWDO_public_allow
-N FWDO_public_deny
-N FWDO_public_log
-N ФВДО_ХХХХ
-N FWDO_XXXX_разрешить
-N FWDO_XXXX_запретить
-N FWDO_XXXX_log
-N ВХОДНЫЕ_ЗОНЫ
-N INPUT_ZONES_SOURCE
-N ВХОД_прямой
-N IN_public
-N IN_public_allow
-N IN_public_deny
-N IN_public_log
-N IN_XXXX
-N IN_XXXX_разрешить
-N IN_XXXX_запретить
-N IN_XXXX_журнал
-N ЛОГ_ВЫХОД
-N ВЫХОД_прямой
-A ВВОД -i virbr0 -p udp -m udp --dport 53 -j ПРИНЯТЬ
-A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ПРИНЯТЬ
-A ВВОД -i virbr0 -p udp -m udp --dport 67 -j ПРИНЯТЬ
-A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ПРИНЯТЬ
-A ВВОД -m conntrack --ctstate СВЯЗАННО, УСТАНОВЛЕНО -j ПРИНЯТЬ
-A ВВОД -i lo -j ПРИНЯТЬ
-A ВХОД -j ВХОД_прямой
-A ВХОД -j INPUT_ZONES_SOURCE
-A ВХОД -j ВХОД_ЗОНЫ
-A INPUT -m conntrack --ctstate INVALID -j LOG --log-prefix "STATE_INVALID_DROP: "
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -j LOG --log-prefix "FINAL_REJECT: "
-A INPUT -j REJECT --reject-with-icmp-host-prohibited
-A FORWARD -d 192.168.122.0/24 -o virbr0 -m conntrack --ctstate СВЯЗАННО, УСТАНОВЛЕНО -j ПРИНЯТЬ
-A ВПЕРЕД -s 192.168.122.0/24 -i virbr0 -j ПРИНЯТЬ
-A ВПЕРЕД -i virbr0 -o virbr0 -j ПРИНЯТЬ
-A FORWARD -o virbr0 -j REJECT --reject-with-icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with-icmp-port-unreachable
-A FORWARD -m conntrack --ctstate СВЯЗАННО, УСТАНОВЛЕНО -j ПРИНЯТЬ
-A ВПЕРЕД -i lo -j ПРИНЯТЬ
-A FORWARD -j FORWARD_direct
-A FORWARD -j FORWARD_IN_ZONES_SOURCE
-A FORWARD -j FORWARD_IN_ZONES
-A FORWARD -j FORWARD_OUT_ZONES_SOURCE
-A FORWARD -j FORWARD_OUT_ZONES
-A FORWARD -m conntrack --ctstate INVALID -j LOG --log-prefix "STATE_INVALID_DROP: "
-A FORWARD -m conntrack --ctstate INVALID -j DROP
-A FORWARD -j LOG --log-prefix "FINAL_REJECT: "
-A FORWARD -j REJECT --reject-with-icmp-host-prohibited
-A ВЫВОД -o virbr0 -p udp -m udp --dport 68 -j ПРИНЯТЬ
-A ВЫВОД -o lo -j ПРИНЯТЬ
-A ВЫХОД -j ВЫХОД_прямой
-A FORWARD_IN_ZONES -i enp0s31f6 -g FWDI_public
-A FORWARD_IN_ZONES -i tun0 -g FWDI_XXXX
-A FORWARD_IN_ZONES -g FWDI_public
-A FORWARD_OUT_ZONES -o enp0s31f6 -g FWDO_public
-A FORWARD_OUT_ZONES -o tun0 -g FWDO_XXXX
-A FORWARD_OUT_ZONES -g FWDO_public
-A FWDI_public -j FWDI_public_log
-A FWDI_public -j FWDI_public_deny
-A FWDI_public -j FWDI_public_allow
-A FWDI_public -p icmp -j ПРИНЯТЬ
-A FWDI_XXXX -j FWDI_XXXX_log
-A FWDI_XXXX -j FWDI_XXXX_запретить
-A FWDI_XXXX -j FWDI_XXXX_разрешить
-A FWDI_XXXX -p icmp -j ПРИНЯТЬ
-A FWDO_public -j FWDO_public_log
-A FWDO_public -j FWDO_public_deny
-A FWDO_public -j FWDO_public_allow
-A FWDO_XXXX -j FWDO_XXXX_log
-A FWDO_XXXX -j FWDO_XXXX_deny
-A FWDO_XXXX -j FWDO_XXXX_разрешить
-A INPUT_ZONES -i enp0s31f6 -g IN_public
-A INPUT_ZONES -i tun0 -g IN_XXXX
-A INPUT_ZONES -g IN_public
-A INPUT_direct -p tcp -m set --match-set f2b-sshd src -j REJECT --reject-with-icmp-port-unreachable
-A INPUT_direct -p tcp -m set --match-set f2b-f2bLongList src -j REJECT --reject-with icmp-port-unreachable
-A INPUT_direct -p tcp -m set --match-set f2b-blocklist_de src -j REJECT --reject-with icmp-port-unreachable
-A IN_public -j IN_public_log
-A IN_public -j IN_public_deny
-A IN_public -j IN_public_allow
-A IN_public -p icmp -j ПРИНЯТЬ
-A IN_public_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate НОВЫЙ, НЕОТСЛЕЖИВАЕМЫЙ -j ПРИНЯТЬ
-A IN_public_allow -p tcp -m tcp --dport 443 -m conntrack --ctstate НОВЫЙ, НЕОТСЛЕЖИВАЕМЫЙ -j ПРИНЯТЬ
-A IN_public_allow -p tcp -m tcp --dport 80 -m conntrack --ctstate НОВЫЙ, НЕОТСЛЕЖИВАЕМЫЙ -j ПРИНЯТЬ
-A IN_public_allow -p tcp -m tcp --dport 58443 -m conntrack --ctstate НОВЫЙ, НЕОТСЛЕЖИВАЕМЫЙ -j ПРИНЯТЬ
-A IN_public_allow -p tcp -m tcp --dport 444 -m conntrack --ctstate НОВЫЙ, НЕОТСЛЕЖИВАЕМЫЙ -j ПРИНЯТЬ
-A IN_public_deny -m set --match-set badIPsSet src -j DROP
-A IN_XXXX -j IN_XXXX_log
-A IN_XXXX -j IN_XXXX_deny
-A IN_XXXX -j IN_XXXX_разрешить
-A IN_XXXX -p icmp -j ПРИНЯТЬ
-A IN_XXXX_allow -p tcp -m tcp --dport 59943 -m conntrack --ctstate НОВЫЙ, НЕОТСЛЕЖИВАЕМЫЙ -j ПРИНЯТЬ
-A IN_XXXX_allow -p tcp -m tcp --dport 9945 -m conntrack --ctstate НОВЫЙ, НЕОТСЛЕЖИВАЕМЫЙ -j ПРИНЯТЬ
-A IN_XXXX_allow -p tcp -m tcp --dport 9944 -m conntrack --ctstate НОВЫЙ, НЕОТСЛЕЖИВАЕМЫЙ -j ПРИНЯТЬ
-A IN_XXXX_allow -p tcp -m tcp --dport 9943 -m conntrack --ctstate НОВЫЙ, НЕОТСЛЕЖИВАЕМЫЙ -j ПРИНЯТЬ
-A IN_XXXX_allow -p tcp -m tcp --dport 9947 -m conntrack --ctstate НОВЫЙ, НЕОТСЛЕЖИВАЕМЫЙ -j ПРИНЯТЬ
-A LOG_OUTPUT -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "FINAL_REJECT: "
-A OUTPUT_direct -m состояние --state СВЯЗАННО, УСТАНОВЛЕНО -j ПРИНЯТЬ
-A OUTPUT_direct -d 185.12.64.1/32 -p udp -m udp --dport 53 -j ПРИНЯТЬ
-A OUTPUT_direct -d 185.12.64.2/32 -p udp -m udp --dport 53 -j ПРИНЯТЬ
-A OUTPUT_direct -p udp -m owner --uid-owner 0 -m udp --dport 67:68 -j ПРИНЯТЬ
-A OUTPUT_direct -p icmp -m icmp --icmp-type 8 -m состояние --state НОВЫЙ, УСТАНОВЛЕННЫЙ -m владелец --uid-владелец 0 -j ПРИНЯТЬ
-A OUTPUT_direct -d 193.111.XXX.XXX/32 -p TCP -m TCP --dport 25 -j ПРИНЯТЬ
-A OUTPUT_direct -d 10.254.XXX.XXX/32 -p TCP -m TCP --dport 58443 -j ПРИНЯТЬ
-A OUTPUT_direct -d 193.111.XXX.XXX/32 -p TCP -m TCP --dport 58443 -j ПРИНЯТЬ
-A OUTPUT_direct -d 10.254.XXX.XXX/32 -p TCP -m TCP --dport 5667 -j ПРИНЯТЬ
-A OUTPUT_direct -d 193.111.XXX.XXX/32 -p udp -m udp --dport 1194 -j ПРИНЯТЬ
-A OUTPUT_direct -p tcp -m owner --uid-owner 0 -m tcp --dport 443 -j ПРИНЯТЬ
-A OUTPUT_direct -p tcp -m owner --uid-owner 0 -m tcp --dport 80 -j ПРИНЯТЬ
-A OUTPUT_direct -p tcp -m owner --uid-owner 986 -m tcp --dport 443 -j ПРИНЯТЬ
-A OUTPUT_direct -j LOG_OUTPUT
-A OUTPUT_direct -p udp -m owner --uid-owner 993 -m udp --dport 123 -j ПРИНЯТЬ
-A OUTPUT_direct -j DROP
Порт UDP 123 (протокол NTP) открыт для исходящих соединений для пользователя «хрони». Если я вызываю chrony вручную из командной строки, я получаю:
/> chronyd -q 'сервер 178.63.52.31 iburst'
2022-03-07T09:09:45Z запуск chronyd версии 3.4 (+CMDMON +NTP +REFCLOCK +RTC +PRIVDROP +SCFILTER +SIGND +ASYNCDNS +SECHASH +IPV6 +DEBUG)
2022-03-07T09:09:45Z Начальная частота -13,925 частей на миллион
2022-03-07T09:09:49Z Системные часы ошиблись на 0,000131 секунды (шаг)
2022-03-07T09:09:49Z хронид уходит
Хорошо, кажется, что работает (как и ожидалось). Но брандмауэр регистрирует следующее:
7 марта 10:09:45 статическое ядро: FINAL_REJECT: IN= OUT=enp0s31f6 SRC=136.243.139.67 DST=178.63.52.31 LEN=76 TOS=0x00 PREC=0x00 TTL=64 ID=24554 DF PROTO=UDP SPT=55470 DPT =123 ЛЕН=56
7 марта 10:09:47 статическое ядро: FINAL_REJECT: IN= OUT=enp0s31f6 SRC=136.243.139.67 DST=178.63.52.31 LEN=76 TOS=0x00 PREC=0x00 TTL=64 ID=25563 DF PROTO=UDP SPT=48110 DPT =123 ЛЕН=56
7 марта 10:09:49 статическое ядро: FINAL_REJECT: IN= OUT=enp0s31f6 SRC=136.243.139.67 DST=178.63.52.31 LEN=76 TOS=0x00 PREC=0x00 TTL=64 ID=25796 DF PROTO=UDP SPT=46482 DPT =123 ЛЕН=56
Если убрать правила для порта "123":
/> firewall-cmd --permanent --direct --remove-rule ipv4 filter OUTPUT 1 -m owner --uid-owner chrony -p udp -m udp --dport=123 -j ACCEPT
успех
/> firewall-cmd --permanent --direct --remove-rule ipv6 filter OUTPUT 1 -m owner --uid-owner chrony -p udp -m udp --dport=123 -j ACCEPT
успех
/> брандмауэр-cmd --reload
успех
и снова вызовите chrony:
chronyd -q 'сервер 178.63.52.31 iburst'
2022-03-07T09:12:46Z запуск chronyd версии 3.4 (+CMDMON +NTP +REFCLOCK +RTC +PRIVDROP +SCFILTER +SIGND +ASYNCDNS +SECHASH +IPV6 +DEBUG)
2022-03-07T09:12:46Z Начальная частота -13,925 миллионных долей
2022-03-07T09:12:56Z Нет подходящего источника для синхронизации
2022-03-07T09:12:56Z хронид уходит
(что, как и ожидалось, не работает) Я получаю 6 строк в файле журнала брандмауэра (вместо 3 строк выше):
7 марта 10:12:46 статическое ядро: FINAL_REJECT: IN= OUT=enp0s31f6 SRC=136.243.139.67 DST=178.63.52.31 LEN=76 TOS=0x00 PREC=0x00 TTL=64 ID=30341 DF PROTO=UDP SPT=45581 DPT =123 ЛЕН=56
7 марта 10:12:48 статическое ядро: FINAL_REJECT: IN= OUT=enp0s31f6 SRC=136.243.139.67 DST=178.63.52.31 LEN=76 TOS=0x00 PREC=0x00 TTL=64 ID=32318 DF PROTO=UDP SPT=36395 DPT =123 ЛЕН=56
7 марта 10:12:50 статическое ядро: FINAL_REJECT: IN= OUT=enp0s31f6 SRC=136.243.139.67 DST=178.63.52.31 LEN=76 TOS=0x00 PREC=0x00 TTL=64 ID=33178 DF PROTO=UDP SPT=56503 DPT =123 ЛЕН=56
7 марта 10:12:52 статическое ядро: FINAL_REJECT: IN= OUT=enp0s31f6 SRC=136.243.139.67 DST=178.63.52.31 LEN=76 TOS=0x00 PREC=0x00 TTL=64 ID=34311 DF PROTO=UDP SPT=55691 DPT =123 ЛЕН=56
7 марта 10:12:54 статическое ядро: FINAL_REJECT: IN= OUT=enp0s31f6 SRC=136.243.139.67 DST=178.63.52.31 LEN=76 TOS=0x00 PREC=0x00 TTL=64 ID=35963 DF PROTO=UDP SPT=57795 DPT =123 ЛЕН=56
7 марта 10:12:56 статическое ядро: FINAL_REJECT: IN= OUT=enp0s31f6 SRC=136.243.139.67 DST=178.63.52.31 LEN=76 TOS=0x00 PREC=0x00 TTL=64 ID=37075 DF PROTO=UDP SPT=51338 DPT =123 ЛЕН=56
Такое поведение у меня только с NTP соединениями. Например, если я открываю SMTP-соединение через порт 25 к 193.111.xxx.xxx (что явно разрешено правилом брандмауэра), я не получаю (как и ожидалось) сообщения журнала брандмауэра.
Почему я получаю сообщения журнала брандмауэра о заблокированных соединениях через UDP-порт 123, когда порт явно разрешен и хрони работает так, как ожидалось?