Привет, Хабр! Делюсь ниже статьей моего коллеги, Алексея Евсеева, который работает инженером технической поддержки в К2 Кибербезопасность в составе Центра экспертизы по комплексному сервису К2Тех и занимается администрированием средств защиты информации. Уже несколько лет он поддерживает Check Point в самых разных инсталляциях, от офисных шлюзов до крупных кластеров, и примерно раз в два-три месяца решает тикеты типа: «правило с доменом не работает», «сайт открывается через раз».

Свежий случай — месяц мучений из-за прерывистого доступа к одному крупному государственному сервису — сподвиг его написать отдельную статью про доменные объекты. Так что давайте разберемся, как устроены изнутри доменные объекты Check Point, чем FQDN отличается от non-FQDN, при чем тут DNS Passive Learning и почему штатная работа этих механизмов порой вызывает массу проблем на практике. Передаю слово Алексею.

Зачем вообще нужны доменные объекты

Все знают, что такое IP, но в современных инфраструктурах постоянный адрес — это уже, в общем-то, редкость. Облака, CDN, балансировщики постоянно меняют свои адреса, и писать правила доступа на конкретные IP в таких условиях — значит бесконечно их править и все равно наблюдать регулярные поломки.

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

В SmartConsole все выглядит просто: создаешь объект, вписываешь имя, (не)проставляешь галочку FQDN — и готово. Однако доменные объекты Check Point — это не очень прозрачный механизм, и чтобы разобраться, откуда берутся ошибки в его работе, нужно понять, что именно включает и выключает та самая галочка.

FQDN и с чем его едят

Включение FQDN переводит шлюз в режим работы, где он становится DNS-клиентом: берет имя из объекта и получает у DNS-сервера нужный адрес. Практически так же это работает в обычном браузере. В определенный интервал времени шлюз отправляет A-запрос по каждому FQDN-объекту на все настроенные DNS-серверы и складывает пары «имя → IP» в forward-кэш.

Когда пакет уходит на какой-то адрес, шлюз сверяется с кэшем: закреплен ли этот IP за доменом из правила? Если адрес среди закэшированных ответов, правило срабатывает, и трафик идет. Если сервис переехал на новый адрес, то шлюз подхватит его при следующем опросе, в пределах минуты.

Для FQDN имя пишется с точкой в начале: .www.example.com и, соответственно, сработает только для www.example.com. Но non-FQDN-объект совпадает не только с самим доменом, но и со всеми его поддоменами вплоть до 10 уровней. То есть .example.com покрывает www.example.com, ftp.example.com, mail.support.example.com и так далее. Это удобно, когда нужно разрешить ресурс целиком, не перечисляя многочисленные поддомены вручную.

При non-FQDN шлюз фиксирует, что пакет уходит на некий IP, и спрашивает у DNS: «Какое имя стоит за этим адресом?», — то есть делает обратный PTR-запрос. Затем шлюз сравнивает ответ с доменом объекта, и если домен совпал, пропускает трафик. Проверка происходит на каждом новом соединении, так что для работы non-FQDN нужно больше ресурсов, чем для FQDN. Updatable Objects, внутри которых находятся non-FQDN-домены, могут заметно просаживать производительность шлюза (sk162577): так бывает редко, но если есть тормоза — стоит проверить политику на такие объекты. А еще non-FQDN-объекты нельзя использовать в NAT-правилах. Для таких задач лучше смотреть в сторону прокси.

Однако если прямую A-запись своего домена контролирует владелец сервиса, то обратной зоной распоряжается тот, кому принадлежат IP-адреса, — обычно это хостер или провайдер. Завести уникальную PTR-запись на каждый адрес из своих диапазонов провайдер зачастую физически не может, поэтому ставит общие. И если общая PTR-запись меняется от запроса к запросу, поведение шлюза тоже меняется: сегодня обратка вернула example.com и запрос прошел, а завтра тот же IP называется cloud.example.net, и правило не срабатывает. За жалобами «то работает, то нет» почти всегда стоит именно non-FQDN.

