LINUX.ORG.RU
решено ФорумAdmin

Suricata/Snort (NFQ) «теряют» второй входящий подряд DNS запрос на сервер.

 ,


0

1

Решил на выходных обстоятельно потыкать палочкой на своем наборе виртуальных серверов в Snort и Suricata (gentoo, qemu-kvm, сетевые virtio, все через статически прописанные tap-ы с бриджами), уж больно заинтересовало в каком они сейчас состоянии. Поставил на DNS сервер Snort, программа отлично работает — оповещает и блокирует, но обнаружилась какая-то аномальная работа в режиме NIPS (NFQ) — «пропадает» второй пакет приходящий на DNS сервер при последовательных запросах (A+AAAA) от клиента. Если запросы идут с достаточным интервалом для ответа DNS сервера, второй пакет с запросом проходит (не «теряется»). Выключил Snort, поставил на сервер Suricata, запустил как NIPS (тоже NFQ) и все повторилось 1 в 1 (все работает, фильтрует, пишет в логи алерты и блокирует... но второй пакет с DNS запросом опять заходит и «теряется» на уровне ядро-юзер спейс не доходя до DNS сервера). Думал, что их фильтрует как DNS флуд, только вот у той же Suricata стоит «request-flood: 500» по умолчанию, что «немного» больше чем 2, да и логи подозрительно молчат у обеих программ (хотя правила отрабатываются отлично, пишет в лог алерты).

Запустил wireshark и начал смотреть на сетевой интерфейс виртуального сервера:

  • При включенном на сервере NIPS (стоит и на входящие и на исходящие пакеты):
    15	0.091477407	192.168.64.4	192.168.64.1	DNS	73	Standard query 0x83c2 A ldap.corp.net
    16	0.091492929	192.168.64.4	192.168.64.1	DNS	73	Standard query 0x63f1 AAAA ldap.corp.net
    17	0.092691561	192.168.64.1	192.168.64.4	DNS	89	Standard query response 0x83c2 A ldap.corp.net A 192.168.64.3
    ...
    20	5.096090016	192.168.64.4	192.168.64.1	DNS	73	Standard query 0x83c2 A ldap.corp.net
    21	5.096631256	192.168.64.1	192.168.64.4	DNS	89	Standard query response 0x83c2 A ldap.corp.net A 192.168.64.3
    22	5.096737005	192.168.64.4	192.168.64.1	DNS	73	Standard query 0x63f1 AAAA ldap.corp.net
    23	5.098640900	192.168.64.1	192.168.64.4	DNS	73	Standard query response 0x63f1 AAAA ldap.corp.net
    

    Как видно, в первом блоке на DNS сервер из сети приходит два запроса, а уходит только один ответ, клиент ждет 5 секунд и отсылает повторный запрос, но с уже большим интервалом по времени между пакетами. DNS сервер в логах клятвенно заверяет, что второй пакет из первого блока (с AAAA запросом) к нему вообще не поступал. При повторном запросе от клиента через 5 секунд - временной интервал между запросами выше, и сервер успевает ответить на первый запрос (А) до поступления второго (AAAA). В логах DNS все это отображается аналогично информации полученной снифером. Если задать через iptables запись в лог (-j LOG до -j NFQUEUE) — пишет тоже самое, что ловлю на снифере, т. е. пакеты 100% заходят и идут до передачи в юзер спейс.

  • Если NIPS выключен:
    7	0.058400579	192.168.64.4	192.168.64.1	DNS	73	Standard query 0xb226 A ldap.corp.net
    8	0.058433208	192.168.64.4	192.168.64.1	DNS	73	Standard query 0xfa0b AAAA ldap.corp.net
    9	0.058548122	192.168.64.1	192.168.64.4	DNS	89	Standard query response 0xb226 A ldap.corp.net A 192.168.64.3
    10	0.058611081	192.168.64.1	192.168.64.4	DNS	73	Standard query response 0xfa0b AAAA ldap.corp.net
    

    Оба запроса проходят и DNS отвечает на них. В логах DNS все так и отображается.

  • Если сам сервер выступает в роли DNS клиента (например, при резолве yandex.ru) с включенным NIPS (стоит и на входящие и на исходящие пакеты):
    1	0.000000000	192.168.64.1	192.168.64.10	DNS	69	Standard query 0xabf7 A yandex.ru
    2	0.000018120	192.168.64.1	192.168.64.10	DNS	69	Standard query 0x70df AAAA yandex.ru
    ...
    5	0.003540832	192.168.64.10	192.168.64.1	DNS	133	Standard query response 0xabf7 A yandex.ru A 77.88.55.66 A 77.88.55.55 A 5.255.255.5 A 5.255.255.55
    6	0.003941852	192.168.64.10	192.168.64.1	DNS	97	Standard query response 0x70df AAAA yandex.ru AAAA 2a02:6b8:a::a
    

    Т. е. предположение, что NIPS не хватает временного интервала не подтвердилось, клиентские (исходящие) DNS запросы с такими же интервалами отлично обрабатывает.

