Статья: виртуальный свич на нетграфе
Добавлено: 2009-12-09 3:58:04
Итак
Виртуальный свич из нескольких сетевух на нетграфе.
Кому лень читать пост, выкладываю свой скрипт. Скрипт предоставляется "As Is" - все "Ты Казёл!" и "Дурак!" по поводу скрипта оставьте при себе. Конструктивная критика приветствуется. Наличие необходимых модулей ядра подразумевается.
ниже подразумевается что все команды выполняются от рута, объединяются сетевушки vr0 и vr1
нетграф по слухам чертовски производителен и чертовски плохо документирован, особенно на русском, так что если что не так, не обессудьте, в описанной конфигураци у меня все работает уже не один месяц. таже оговорюсь, что все беру с рабочей системы, так что может быть что от лишнее, а чего то не хватать
начнем с необходимого - с нетграфа. вот список того, что стоит у меня:
как видно из всего этого необходим минимум ng_eiface, который я забыл(или поленился) положить в ядро. Кроме того нам понадобятся модули ng_ether и ng_bridge. Но никто не запрещает побаловаться с ng_tee, ng_ipfw и чем нить подобным для подсчета трафика, шейпинга итд
После загрузки модулей нужных модулей смотрим что мы видим(оверквотинг удален)
мы должны видеть узлы типа ether по числу реальных интерфейсов, виртуальные интерфейс ngeth0 и узел socket, который служит для связи ngctl с ядром(это уже мои измышления. подробнее - man ng_socket) внешний интерфейс у меня rl0. vrX - внутренние
Далее нам надо сделать мост. но просто так его нельзя сделать, его надо на что то прицепить. Прицепим хук link0 к хуку lower сетевухи vr0. Сказано сделано. Попутно обзовем его каким нибудь нехорошим именем, типа switch
вот тут надо остановиться и поподробнее рассказать что такое хуки, узлы(ноды), какие они бывают и с чем их едят. Нетграф - это система, которая строит граф, по которому бегают пакеты. В графе есть узлы и ребра. иногда узел может просто висеть в воздухе(как например узлы наших сетевух), но чаще чтобы добавить какой то узел надо его к чему ни будь прикрутить. Прикручивание происходит соединением хуков разных узлов. хуки бывают разных типов, какие то пропускают пакеты только в одну торону, какие то пускают только пакеты верхних сетевух протоколов, подробнее про типу узлов написано в манах, а пока про насущное.
У сетевух(ether) есть три хука - upper lower orphans. Грубо говоря, lower работает с нижними протоколами(ethernet), upper - с верхними, а про orphans не помню, но он мне не вроде не подошел. у bridge - до NG_BRIDGE_MAX_LINKS(у меня на 7.2 в src/sys/netgraph/ng_bridge.h:55 говорится про 32 хука) хуков с именами типа link0 link1 link2... У eiface только один хук - ether через который бегают все пакеты.
при обращении к локальным узлам пишем двоеточие в конце имени
c теорией вроде закончил, перейдем к практике. продолжаем строит свич. цепляем к мосту остальные хуки сетевушек
Идем далее. Сетевухи имеют свойства выпуская пакет прописывать в нем поле отправитель себя и игнорировать пакеты, предназначенные не ей. отучаем их от этих нехороших привычек:
свич почти готов. цепляем к нему виртуальную сетевуху, чтобы общаться с ним
и далее самое интересное. снимаем ипы с реальных сетевух(порты свича не имеют ипов) и ставим ип машины на виртуальную сетевуху. реальные карточки должны быть без ипов только в состояниии up
вроде бы и все.
смотрим что у нас получилось
как видно, сетевухи vrX смирились со своей ролью в качестве портов свича и на них не висят маки соседих машин. все выглядит так, будто у нас есть свич, в который воткнуты кабеля машин внутренней сети и кабель от нашего компа с интерфейса ngeth0
дальше разруливаем все пакеты файером, в нем разрешаем прохождение пакетов через реальные внутренние сетевухи(или шейпим/режем по надобности), ставим нат с внешней сетевухи на ngeth0, раздача инета между сетевухами моста будет регулироваться нетграфом
спасибо за внимание, конструктивная критика приветствуется
PS
Имеет ли смысл создавать статью? полезен ли материал, вобщем требую критики)
Виртуальный свич из нескольких сетевух на нетграфе.
Кому лень читать пост, выкладываю свой скрипт. Скрипт предоставляется "As Is" - все "Ты Казёл!" и "Дурак!" по поводу скрипта оставьте при себе. Конструктивная критика приветствуется. Наличие необходимых модулей ядра подразумевается.
Код: Выделить всё
#!/bin/sh
ngCtl="/usr/sbin/ngctl "
Sleep="/bin/sleep"
PFcmd="/sbin/pfctl"
Head="/usr/bin/head"
Tail="/usr/bin/tail"
Echo="/bin/echo"
Rm="/bin/rm"
PidFile="/var/run/mybridge.pid"
if1="vr0"
if2="vr1"
ifng="ngeth0"
Switch="switch"
case $1 in
start)
if [ -s $PidFile ]; then
${Echo} Bridge already runned!
exit 1
fi
${Echo} Starting bridge
${ngCtl} debug 2
${ngCtl} mkpeer $if1: bridge lower link0
${ngCtl} name $if1:lower $Switch
${ngCtl} connect $if1: $Switch: upper link1
${ngCtl} connect $if2: $Switch: lower link2
${ngCtl} connect $if2: $Switch: upper link3
${ngCtl} msg $if1: setpromisc 1
${ngCtl} msg $if2: setpromisc 1
${ngCtl} msg $if1: setautosrc 0
${ngCtl} msg $if2: setautosrc 0
${ngCtl} mkpeer $Switch: eiface link5 ether
${ngCtl} name $Switch:link5 $ifng
${Sleep} 2
${Head} -n7 /etc/pf.conf.bak > /etc/pf.conf
${Echo} 'int_if="'$ifng'"' >> /etc/pf.conf
${Tail} -n79 /etc/pf.conf.bak >> /etc/pf.conf
ifconfig $if1 -alias
ifconfig $ifng inet 192.168.0.1 netmask 255.255.255.0
${PFcmd} -f /etc/pf.conf
${Echo} "runned" >> $PidFile
;;
stop)
if [ ! -s $PidFile ]; then
${Echo} Bridge is not runned!
exit 1
fi
${ngCtl} shutdown $Switch:
${ngCtl} shutdown $ifng:
${Head} -n7 /etc/pf.conf.bak > /etc/pf.conf
${Echo} 'int_if="'$if1'"' >> /etc/pf.conf
${Tail} -n79 /etc/pf.conf.bak >> /etc/pf.conf
ifconfig $if1 inet 192.168.0.1 netmask 255.255.255.0
${Rm} $PidFile
${PFcmd} -f /etc/pf.conf
;;
*)
if [ -s $PidFile ]; then
${Echo} State: Up
else
${Echo} State: Down
fi
;;
esac
нетграф по слухам чертовски производителен и чертовски плохо документирован, особенно на русском, так что если что не так, не обессудьте, в описанной конфигураци у меня все работает уже не один месяц. таже оговорюсь, что все беру с рабочей системы, так что может быть что от лишнее, а чего то не хватать
начнем с необходимого - с нетграфа. вот список того, что стоит у меня:
Код: Выделить всё
# kldstat -v |grep ng
202 ng_socket
181 ng_car
201 ng_rfc1490
200 ng_pptpgre
177 ng_async
199 ng_ppp
180 ng_bridge
198 ng_one2many
197 ng_nat
176 ng_UI
196 ng_mppc
195 ng_lmi
179 ng_bpf
194 ng_l2tp
175 ng_netflow
193 ng_ksocket
192 ng_ipfw
191 ng_ip_input
190 ng_iface
189 ng_hole
188 ng_gif_demux
187 ng_gif
186 ng_framerelay
185 ng_ether
184 ng_echo
183 ng_deflate
207 ng_vjc
206 ng_tty
205 ng_tee
204 ng_tcpmss
203 ng_ng_split
182 ng_cisco
2 1 0xc0945000 2fd4 ng_eiface.ko
1 ng_eiface
# kldstat -v |grep netgraph
178 netgraph
После загрузки модулей нужных модулей смотрим что мы видим(оверквотинг удален)
Код: Выделить всё
# ngctl list
There are N total nodes:
Name: <unnamed> Type: eiface ID: 0000001e Num hooks: 0
Name: rl0 Type: ether ID: 00000001 Num hooks: 0
Name: vr0 Type: ether ID: 00000002 Num hooks: 0
Name: vr1 Type: ether ID: 00000003 Num hooks: 0
Name: ngeth0 Type: ether ID: 00000003 Num hooks: 0
Name: ngctl38473 Type: socket ID: 0000be26 Num hooks: 0
мы должны видеть узлы типа ether по числу реальных интерфейсов, виртуальные интерфейс ngeth0 и узел socket, который служит для связи ngctl с ядром(это уже мои измышления. подробнее - man ng_socket) внешний интерфейс у меня rl0. vrX - внутренние
Далее нам надо сделать мост. но просто так его нельзя сделать, его надо на что то прицепить. Прицепим хук link0 к хуку lower сетевухи vr0. Сказано сделано. Попутно обзовем его каким нибудь нехорошим именем, типа switch
Код: Выделить всё
ngctl mkpeer vr0: bridge lower link0
ngctl name vr0:lower switch
У сетевух(ether) есть три хука - upper lower orphans. Грубо говоря, lower работает с нижними протоколами(ethernet), upper - с верхними, а про orphans не помню, но он мне не вроде не подошел. у bridge - до NG_BRIDGE_MAX_LINKS(у меня на 7.2 в src/sys/netgraph/ng_bridge.h:55 говорится про 32 хука) хуков с именами типа link0 link1 link2... У eiface только один хук - ether через который бегают все пакеты.
при обращении к локальным узлам пишем двоеточие в конце имени
c теорией вроде закончил, перейдем к практике. продолжаем строит свич. цепляем к мосту остальные хуки сетевушек
Код: Выделить всё
ngctl connect vr0: switch: upper link1
ngctl connect vr1: switch: lower link2
ngctl connect vr1: switch: upper link3
Код: Выделить всё
ngctl msg vr0: setpromisc 1
ngctl msg vr1: setpromisc 1
ngctl msg vr0: setautosrc 0
ngctl msg vr1: setautosrc 0
Код: Выделить всё
ngctl mkpeer switch: eiface link5 ether
ngctl name switch:link5 ngeth0
Код: Выделить всё
ifconfig vr0 up
ifconfig vr1 up
ifconfig vr0 -alias
ifconfig vr1 -alias
ifconfig ngeth0 inet 192.168.0.1 netmask 255.255.255.0
смотрим что у нас получилось
Код: Выделить всё
# ifconfig
rl0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=8<VLAN_MTU>
ether <XXX>
inet 10.XXX.XXX.XXX netmask 0xffffXXX broadcast 10.XXX.XXX.XXX
media: Ethernet autoselect (100baseTX <full-duplex>)
status: active
vr0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=2808<VLAN_MTU,WOL_UCAST,WOL_MAGIC>
ether <XXX>
media: Ethernet autoselect (100baseTX <full-duplex>)
status: active
vr1: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=2808<VLAN_MTU,WOL_UCAST,WOL_MAGIC>
ether <XXX>
media: Ethernet autoselect (100baseTX <full-duplex>)
status: active
ngeth0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
ether 00:00:00:00:00:00
inet 192.168.0.1 netmask 0xffffff00 broadcast 192.168.0.255
<overquoting deleted>
# ngctl list
Name: <unnamed> Type: ksocket ID: 0000be23 Num hooks: 1
Name: <unnamed> Type: pptpgre ID: 0000be22 Num hooks: 2
Name: <unnamed> Type: eiface ID: 0000001e Num hooks: 1
Name: ng0 Type: iface ID: 0000bd94 Num hooks: 1
Name: rl0 Type: ether ID: 00000001 Num hooks: 0
Name: switch Type: bridge ID: 00000014 Num hooks: 5
Name: vr0 Type: ether ID: 00000002 Num hooks: 2
Name: vr1 Type: ether ID: 00000003 Num hooks: 2
Name: mpd16513-stats Type: socket ID: 0000bd9a Num hooks: 0
Name: ngctl38842 Type: socket ID: 0000be2a Num hooks: 0
Name: mpd16513-cso Type: socket ID: 0000bd92 Num hooks: 0
Name: mpd16513-eso Type: socket ID: 0000bd93 Num hooks: 0
Name: ipfw Type: ipfw ID: 00000004 Num hooks: 0
Name: mpd16513-lso Type: socket ID: 0000bd91 Num hooks: 1
Name: ngeth0 Type: ether ID: 0000001f Num hooks: 0
Name: mpd16513-B1-mss Type: tcpmss ID: 0000be24 Num hooks: 2
Name: mpd16513-B1 Type: ppp ID: 0000bd95 Num hooks: 3
Name: mpd16513-L1-lt Type: tee ID: 0000bd96 Num hooks: 2
# arp -a
? (10.XXX.XXX.XXX) at <XXX_MAC> on rl0 [ethernet](записи такого вида - адреса из локалки провайдера)
------------------------``----------------------------------
? (192.168.0.2) at <XXX_MAC> on ngeth0 [ethernet]
? (192.168.0.3) at <XXX_MAC> on ngeth0 [ethernet]
? (192.168.0.255) at ff:ff:ff:ff:ff:ff on ngeth0 permanent [ethernet]
дальше разруливаем все пакеты файером, в нем разрешаем прохождение пакетов через реальные внутренние сетевухи(или шейпим/режем по надобности), ставим нат с внешней сетевухи на ngeth0, раздача инета между сетевухами моста будет регулироваться нетграфом
спасибо за внимание, конструктивная критика приветствуется
PS
Имеет ли смысл создавать статью? полезен ли материал, вобщем требую критики)