Поэтому первым делом я рекомендую заказчикам включать FQDN, за исключением случаев, когда действительно нужны все поддомены разом и с обратными записями у ресурса точно полный порядок. Перевод объекта на FQDN, кстати, спокойно делается на живой системе, без окна обслуживания. Я обычно мигрирую в два этапа: сначала создаю новый FQDN-объект и ставлю его в правиле ниже старого с non-FQDN — трафик пока идет по-старому, а новый объект только собирает статистику. Убедившись по логам, что новые правила матчатся как надо, меняю правила местами и удаляю старый объект.

Что лежит в кэше, и кто им управляет

После установки политики шлюз создает в памяти несколько таблиц. Forward-кэш хранит пары «домен → IP» для FQDN-объектов. Reverse-кэш собирает результаты PTR-запросов для non-FQDN (dns_reverse_cache_tbl). Отдельно создается еще и dns_reverse_unmatched_cache: туда попадают IP-адреса, не совпавшие ни с одним доменным объектом политики.

Кроме того, существует таблица dns_reverse_domains_tbl. Она содержит список доменных имен из объектов политики, с которыми сравниваются результаты PTR. Иногда бывает полезно туда залезть и посмотреть, что шлюз пытался смэтчить, но не смог:

fw ctl multik print_bl dns_reverse_cache_tbl -u
fw ctl multik print_bl dns_reverse_unmatched_cache -u
fw ctl multik print_bl dns_reverse_domains_tbl -u

По умолчанию эти данные хранятся 60 минут, и TTL, выставленный DNS-сервером, на это значение не влияет. Лимит составляет 25 тысяч записей, и при заполнении кэша старые строки вытесняются. Кэш обновляется раз в минуту, и при поступлении трафика шлюз опрашивает все настроенные DNS-серверы по каждому FQDN-домену из политики. Управляет всем этим хозяйством отдельный демон — WSDNSD, который читает список DNS-серверов только при старте.

DNS Passive Learning

Минутный цикл опроса покрывает не все, поэтому с R80.40 в шлюзе по умолчанию работает DNS Passive Learning (DPL).

В этом режиме шлюз перестает полагаться только на собственные запросы и начинает анализировать DNS-трафик, который через него проходит. Клиент получил ответ «portal.company.ru = 1.2.3.4», а шлюз сохранил эту пару в свой кэш. Обновление происходит за миллисекунды вместо минуты, а DNS-серверы больше не получают от шлюза запрос на каждый домен раз в минуту. Это помогает отслеживать non-FQDN-объекты, Updatable Objects (в кэш попадают только реально запрашиваемые адреса) и домены с коротким TTL, расположенные за балансировщиками. Режим задается параметром ядра dns_data_src_enabled:

Значение

Что делает

0

DPL выключен

1

non-FQDN и Updatable Objects (значение по умолчанию с R80.40)

2

Только non-FQDN

3

Все типы: non-FQDN, FQDN, Updatable Objects

Третий режим включают, когда нужно, чтобы DPL обновлял и FQDN-объекты:

fw ctl set int dns_data_src_enabled 3        # на каждом узле кластера
fw ctl set -f int dns_data_src_enabled 3     # сохранить после перезагрузки
fw ctl get int dns_data_src_enabled          # проверить текущее значение

Важно помнить, что это значение должно совпадать на всех узлах кластера, а синхронизация кэшей между узлами появилась только с версии R81.10. Кроме того, у этого механизма есть одно естественное ограничение. Трафик, идущий в обход шлюза, подслушать не получится, и шлюз учитывает только ответы доверенных DNS-серверов, то есть явно известных ему. Чужие серверы приходится добавлять вручную через меню: Host-объект, в свойствах на вкладке Servers галочка DNS Server, установка политики. Вариант fw ctl set int dns_data_src_allow_all_dns 1 тоже существует, но он означает «верить всем DNS-ответам подряд» со всеми вытекающими рисками подделки ответов.

Месяц возни с одним доменом

Теперь, когда мы разобрали матчасть, расскажу кейс, в котором описанные механизмы создали массу неудобств нашему заказчику на пустом месте.

В начале весны заказчик завел тикет с жалобой на то, что не открывается rosstat.gov.ru. Трафик блокировался, хотя в политике было отдельное разрешающее правило (назначим ему № 31) с доменным объектом.