Полностью убирал правила, собирал Suricata вообще с конфигурацией "--disable-detection", вносил udp 53 в исключения на Snort и выключал работу по dns вообще в Suricata, выключал все что можно, но даже «голые» Suricata и Snort ведут себя так же. Пока на входящем 53 udp сидит Suricata или Snort и обрабатывают nfq очередь, я ловлю этот нюанс со 100% вероятностью. Очередь nfqueue всегда около нулевая (судя по «cat /proc/net/netfilter/nfnetlink_queue»), нагрузки никакой нет 100%, плюс, fail open на обеих программах задействован. Логи на вопрос «где пакет?» молчат как партизаны на допросе.

Самое смешное, в статистике нет ни слова что пакет вообще был потерян или заблокирован:

  • как-то так для Snort:
    Packet I/O Totals:
    Received:         223
    Analyzed:         223 (100.000%)
    Dropped:            0 (  0.000%)
    Filtered:            0 (  0.000%)
    Outstanding:            0 (  0.000%)
    Injected:            0
  • вот так для Suricata:
    <Notice> - (Recv-Q1) Treated: Pkts 182, Bytes 43384, Errors 0
    <Notice> - (Recv-Q1) Verdict: Accepted 182, Dropped 0, Replaced 0

Идеи закончились... ощущение, что я не учитываю какую-то мелочь, но какую — понять не могу. Может, кто-то сталкивался с подобным?

★★

Последнее исправление: viewizard (всего исправлений: 1)

"-j TRACE" тебе в помощь.

А на хосте tcpdump запускал? Если ответ не приходит на хост, то и в виртуалке он тоже не появится.

Я бы начал с проверки iperf-ом скорости между виртуалкой и реальным хостом в локалке (в обе стороны). Низкая скорость будет говорить об адких потерях.

vel ★★★★★
()
Ответ на: комментарий от vel

А на хосте tcpdump запускал? Если ответ не приходит на хост, то и в виртуалке он тоже не появится.
Я бы начал с проверки iperf-ом скорости между виртуалкой и реальным хостом в локалке (в обе стороны). Низкая скорость будет говорить об адких потерях.

У меня запрос идет с одной виртуалки к другой (все через виртуальные интерфейсы, железо и реальная «локалка», тем более реальные хосты не задействованы вообще). Сами понимаете, отгребать еще и проблемы какого-то реалтека на реальном хосте (добавленного в бридж к виртуальным интерфейсам) в «тестовой песочнице» совсем желания нет. Все точно передается и принимается, трафик идет между виртуалками 100% без потерь, снифером (вместо tcpdump использую wireshark) с хоста смотрю непосредственно на виртуальный сетевой интерфес виртуального сервера.

"-j TRACE" тебе в помощь.

К сожалению, он показывает то что я и так уже знаю - все пакеты заходят, и их путь заканчивается на 12-м правиле (-j NFQUEUE для входящих на 53-й udp порт).

Собственно, проблема как раз в том, что я не могу проверить участок после помещение в nfqueue. Я только вижу уже по факту — на dnsmasq второй пакет не приходит.

viewizard ★★
() автор топика
Ответ на: комментарий от viewizard

можно собрать тест из libnetfilter_queue/examples/ nf-queue и запустить его вместо snort/surricata он все акцептит и печатает инфу о пакете.

Или посмотреть документацию/исходники на тему получения отладочной информации при работе NFQUEUE в snort/surricata.

Есть подозрение, что твой враг gro/gso, которые не обрабатываются должным образом.

А померить скорость между машинками не помешает....

vel ★★★★★
()
Ответ на: комментарий от vel

можно собрать тест из libnetfilter_queue/examples/ nf-queue и запустить его вместо snort/surricata он все акцептит и печатает инфу о пакете.
Или посмотреть документацию/исходники на тему получения отладочной информации при работе NFQUEUE в snort/surricata.
Есть подозрение, что твой враг gro/gso, которые не обрабатываются должным образом.

Спасибо, копну в эту сторону.

А померить скорость между машинками не помешает....

На всякий случай померил. Хост — компьютер 8-ми летней выдержки. Результаты примерно одинаковые получаются (попробовал разные направления ставить на 4 виртуалках):

