Главная страница | Добавить в избранное    
   

 

» Статьи » Multicast во FreeBSD без igmpproxy replacement on netgraph

   
main1
pix
 

Multicast во FreeBSD без igmpproxy replacement on netgraph

Статьи  
pix pix pix

Скрипт собирающий netgraph мост для мультикаст трафика (IGMP, UDP) между двумя сетевыми интерфейсами предназначен для замены igmpproxy/mrouted.

 

#!/bin/sh
# Copyright (c) 2011 Rozhuk Ivan <rozhuk.im@gmail.com>
# All rights reserved.
# 
# Subject to the following obligations and disclaimer of warranty, use and
# redistribution of this software, in source or object code forms, with or
# without modifications are expressly permitted by Whistle Communications;
# provided, however, that:
# 1. Any and all reproductions of the source or object code must include the
#    copyright notice above and the following disclaimer of warranties; and
# 2. No rights are granted, in any manner or form, to use Whistle
#    Communications, Inc. trademarks, including the mark "WHISTLE
#    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
#    such appears in the above copyright notice or in the software.
# 
# THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
# TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
# REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
# INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
# WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
# REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
# SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
# IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
# RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
# WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
# OF SUCH DAMAGE.
#
# Author: Rozhuk Ivan <rozhuk.im@gmail.com>
#
# This script creates bridge between two network interfaces
# downstream - network with clients
# upstream - network with multicast
# downstream <-IGMP-> upstream
# downstream <-UDP<- upstream
# Only packets with multicast destination mac address are forwarded
# through the bridge and (!) are not passed to network stack
IF_UPSTREAM="$2"
IF_DOWNSTREAM="$3"
BR_NAME="${IF_UPSTREAM}-${IF_DOWNSTREAM}-br"
PATTERN_MCAST_IGMP="ether[0] & 1 = 1 and (ether[0:4] != 0xffffffff or ether[4:2] != 0xffff) and ip[9] = 2"
PATTERN_MCAST_IGMP_UDP="ether[0] & 1 = 1 and (ether[0:4] != 0xffffffff or ether[4:2] != 0xffff) and (ip[9] = 17 or ip[9] = 2)"
# allways NOT MATCH
BPFPROG_PASSTROUTH="bpf_prog_len=1 bpf_prog=[ { code=6 jt=0 jf=0 k=0 } ]"

usage_msg()
{
	echo "usage: start|stop upstreamIF downstreamIF"
	echo "This will create bridge between two interfaces for IGMP, and UDP from upstreamIF to downstreamIF"
}
if [ -z "${IF_UPSTREAM}" -o -z "${IF_DOWNSTREAM}" ]; then
	usage_msg
	return 1
fi
if ! ifconfig "$IF_UPSTREAM" > /dev/null 2>&1 ; then
	usage_msg
	echo "Invalid upstream interface: ${IF_UPSTREAM}"
	return 1
fi
if ! ifconfig "$IF_DOWNSTREAM" > /dev/null 2>&1 ; then
	usage_msg
	echo "Invalid downstream interface: ${IF_DOWNSTREAM}"
	return 1
