|
Май 31, 2007
07:26 pm - Фильтрация DNS запросов с помощью ng_ipfw+ng_bpf Недавно настроил для ИКС фильтрацию DNS запросов по типу. Возможно этот опыт пригодится еще кому то. Аналогичным образом можно фильтровать не только DNS, но и любые пакеты по их содержимому, если условие можно выразить в виде понятном bpf. Сама статья лежит на citrin.ru, а здесь только пара слов о том, зачем и почему это было мне нужно.
То ли пользователи в своей массе глупеют, то ли программисты разрабатывающие трояны умнеют, но за последние полгода в ИКС резко увеличилось число машин на которых установлены трояны, используемые для рассылки спама и DDoS-аттак (и другой подобной деятельности).
Когда число зараженных машин (и скорость появления новых членов "ботнета") превысила разумные пределы было принято решение закрыть пользователям 25-й порт. Мера это крайняя, но она было вынуждена. А более мягкие решения, например, автоматическое выявление спам-ботов и блокировка 25-го порта только машин рассылающих спам, с возможностью снятия блокировки через веб-интерфейс, небольшой сети сети с маленьким бюджетом, просто не по карману.
После того как 25-й порт был закрыт, я думал, что о проблеме спамботов у пользователей ИКС можно будет забыть если не на всегда, то на долго.
Однако у них оказался побочный эффект. Несмотря на то, что рассылать спам у них уже не получается они по прежнему пытаются это делать. При этом посылают к ДНС серверу много запросов на MX-записи. Чем вызывают повышенную загрузку сервера (и в небольшой степени внешнего канала).
Отсюда возникло желание зафильтровать запросы на MX-записи. Честные пользователи страдать от этого не должны - им MX-записи не нужны. Даже если кто то отправлял почту через локальный MTA (таких не больше нескольких человек из тысячи), то после закрытия 25-го порта им пришлось прописать relayhost/smarthost. Так что MX-записи не нужны даже им.
Но оказалось это не так просто сделать сделать. Все же в итоге задача была решена с помощью связки ipfw+ng_ipfw+ng_bpf. О том как это можно сделать я написал небольшую заметку у себя на сайте.
Надо сказать, что задача отняла у меня сравнительно много времени (часа два тольк ушло на ручное составление bpf-программы) - в сумме часов 5 наверно (всё ни как не приучу себя учитывать потраченное время). И овчинка не стоила выделки - нагрузка на сервер от спамботов была не на столько большой чтобы довести сервер до состояния 0% idle, можно было было на них просто забить. Но мне давно хотелось разобраться с тем, как фильтровать пакеты по их содержимому с помощью bg_bpf и был хороший повод этим заняться :)
Заодно разобрался с тем как работает bpf и узнал про багу особенность работы libpcap когда она собрана с поддержкой IPv6: функция pcap_compile для DLT_RAW сначала проверяет каждый пакет как будто это пакет IPv6 (даже если на самом деле это IPv4), а потом проверяет как IPv4. И за этого под правило попадает большое пакетов чем нужно (хоть и с низкой вероятностью). Разработчики пишут, что в CVS это уже исправлено.
|
Comments:
| From: | netch |
| Date: | Август 17, 2007 06:09 am none (UTC) |
|---|
| | | (Link) |
|
> часа два тольк ушло на ручное составление bpf-программы
tcpdump -d[d][d] не мог помочь?
tcpdump -d[d][d] немного помог. Только поскольку он считает все смещения для ethernet фрейма, а из ng_ipfw приходят IP пакеты, смещения нужно пересчитывать. А поскольку в ethernet фрейме полей больше чем в IP пакете, программу для IP пакета, пограмму нужно еще и укорачивать. Чтобы сделать все это нужно дезассемблировать bpf программу (вывод -ddd недостаточно понятнен и местами приходилось просто по кодам команд смотреть в net/bpf.h) и разобраться как она работает.
| From: | buddy_ekb |
| Date: | Ноябрь 26, 2007 10:30 am none (UTC) |
|---|
| | туннельный интерфейс | (Link) |
|
если указывать tcpdump'у в качестве -i туннельный интерфейс, то можно получить искомую микропрограмму без влезания в дебри net/bpf.h.
![[User Picture]](http://l-userpic.livejournal.com/13703899/1896181) | | From: | nuclight |
| Date: | Январь 26, 2009 12:27 pm none (UTC) |
|---|
| | Re: туннельный интерфейс | (Link) |
|
На 6.x это приведет к нерабочей программе:
# tcpdump -di tun0 src host 1.2.3.4
tcpdump: WARNING: tun0: no IPv4 address assigned
(000) ld [0]
(001) jeq #0x2000000 jt 2 jf 5
(002) ld [16]
(003) jeq #0x1020304 jt 4 jf 5
(004) ret #96
(005) ret #0
# tcpdump -di lo0 src host 1.2.3.4
(000) ld [0]
(001) jeq #0x2000000 jt 2 jf 5
(002) ld [16]
(003) jeq #0x1020304 jt 4 jf 5
(004) ret #96
(005) ret #0
# tcpdump -di ng0 src host 1.2.3.4
(000) ld [0]
(001) jeq #0x2000000 jt 2 jf 5
(002) ld [16]
(003) jeq #0x1020304 jt 4 jf 5
(004) ret #96
(005) ret #0
# tcpdump -dr dltraw.pcap src host 1.2.3.4
reading from file dltraw.pcap, link-type RAW (Raw IP)
(000) ld #0x0
(001) ld [12]
(002) jeq #0x1020304 jt 3 jf 4
(003) ret #65535
(004) ret #0
Видно, что в случае туннельных интерфейсов и лупбэка оно ищет адрес на 4 байта позже, чем в чистом DLT_RAW, а при вызове из ipfw именно RAW и надо. Сам файл dltraw.pcap (там только лишь 24 байта заголовка для определения типа линка), если лень извращаться с ipfwpcap, можно получить так: echo '1MOyoQIABAAAAAAAAAAAAP//AABlAAAA' | uudecode -mr > dltraw.pcap
![[User Picture]](http://l-userpic.livejournal.com/70195757/1956426) | | From: | _dyr |
| Date: | Октябрь 30, 2007 10:01 am none (UTC) |
|---|
| | | (Link) |
|
Немного отвлечённый вопрос на тему ngctl и ng_bpf: как получить getprogram из ng_bpf, не зная имени хука? Пример (mpd4 + shape):
nas3# ngctl list | grep bpf
Name: mpd5864-B-3-lim Type: bpf ID: 0000a2d3 Num hooks: 6
Name: mpd5864-B-4-lim Type: bpf ID: 0000a2ab Num hooks: 6
Name: mpd5864-B-1-lim Type: bpf ID: 0000a28a Num hooks: 6
Name: mpd5864-B-323-lim Type: bpf ID: 00009b6b Num hooks: 6
Name: mpd5864-B-733-lim Type: bpf ID: 000092fa Num hooks: 6
Name: mpd5864-B-638-lim Type: bpf ID: 000092eb Num hooks: 6
Name: mpd5864-B-284-lim Type: bpf ID: 000091bf Num hooks: 6
Name: mpd5864-B-244-lim Type: bpf ID: 00008fc5 Num hooks: 6
Name: mpd5864-B-423-lim Type: bpf ID: 00008bb7 Num hooks: 6
Name: mpd5864-B-52-lim Type: bpf ID: 0000812c Num hooks: 6
Name: mpd5864-B-192-lim Type: bpf ID: 00006a2d Num hooks: 6
Name: mpd5864-B-701-lim Type: bpf ID: 00005bae Num hooks: 6
Name: mpd5864-B-619-lim Type: bpf ID: 00004a78 Num hooks: 6
Name: mpd5864-B-389-lim Type: bpf ID: 00003fef Num hooks: 6
Name: mpd5864-B-104-lim Type: bpf ID: 000035d7 Num hooks: 6
Name: mpd5864-B-380-lim Type: bpf ID: 00002ad5 Num hooks: 6
Name: mpd5864-B-359-lim Type: bpf ID: 00002785 Num hooks: 6
Name: mpd5864-B-6-lim Type: bpf ID: 000018ed Num hooks: 6
Name: mpd5864-B-123-lim Type: bpf ID: 00000c2f Num hooks: 6
nas3# ngctl msg mpd5864-B-123-lim getprogram
ngctl: send msg: No such file or directory
nas3#
1. Сначала смотрим название хука (в колонке Local hook):
ngctl show mpd5864-B-123-lim:
потом зная его смотрим уже bpf-программу
ngctl msg mpd5864-B-123-lim: getprogram \"hook_name\"
![[User Picture]](http://l-userpic.livejournal.com/70195757/1956426) | | From: | _dyr |
| Date: | Октябрь 31, 2007 07:11 pm none (UTC) |
|---|
| | | (Link) |
|
Огромное спасибо, очень помогли. |
|
|