Виртуальный свич из нескольких сетевух на нетграфе.
Кому лень читать пост, выкладываю свой скрипт. Скрипт предоставляется "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
Имеет ли смысл создавать статью? полезен ли материал, вобщем требую критики)