fi
case "$1" in
start)
	echo "start bridging beetwen ${IF_UPSTREAM} and ${IF_DOWNSTREAM}"
	# load modules
	kldload ng_ether > /dev/null 2>&1
	kldload ng_bpf > /dev/null 2>&1
	BPFPROG_MCAST_IGMP=$( tcpdump -s 65535 -ddd ${PATTERN_MCAST_IGMP} | \
		( read len ; \
		echo -n "bpf_prog_len=$len " ; \
		echo -n "bpf_prog=[" ; \
		while read code jt jf k ; do \
		  echo -n " { code=$code jt=$jt jf=$jf k=$k }" ; \
		done ; \
		echo " ]" ) )
	BPFPROG_MCAST_IGMP_UDP=$( tcpdump -s 65535 -ddd ${PATTERN_MCAST_IGMP_UDP} | \
		( read len ; \
		echo -n "bpf_prog_len=$len " ; \
		echo -n "bpf_prog=[" ; \
		while read code jt jf k ; do \
		  echo -n " { code=$code jt=$jt jf=$jf k=$k }" ; \
		done ; \
		echo " ]" ) )
	# create and connect nodes
	ngctl mkpeer ${IF_UPSTREAM}: bpf lower ${IF_UPSTREAM}-lower
	ngctl name ${IF_UPSTREAM}:lower ${BR_NAME}-bpf
	ngctl connect ${IF_UPSTREAM}: ${BR_NAME}-bpf: upper ${IF_UPSTREAM}-upper
	ngctl connect ${IF_DOWNSTREAM}: ${BR_NAME}-bpf: lower ${IF_DOWNSTREAM}-lower
	ngctl connect ${IF_DOWNSTREAM}: ${BR_NAME}-bpf: upper ${IF_DOWNSTREAM}-upper
	# configure BPF node
	ngctl msg ${BR_NAME}-bpf: setprogram { thisHook=\"${IF_UPSTREAM}-lower\" ifMatch=\"${IF_DOWNSTREAM}-lower\" ifNotMatch=\"${IF_UPSTREAM}-upper\" ${BPFPROG_MCAST_IGMP_UDP} }
	ngctl msg ${BR_NAME}-bpf: setprogram { thisHook=\"${IF_UPSTREAM}-upper\" ifMatch=\"\" ifNotMatch=\"${IF_UPSTREAM}-lower\" ${BPFPROG_PASSTROUTH} }
	ngctl msg ${BR_NAME}-bpf: setprogram { thisHook=\"${IF_DOWNSTREAM}-lower\" ifMatch=\"${IF_UPSTREAM}-lower\" ifNotMatch=\"${IF_DOWNSTREAM}-upper\" ${BPFPROG_MCAST_IGMP} }
	ngctl msg ${BR_NAME}-bpf: setprogram { thisHook=\"${IF_DOWNSTREAM}-upper\" ifMatch=\"\" ifNotMatch=\"${IF_DOWNSTREAM}-lower\" ${BPFPROG_PASSTROUTH} }
	# configure net if
	ngctl msg ${IF_UPSTREAM}: setautosrc 1
	ngctl msg ${IF_UPSTREAM}: setpromisc 1
	#ngctl msg ${IF_DOWNSTREAM}: setautosrc 0
	ngctl msg ${IF_DOWNSTREAM}: setpromisc 1
	;;
stop)
	echo "stop bridging beetwen ${IF_UPSTREAM} and ${IF_DOWNSTREAM}"
	# configure net if
	ngctl msg ${IF_UPSTREAM}: setautosrc 0
	ngctl msg ${IF_UPSTREAM}: setpromisc 0
	#ngctl msg ${IF_DOWNSTREAM}: setautosrc 0
	ngctl msg ${IF_DOWNSTREAM}: setpromisc 0
	# remove hooks and nodes
	ngctl rmhook ${IF_UPSTREAM}: lower
	ngctl rmhook ${IF_UPSTREAM}: upper
	ngctl rmhook ${IF_DOWNSTREAM}: lower
	ngctl rmhook ${IF_DOWNSTREAM}: upper
	ngctl shutdown ${BR_NAME}-bpf:
	# unload modules
	#kldunload ng_ether > /dev/null 2>&1
	#kldunload ng_bpf > /dev/null 2>&1
	;;
*)
	usage_msg
esac
return 0

Использование
Создать мост между em0 и re0, где re0 подключён к сети с мультикастом:
Код:
mcastbr2.sh start re0 em0

Удалить мост:
Код:
mcastbr2.sh stop re0 em0


История
igmpproxy и mrouted у меня работать отказались, после нескольких часов проб,
чтения и новых проб я решил не заниматься ремонтом ядра и этих приложений,
а просто выборочно сбриджевать два сетевых интерфейса:
 - IGMP на multicast адреса из локалки в сеть провайдера и обратно;
 - UDP на multicast адреса из сети провайдера в локалку. Броадкаст не нужен, и направляется в ядро как обычно.

Несмотря на цифру 2, по сути эта третья версия графа, получившая в результате оптимизации первых двух.
Первая содержала ng_ether, ng_tee, ng_one2many, ng_bpf.
Вторая содержала ng_ether, ng_tee, ng_one2many, ng_bpf.
Окончательная содержит: ng_ether, ng_left2right, ng_tee, ng_bpf.
В первых двух версиях создавалась копия пакета, и один уходил через мост в другую сеть либо отбрасывался, а второй попадал в ядро.
Поскольку ядро всё равно их дропало где то внутри и нетграф их очень много отбрасывал, ничего полезного не делая,
то я решил их вообще туда не посылать и организовать так чтобы не создавать дубликатов и не уничтожать пакеты.


Принцип работы
BPF настроен таким образом чтобы пропускать все без исключения пакеты с upper хуков ng_ether нод на lower хуки (пакеты от системы в сеть).
Приходящие из сети пакеты с lower хуков нод проверяются в BPF, и
 - если это мультикаст;
 - и не броадкаст;
 - и IGMP [или UDP в случае если пакет от адаптера подключённого к провайдеру]
то такой пакет целиком пересылается на lower хук другого адаптера, минуя сетевой стёк операционной системы.


Тонкости
1. Пришлось включить promisc режим на обоих интерфейсах, иначе мультикаст дропается самим сетевым адаптером, это нормальное поведение.

2. Пришлось включить autosrc на интерфейсе в сети провайдера, тк у провайдера на коммутаторе настроен Port Security
на пропускание только одного MAC адреса - первого изученного на порту после поднятия линка.

3. Моему провайдеру нет дела до того какой src-ip в IP приходит от меня, если бы было,
то я бы попробовал гнать трафик в сторону провайдера через ng_patch ноду, которая бы заменяла src-ip на нужны,
и выставляла CSUM_IP и CSUM_UDP в заголовке пакета - есть шанс что драйвер сетевого адаптера
сам рассчитает эти суммы либо что оборудование провайдера проигнорирует неверную контрольную сумму в IGMP пакетах от меня.
Нода также подключается обоими хуками к BPF, выход настраивается на passtrouth (пересылку всех пакетов) на lower хук ng_ether
на адаптере в сети провайдера, а вход ng_patch должен быть match выходом от lower на адаптере в локальной сети. Те совсем не большая модификация графа.

4. Работает на vlan интерфейсах.



PS
Для создания аналогичного по функционалу моста, в котором будет несколько сетевых интерфейсов в разных сетях с мультикастом
и несколько сетевых адаптеров в сетях куда его нужно переправить потребуется на каждый сетевой адаптер вешать по ng_split + ng_one2many
и по одной ng_one2many с каждой стороны моста для рассылки копий мультикаста на все интерфейсы. upper хуки ng_ether нод по прежнему будут
напрямую подключатся к BPF. В случае нескольких сетей - источников мультикаста будет ещё проблема с возможным перекрытием адресных пространств,
которую можно частично разрешить настроив в BPF фильтрацию по адресам.



Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь. Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.
 
Автор: hellevil | 20-01-2012, 13:01 | Просмотров: 8 600
 
pix
  Новости по теме    
pix pix pix
  • Оценка производителности графов Netgraph.
  • Xen Скрипт монтирования образа системы (*.img) for Centos
  • MySQL Error Codes
  • FreeBSD - fail2ban
  • Настройка/установка natd/маршрутизатора в FreeBSD на основе natd+ipfw
  •  
     
     
    pix
     
    pix
    search
    navi
    poll
    calendar
    «    Апрель 2024    »
    ПнВтСрЧтПтСбВс
    1234567
    891011121314
    15161718192021
    22232425262728
    2930 
    main4
    pix pix pix

    2007 © www.DesktopBSD.ru
    Все права сохранены