До обращения проблему «чинили» самыми разными способами: включали и отключали правила, меняли их порядок, создавали уточняющие, а иногда она проходила сама. В итоге заказчик создал более явное правило № 31, и доступ ожил. Вот только в логах трафик по-прежнему шел через старое правило № 30, а новое правило будто оставалось незамеченным. В тикете так и стояли два вопроса: почему доступ перестал работать при разрешающем правиле и почему заработал после добавления другого?

Заказчик попался из тех, кто хочет посмотреть и понять, как оно устроено под капотом, так что мы стали разбираться.

Просмотр логов дал первую зацепку: reject блокировал именно rosstat.gov.ru, а соединения к www.rosstat.gov.ru проходили. Объект в правиле находился в режиме non-FQDN, а значит, шлюз определял принадлежность адреса через обратный DNS. Вместо самого имени он резолвил PTR-запись для адреса назначения, что-нибудь вроде 60.89.226.194.in-addr.arpa.

Утилита domains_tool показала, что обратный запрос для проблемного адреса возвращал имя вида server-xxx.cloud-provider.net — то есть чужое имя из диапазона хостинг-провайдера. Шлюз честно сравнивал его с .rosstat.gov.ru, совпадения не находил и блокировал трафик. Обратные ответы менялись от запроса к запросу, время от времени имена все-таки совпадали — и сайт ненадолго оживал.

Самодиагностика шлюза, как выяснилось, все это время исправно сигналила: «Test Non-FQDN Objects finished with result WARNING» и «Domain Objects — DNS Passive Learning … WARNING».

Второе предупреждение и дало нам окончательное объяснение ситуации. Оказывается, пассивное обучение работало вполсилу, потому что в DNS-трафике встречались ответы от недоверенных серверов. Внутренние DNS-серверы заказчика форвардили запросы на провайдерские, а провайдерские были неизвестны шлюзу. DPL видел их ответы и отбрасывал.

Очевидное решение — перевести проблемные домены на FQDN-объекты, но оно здесь не подходило, так как перечислить все дочерние домены госресурсов фактически невозможно. Так что в итоге нам пришлось пометить провайдерские DNS-серверы как доверенные. В результате DPL начал принимать прямые ответы, кэш стал наполняться парами «домен → IP», и обратные запросы перестали быть единственным источником истины. На решение ушло несколько часов чистой работы инженера и всего два адреса в списке доверенных серверов.

Еще две доменные кулстори

Корпоративный портал периодически зависал на 30–50 секунд, а потом снова работал как ни в чем не бывало, и так по несколько раз в день.

Оказалось, что портал стоял за балансировщиком, который часто переключал IP между узлами. У записи в DNS был выставлен TTL в 30 секунд, чтобы клиенты быстро узнавали новый адрес, а вот шлюз переспрашивал DNS раз в минуту и после каждой смены адреса какое-то время продолжал слать трафик на старый.

Вылечилось это включением DNS Passive Learning для всех типов объектов: шлюз начал перехватывать DNS-ответы, которые получали компьютеры сотрудников, и стал обновлять кэш мгновенно. Доступ стал восстанавливаться за пару секунд, и жалобы прекратились. В другом запомнившемся мне случае заказчик сменил DNS-сервер в настройках Gaia: добавил новый и убрал старый, однако домены продолжили разрешаться по-старому, как будто никто ничего не менял.

Разгадка была в особенности WSDNSD, о которой я упоминал выше: демон читает список DNS-серверов только при старте, и он не мог подхватить изменения в /etc/resolv.conf на лету. Чтобы исправить ситуацию, потребовалось всего несколько команд для перезапуска демона:

cpwd_admin stop -name WSDNSD -path "$FWDIR/bin/wsdnsd" -command "fw kill wsdnsd"
cpwd_admin start -name WSDNSD -path "$FWDIR/bin/wsdnsd" -command "wsdnsd"
cpwd_admin list | grep WSDNSD   # статус E -- демон работает

Как узнать, что на уме у шлюза

Какие бы проблемы с доменными объектами Check Point мы ни разбирали, все сводится к тому, что на самом деле записано в памяти шлюза. Чтобы заглянуть туда, достаточно утилиты domains_tool и знания нескольких команд. Она доступна в Expert mode и работает только с IPv4. Как правило, расследование начинается с запроса «какие адреса у этого домена?». Если в ответе пусто, а объект в политике точно есть, то мы добавляем ключ -m: тогда тулза прочесывает весь кэш целиком — это медленнее, зато она ничего не пропустит.

