Site Tools


software:freebsd:igmpproxy_on_netgraph

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Next revisionBoth sides next revision
software:freebsd:igmpproxy_on_netgraph [2015/05/15 15:08]
– [Фильтры] root
software:freebsd:igmpproxy_on_netgraph [2015/07/18 23:14]
– [История] root
Line 20: Line 20:
  
 ===== Принцип работы ===== ===== Принцип работы =====
 +==== netgraph ====
 +Его можно сравнить с LUA: он даёт широкие возможности по манипуляции с сетевыми пакетами, относительно прост в использовании и максимально быстр тк всё происходит в ядре.\\
 +У меня было много разных вариантов но в конце мне удалось свести количество нод к двум: **ng_ether** и **ng_bpf**.\\
 +**ng_ether** — имеет несколько хуков: __lower__ — это вход/выход сетевого адаптера, __upper__ — ввод/выход в сетевой стёк OS.\\
 +**ng_bpf** — программируемая нода, общий смысл программ: один вход и два выхода: пакет соответствует заданному условии и для пакетов которые не соответствуют. В ноде есть собственный ассемблер для матчинга пакетов. Но можно написать условия для tcpdump и получить код для **ng_bpf**.\\
 +Не большая хитрость ноды в том, что программа устанавливается на входную ноду. Но ноды которые указаны как выходные тоже могут принимать пакеты и обрабатывать они их будут по тем программам которые ассоциированы с ними.\\
 +
 +==== Передача пакетов ====
 {{:ru:software:freebsd:ng_bpf_bridge.png|}}\\ {{:ru:software:freebsd:ng_bpf_bridge.png|}}\\
 **BPF** настроен таким образом чтобы пропускать все без исключения пакеты с __upper__ хуков **ng_ether** нод на __lower__ хуки (пакеты от системы в сеть). Приходящие из сети пакеты с __lower__ хуков нод проверяются в **BPF**, и\\ **BPF** настроен таким образом чтобы пропускать все без исключения пакеты с __upper__ хуков **ng_ether** нод на __lower__ хуки (пакеты от системы в сеть). Приходящие из сети пакеты с __lower__ хуков нод проверяются в **BPF**, и\\
Line 42: Line 50:
 Теперь получим ассемблерный код для bpf: Теперь получим ассемблерный код для bpf:
 <code>tcpdump -i em0 -s 65535 -ddd 'ether[0] & 1 = 1 and ( ether[0:4] != 0xffffffff or ether[4:2] != 0xffff ) and ip[9] = 2'</code> <code>tcpdump -i em0 -s 65535 -ddd 'ether[0] & 1 = 1 and ( ether[0:4] != 0xffffffff or ether[4:2] != 0xffff ) and ip[9] = 2'</code>
-(имя интерфейса указывать не обязательно, но возможны ошибки тк не все интерфейсы в системе могут работать с tcpdump а берёт ое первый попавшийся):\\+(имя интерфейса указывать не обязательно, но возможны ошибки тк не все интерфейсы в системе могут работать с tcpdump а берёт первый попавшийся):\\
 <code>    13 <code>    13
     48 0 0 0     48 0 0 0
Line 69: Line 77:
  
 ==== Тонкости ==== ==== Тонкости ====
-1. Пришлось включить **promisc** режим на обоих интерфейсах, иначе мультикаст дропается самим сетевым адаптером, это нормальное поведение.+1. Адаптеры нужно перевести в «не разборчивый» = promisc режим, иначе они аппаратно отфильтрую весь мультикат, тк OS не настраивала его пропускание.\\ 
 +<code>ngctl msg ${IF_UPSTREAM}: setpromisc 1 ngctl msg ${IF_DOWNSTREAM}: setpromisc 1</code>
  