[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-10.00  sec  2.59 GBytes  2.23 Gbits/sec    0             sender
[  4]   0.00-10.00  sec  2.59 GBytes  2.23 Gbits/sec                  receiver

viewizard ★★
() автор топика
Ответ на: комментарий от viewizard

Замечательно!

Попробуй отключить на машине со snort/surricata gro/gso/lro

«ethtool -K ethX gro off lro off»

Если не поможет, ковыряй суррикату/снорт

vel ★★★★★
()
Ответ на: комментарий от vel

Попробуй отключить на машине со snort/surricata gro/gso/lro

gro и gso выключил (были включены), на lro поругалось что не может изменить состояние, глянул — оно уже выключено с маркером [fixed]. К сожалению, не помогло.

Буду ковырять nfq очереди и NIPS-ы.

viewizard ★★
() автор топика

Собрал из пакета libnetfilter_queue утилиту nfqnl_test (libnetfilter_queue/utils/), в исходниках проверил, что nfq_set_verdict возвращать будет именно (и только) NF_ACCEPT, и запустил:

  • При первом резолве адреса, на 2 запроса (идущих с минимальным интервалом) возвращается 1 ответ через очередь:
    pkt received
    hw_protocol=0x0800 hook=1 id=3 hw_src_addr=08:00:57:ce:28:6c indev=2 payload_len=59 
    entering callback
    pkt received
    hw_protocol=0x0800 hook=1 id=4 hw_src_addr=08:00:57:ce:28:6c indev=2 payload_len=59 
    entering callback
    pkt received
    hw_protocol=0x0800 hook=3 id=5 outdev=2 payload_len=75 
    entering callback
    
  • Через 5 секунд, на повторные запросы (с большим интервалом между ними) через очередь проходит ответ на каждый запрос:
    pkt received
    hw_protocol=0x0800 hook=1 id=6 hw_src_addr=08:00:57:ce:28:6c indev=2 payload_len=59 
    entering callback
    pkt received
    hw_protocol=0x0800 hook=3 id=7 outdev=2 payload_len=75 
    entering callback
    pkt received
    hw_protocol=0x0800 hook=1 id=8 hw_src_addr=08:00:57:ce:28:6c indev=2 payload_len=59 
    entering callback
    pkt received
    hw_protocol=0x0800 hook=3 id=9 outdev=2 payload_len=59 
    entering callback
    

Т. е. получается, что проблема не в nfqueue и очередь 100% работает (соответственно, NIPS-ы не причем вообще), а вот уже выдача после обработки в юзер-спейсе не доходит до dnsmasq, или dnsmasq «не нравится» получаемое именно после очереди (без нее он работает отлично). Думаю попробовать другой DNS сервер, чтобы исключить кривую работу именно dnsmasq.

Если кто-то знает, как отслеживать/дебажить передачу пакетов в этом случае (выход из очереди - программа), буду признателен за любую информацию (не доводилось с таким пока сталкиваться).

viewizard ★★
() автор топика
Ответ на: комментарий от viewizard

Очень похоже на фичу batch_verdict, она появилась с ядра 3.1.

в сурикате для нее были патчи. Вошли ли они в официальную версию - не знаю.

vel ★★★★★
()
Ответ на: комментарий от vel

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

Да, они вошли. NFQ в рантайм режиме «workers» позволяет выставить «batchcount». Увы, это не мой случай.

Поставил bind вместо dnsmasq, ситуация не изменилась. После очередного поиска, наткнулся на тему в списке рассылки netfilter-devel — http://www.spinics.net/lists/netfilter-devel/msg27247.html Очень похоже на мой случай — conntrack, доли милисекунд между пакетами (виртуальные интерфейсы, никаких задержек при передачи) и второй пакет «пропадает» после успешного выхода из nfqueue-внешнего-обработчика с NF_ACCEPT.

Несколько напрягает сам факт, что уже после nfqueue и внешней программы-обработчика пакет может «затеряться» вернувшись в ядро только потому, что ядро что-то не успело доделать в своем потоке еще с первым пакетом.

Надо будет потом глянуть, как это все работает с таблицей raw и NOTRACK на пакетах, чтоб conntrack не лез к ним «помогать».

viewizard ★★
() автор топика
Ответ на: комментарий от viewizard

Зачетные грабли :) гм. проблема была известна 5 лет назад

NOTRACK - худший вариант. IMHO в raw/prerouting нужно все это делать.

vel ★★★★★
()
Ответ на: комментарий от vel

Зачетные грабли :) гм. проблема была известна 5 лет назад

Да, я сам удивился.

NOTRACK - худший вариант. IMHO в raw/prerouting нужно все это делать.

Согласен. Все протестировал, работает. Как итог (решение проблемы):

«Лучший» вариант — это работать с nfqueue еще на этапе PREROUTING/OUTPUT таблицы raw. Взял в кавычки слово лучший, потому как гнать на NIPS приходится и инвалидные пакеты со всяким мусором тоже (радует, что они хотя бы дефрагментированные на этом этапе). Мусор убираем уже на этапе работы с фильтрами (как обычно).

viewizard ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.