domains_tool -d internal.corp
domains_tool -d internal.corp -m

Второй вопрос — обратный: «какому домену принадлежит этот адрес?». Он помогает, когда в логах всплыл подозрительный IP и нужно понять, к какому домену и объекту политики он привязан. domains_tool -ip 203.0.113.45

Бывает, зайти нужно со стороны объекта. domains_tool -o <домен> показывает, в каких объектах политики участвует домен. Когда доменов сразу несколько, на R82 и новее их перечисляют одной командой — domains_tool -md <домен1> <домен2>. Для NAT-сценариев адрес отдает domains_tool -dx <домен>, а проверить, работает ли WSDNSD, помогает domains_tool -hc.

Отдельная история — Updatable Objects. Чтобы увидеть, что там внутри, мы запрашиваем объект по имени:

domains_tool -uo "Office365 Worldwide Services"

Пустой вывод значит одно из двух: либо объект не используется в политике, либо он не обновился. Во втором случае полезно заглянуть в сами файлы — они лежат в $CPDIR/database/downloads/ONLINE_SERVICES.

Команда domains_tool -report прогоняет проверку политики и DNS:

Сообщение

Что случилось

Что делать

No Domain or Updatable or Network Feed object in policy

В политике нет доменных объектов

Убедиться, что объекты добавлены и политика установлена

Cannot access DNS servers

Шлюз вообще не может достучаться до DNS (nslookup тоже не работает)

Проверить настройки DNS в Gaia, сетевую доступность серверов и не блокирует ли шлюз сам себе DNS-трафик

WSDNSD and DNS servers are not synchronized

WSDNSD не резолвит, хотя nslookup работает

Перезапустить WSDNSD

Process WSDNSD is not running

Демон упал

Запустить: cpwd_admin start -name WSDNSD -path “$FWDIR/bin/wsdnsd” -command “wsdnsd”

You have Domain or Updatable Objects in policy but DNS Passive Learning (DPL) is disabled

DPL выключен при наличии доменных объектов

Включить DPL

Undefined DNS servers found

Шлюз видит DNS-запросы к серверу, который не отмечен доверенным

Добавить Host-объект с типом DNS Server или, осознавая риски, разрешить всех через dns_data_src_allow_all_dns 1

Здесь важно помнить, что ключ -extended запускает tcpdump на всех интерфейсах на 60 секунд и поэтому заметно нагружает CPU, так что стоит использовать его обдуманно и только по необходимости.

Чек-лист для быстрой диагностики

  1. Проверяем, что в кэше: domains_tool -d <проблемный домен>.

  2. Смотрим, к какому домену привязан IP из логов: domains_tool -ip <адрес>.

  3. Оцениваем состояние WSDNSD: domains_tool -hc и cpwd_admin list | grep WSDNSD.

  4. Снимаем общий отчет: domains_tool -report (при необходимости — с -extended).

  5. Проверяем режим пассивного обучения: fw ctl get int dns_data_src_enabled.

  6. Для non-FQDN-объектов заглядываем в fw ctl multik print_bl dns_reverse_unmatched_cache -u.

В большинстве кейсов из этой статьи диагноз ставился уже на первом-втором шаге.

Заключение, или незаметная машинерия

Итак, доменные объекты Check Point и настройки FQDN в SmartConsole — это всего лишь удобные абстракции, за которыми спрятаны прямой и обратный кэш со своим TTL, минутный таймер опроса, демон, который читает конфигурацию, пассивное обучение со списком доверенных серверов и чужие PTR-записи.

И когда правила в политике безопасности начинают капризничать, менять их порядок и плодить дубли бесполезно. На первом этапе так делают почти все, и почти всегда это лотерея. Куда проще узнать, что шлюз держит в кэше и какие имена он резолвит: domains_tool и пара служебных таблиц отвечают на этот вопрос за минуту. И стоит один раз разобраться в работе этих механизмов, как вы будете знать, куда смотреть, если что-то снова пойдет не так.

Дополнительные источники по теме:

  • sk120633 — как работают объекты Domain;

  • sk161612 — DNS Passive Learning;

  • sk161632 — утилита domains_tool;

  • sk90401 — дополнительная информация по работе с FQDN/non-FQDN-объектами.