-2. Пришлось включить **autosrc** на интерфейсе в сети провайдера, тк у провайдера на коммутаторе настроен Port Security на пропускание только одного MAC адреса - первого изученного на порту после поднятия линка.+2. autosrc на WAN интерфейсе лучше включить. Таким образом все отбриджованные пакеты будут улетать провайдеру с мак адресом WAN адаптера. Это особенно актуально когда провайдер включает __Port Security__ и задаёт лимит в один адрес. 
 +<code>ngctl msg ${IF_UPSTREAM}: setautosrc 1</code>
  
 3. Моему провайдеру нет дела до того какой src-ip в IP приходит от меня, если бы было, то я бы попробовал гнать трафик в сторону провайдера через **ng_patch** ноду, которая бы заменяла src-ip на нужны, и выставляла CSUM_IP и CSUM_UDP в заголовке пакета - есть шанс что драйвер сетевого адаптера сам рассчитает эти суммы либо что оборудование провайдера проигнорирует неверную контрольную сумму в IGMP пакетах от меня. Нода также подключается обоими хуками к BPF, выход настраивается на passtrouth (пересылку всех пакетов) на __lower__ хук __ng_ether__ на адаптере в сети провайдера, а вход __ng_patch__ должен быть //match// выходом от __lower__ на адаптере в локальной сети. Те совсем не большая модификация графа. 3. Моему провайдеру нет дела до того какой src-ip в IP приходит от меня, если бы было, то я бы попробовал гнать трафик в сторону провайдера через **ng_patch** ноду, которая бы заменяла src-ip на нужны, и выставляла CSUM_IP и CSUM_UDP в заголовке пакета - есть шанс что драйвер сетевого адаптера сам рассчитает эти суммы либо что оборудование провайдера проигнорирует неверную контрольную сумму в IGMP пакетах от меня. Нода также подключается обоими хуками к BPF, выход настраивается на passtrouth (пересылку всех пакетов) на __lower__ хук __ng_ether__ на адаптере в сети провайдера, а вход __ng_patch__ должен быть //match// выходом от __lower__ на адаптере в локальной сети. Те совсем не большая модификация графа.
Line 79: Line 89:
  
 ===== История ===== ===== История =====
-igmpproxy и mrouted у меня работать отказались: PF по умолчанию убивает все пакеты с IP опциями в заголовке (IGMP они нужны для работы) и поэтому добавлять специально правило:+igmpproxy и mrouted у меня работать отказались: PF по умолчанию убивает все пакеты с IP опциями в заголовке (IGMP они нужны для работы) и поэтому нужно добавлять правило:
 <code>pass quick proto igmp from any to 224.0.0.0/4 allow-opts</code> <code>pass quick proto igmp from any to 224.0.0.0/4 allow-opts</code>
 а я этого не сделал.\\ а я этого не сделал.\\
Line 97: Line 107:
 ===== PS ===== ===== PS =====
 Для создания аналогичного по функционалу моста, в котором будет несколько сетевых интерфейсов в разных сетях с мультикастом и несколько сетевых адаптеров в сетях куда его нужно переправить потребуется на каждый сетевой адаптер вешать по **ng_split** + **ng_one2many** и по одной **ng_one2many** с каждой стороны моста для рассылки копий мультикаста на все интерфейсы. __upper__ хуки **ng_ether** нод по прежнему будут напрямую подключатся к BPF. В случае нескольких сетей - источников мультикаста будет ещё проблема с возможным перекрытием адресных пространств, которую можно частично разрешить настроив в BPF фильтрацию по адресам. Для создания аналогичного по функционалу моста, в котором будет несколько сетевых интерфейсов в разных сетях с мультикастом и несколько сетевых адаптеров в сетях куда его нужно переправить потребуется на каждый сетевой адаптер вешать по **ng_split** + **ng_one2many** и по одной **ng_one2many** с каждой стороны моста для рассылки копий мультикаста на все интерфейсы. __upper__ хуки **ng_ether** нод по прежнему будут напрямую подключатся к BPF. В случае нескольких сетей - источников мультикаста будет ещё проблема с возможным перекрытием адресных пространств, которую можно частично разрешить настроив в BPF фильтрацию по адресам.
 +
 +
 +===== Ссылки =====
 +[[http://www.freebsd.org/cgi/man.cgi?query=ng_bpf&apropos=0&sektion=4&manpath=FreeBSD+9.2-RELEASE&arch=default&format=html|man ng_bpf]]\\
 +[[http://nuclight.livejournal.com/124989.html?nojs=1|Как работает tcpdump: ассемблер BPF; фильтрация с ng_bpf на FreeBSD]]\\
 +[[http://citrin.ru/freebsd:ng_ipfw_ng_bpf|Использование ng_ipfw + ng_bpf для фильтрации по телу пакета]]\\
 +[[http://nuclight.livejournal.com/122098.html?nojs=1|Программирование ng_bpf(4) и L7 filtering на FreeBSD]]\\
software/freebsd/igmpproxy_on_netgraph.txt · Last modified: 2022/02/05 05:30 by root