2012-09-14

Multicast light: statikus multicast routing Linuxon (2.)

Az előző részben elkészült egyszerű multicast rendszert valahogy le kell tesztelni. Sokan a VLC média playert használják ehhez, ami teljesen rendjén is van, de azért sosem árt, ha van valami igazán igénytelen, CLI-s eszközünk, amivel valódi multicast forgalmat generálhatunk. Pontosan ilyen program az "mcsender", ami az "smcroute" csomaggal együtt érkezik (legalábbis Ubuntu/Debian alatt). Ennek segítségével kipróbálhatóak az előző részben beállított statikus multicast route-ok. A topológiánk most is a következő:



A "bajor" hostról legalább 3-as IP TTL értékkel (hiszen három hálózaton kell átjutnia a multicast üzenetnek ebben a topológiában), 192.168.1.100-as forrás IP-vel, a 225.1.2.3-as csoportnak címezve, 3000-es UDP porton a következő paranccsal küldetünk teszt UDP streamet:

robert@bajor:~$ mcsender -t3 -ieth0 225.1.2.3:3000

Igen ám, de mi fogja ezt fogadni? Az "andoria" hoston szükségünk lesz egy másik multicastos teszteszközre, az "emcast"-ra. Az "emcast" multicast streamet képes fogadni, és a stream tartalmát kiteszi az STDOUT-ra, valahogy így:

robert@andoria:~$ emcast 225.1.2.3:3000
this is the test message from mclab/mcsender
this is the test message from mclab/mcsender
this is the test message from mclab/mcsender
this is the test message from mclab/mcsender
this is the test message from mclab/mcsender
this is the test message from mclab/mcsender
this is the test message from mclab/mcsender
this is the test message from mclab/mcsender
...

Annyi csavar van a dologban, hogy az "emcast" csomagot az Ubuntu 11.04-es verzió után kidobták a hivatalos repókból, így vagy fordítunk magunknak, vagy feltesszük a 11.04-esben lévő deb-et (12.04-en csont nélkül megy). Ha mégsem működne a multicast rendszerünk, ellenőrizzük, hogy fut-e egyáltalán az smcroute démon (pgrep smcroute), nézzük végig minden multicast routeren a multicast route-okat az "ip mroute show" paranccsal, illetve bizonyosodjunk meg arról, hogy a bejövő és kimenő multicast interfészek benne vannak-e a kernel multicast interfész táblázatában (cat /proc/net/ip_mr_vif).

További hibalehetőség lehet az, ha az smcroute démon indításakor még nem él valamelyik, a multicast route-ok által hivatkozott interfész. Tipikusan ilyen lehet a VPN tunnel interfész, ha le-föl kapcsolgatjuk. Ilyenkor hiába él már a tun1 utólag, az smcroute démon indítása után:

root@trill:~# ifconfig tun1
tun1      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet addr:172.31.255.1  P-t-P:172.31.255.2  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

Nem lehet hozzáadni a statikus multicast route-ot:

root@trill:~# smcroute -a eth0 192.168.1.100 225.1.2.3 tun1
Daemon error: Warn: invalid output interface

...és a multicast interfészek közt sincs benne a kernel szerint:

root@trill:~# cat /proc/net/ip_mr_vif
Interface      BytesIn  PktsIn  BytesOut PktsOut Flags Local    Remote
 0 eth0              0       0         0       0 00000 0101A8C0 00000000
 1 eth1              0       0         0       0 00000 010A0A0A 00000000

Újra kell az smcroute-ot indítani, és megint megpróbálni a route hozzáadást:

root@trill:~# service smcroute stop
Stopping static multicast router daemon: smcroute.
root@trill:~# service smcroute start
Starting static multicast router daemon: smcroute.

root@trill:~# cat /proc/net/ip_mr_vif
Interface      BytesIn  PktsIn  BytesOut PktsOut Flags Local    Remote
 0 eth0              0       0         0       0 00000 0101A8C0 00000000
 1 eth1              0       0         0       0 00000 010A0A0A 00000000
 2 tun1              0       0         0       0 00000 01FF1FAC 00000000
root@trill:~# smcroute -a eth0 192.168.1.100 225.1.2.3 tun1
root@trill:~# ip mroute show
(192.168.1.100, 225.1.2.3)       Iif: eth0       Oifs: tun1

2012-09-05

Multicast light: statikus multicast routing Linuxon (1.)

Mostanában szinte kizárólag Linuxokkal foglalkozom, és egyre többször találkozom sajátos megoldásokkal. Az egyik ilyen sajátosan linuxos megoldás a minden nélküli multicast, avagy "multicast light" lehetőség, ami valószínűleg eléggé unortodox, viszont cserébe egyszerű mint az ék, kevésbé összetett multicast környezetekben kiválóan alkalmazható.

A korrekt IPv4 multicast rendszerek működéséhez LAN oldalon IGMP-s hostok, IGMP querier a router(ek)en, illetve a switcheken IGMP snooping szükségeltetik, a routerek pedig egymás közt valamilyen multicast routing protokollal (pl. PIM vagy DVMRP) lerendezik, hogy melyik multicast csoportnak címzett forgalmat hová kell továbbítani. Az „smcroute” multicast routing megoldással tulajdonképpen ebből a listából mindent el lehet hagyni, ha elfogadhatóak számunkra az ezekkel járó kompromisszumok.

LAN oldalon a legfájóbb pont IGMP snooping hiánya lehet. Layer 2-ben a multicast forgalom alapesetben, extra konfiguráció nélkül, minden hosthoz eljut (flood), max. azok nem törődnek vele, ha nem tagjai az adott multicast csoportnak. Attól függően, hogy mekkora ez a multicast forgalom, hogy csak egy vékonyka, mondjuk 20Kbit/s-os tőzsdei árfolyam-streamről beszélünk, vagy durva, sok Mbit/s-os video streamről, ez az elárasztásos forgalom lehet szinte észrevehetetlen, megtűrt vagy éppen nagyon is zavaró. Az IGMP snoopinggal felvértezett switchek megértik a multicast hostok és az IGMP querier közötti IGMP üzenetváltásokat, és pontosan tudják, hogy egy adott pillanatban melyik portjuk mely multicast streamekre van feliratkozva, így nem árasztják el a teljes LAN-t, célzottan jutnak el a multicast csomagok a végállomásokra.

WAN oldalon a dinamikus multicast routing hiánya okozhat kényelmetlenséget, az smcroute-ot, és a vele járó statikus multicast útvonalakat ennek megfelelően olyan helyeken érdemes alkalmazni, ahol viszonylag kevés hostra kell eljuttatni a multicast streamünket. Az smcroute teszteléséhez a létező legegyszerűbb, a valódi környezetketől nem túlságosan távoli multicast tesztkörnyezet a következőképp nézne ki linuxos multicast routerekkel:



IP konfiguráció a hostokon (a teszt alatt használt OS egységesen Ubuntu 12.04.1, i386):

root@bajor:~# cat /etc/network/interfaces 
auto lo eth0

iface lo inet loopback

iface eth0 inet static
address 192.168.1.100
netmask 255.255.255.0
gateway 192.168.1.1
---
root@trill:~# cat /etc/network/interfaces 
auto lo eth0 eth1

iface lo inet loopback

iface eth0 inet static
address 192.168.1.1
netmask 255.255.255.0

iface eth1 inet static
address 10.10.10.1
netmask 255.255.255.0
---
root@vulcan:~# cat /etc/network/interfaces 
auto lo eth0 eth1

iface lo inet loopback

iface eth0 inet static
address 192.168.2.1
netmask 255.255.255.0

iface eth1 inet static
address 10.10.10.2
netmask 255.255.255.0
---
root@andoria:~# cat /etc/network/interfaces 
auto lo eth0

iface lo inet loopback

iface eth0 inet static
address 192.168.2.100
netmask 255.255.255.0
gateway 192.168.2.1

A Layer3-as VPN interfészek, azaz WAN VPN kapcsolat esetünkben OpenVPN „tun” tunnelt jelent a „trill” és a „vulcan” hoston, PSK-val. Először generáljuk le a PSK-t:

root@trill:~# cd /etc/openvpn/
root@trill:/etc/openvpn# openvpn --genkey --secret s2stunnel.psk
root@trill:/etc/openvpn# cat s2stunnel.psk
#
# 2048 bit OpenVPN static key
#
-----BEGIN OpenVPN Static key V1-----
06d0ae16e16150f850462271490e1055
e0c516af702ccf95986660889f4f02ee
0abe658cebb12b326e32214a659ba70f
ee79a55158526101ed6c6477d05a03e7
40293591d110af3c45801f537c41d71b
59304d171084e6f174e44aba2c32766b
6a88b617a6ca8e0e371f040858c289ed
b83a5c943030ec4758065ee556a458f3
ce266b42e956a5c867586fde20f4d51a
396ebdade3f55d27fe12aa184b134298
aeaa91fdaf40f2d80bcb001969608c94
9daae5a2bbf03149b93cf076b80532cd
eb68c84c314bfc0eae8ba008c19a00f9
425b80005fb26e7bc2140442794813ec
e2718ce0df00f17473ac23561c4fd088
987f8ffb9864e448fb0f6a18d170bf2c
-----END OpenVPN Static key V1-----

Ezt a fájlt másoljuk át a „vulcan” ugyanezen a könyvtárba, úgy, hogy közben lehetőleg ne publikáljuk az interneten a PSK-t, majd folytathatjuk a „trill” konfigurációját a tunnel beállításával:

root@trill:/etc/openvpn# cat s2stunnel.conf 
daemon
verb            3
#ubuntu openvpn init script handles this:
#writepid       /var/run/openvpn-s2stunnel.pid
#ubuntu openvpn init script handles this:
#status         /var/run/openvpn-s2stunnel.status 30
log             /var/log/openvpn-s2stunnel.log
log-append      /var/log/openvpn-s2stunnel.log
dev-type        tun
dev             tun1
ping            10
ping-restart    60
ifconfig        172.31.255.1 172.31.255.2
local           10.10.10.1
lport           1194
remote          10.10.10.2
rport           1194
route           192.168.2.0 255.255.255.0
cipher          bf-cbc
keysize         128
auth            sha1
secret          /etc/openvpn/s2stunnel.psk

A „vulcan”-on egy nagyon hasonló konfigurációs fájlt kell összeállítanunk, figyelve arra, hogy a helyi és a távoli IP-k, subnetek értelemszerűen változzanak. Ha készen vagyunk, indítsuk újra mindkét VPN gateway-en az OpenVPN szolgáltatást a „service openvpn restart” paranccsal. Ne feledjük az IP forwarding engedélyezését a procfs-en keresztül; amennyiben mindent jól csináltunk, kapunk egy új, „tun1” nevű, multicastra képes virtuális interfészt mindkét gépen, és a két „tun1” IP tudja pingelni egymást:

root@trill:/# ifconfig tun1
tun1      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inet addr:172.31.255.1  P-t-P:172.31.255.2  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:7 errors:0 dropped:0 overruns:0 frame:0
          TX packets:7 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100 
          RX bytes:588 (588.0 B)  TX bytes:588 (588.0 B)

Ezzel eljutottunk a tulajdonképpeni témához, a multicast routeolás beállításához. Linux alatt ehhez a funkcióhoz egy multicast routing démont kell telepíteni, amennyire tudom, összesen három ilyen szoftver létezik Linuxra, az „mrouted” (DVMRP), a „pimd” (PIM) és az „smcroute”. Egyszerre csak egy multicast routing démon futhat, teljesen felesleges mindegyiket felpakolni. Az „smcroute” sajátossága, hogy egyáltalán nem dinamikus, nem valósít meg semmilyen multicast routing protokollt, így a démon elindulása után nekünk magunknak kell kézzel felvennünk a multicast útvonalakat.

Ubuntuban az smcroute az „apt-get install smcroute” paranccsal telepíthető. Sajnálatos hiányosságnak érzem az aktuális LTS-ben, hogy az alapértelmezett repóból feltett csomag SEGFAULT-tal elszáll, amint egynél több multicast képes interfészt talál a rendszeren -- ez némiképp megnehezíti a rendeltetésszerű használatát. Remélhetőleg a problémát hamarosan javítani fogják, a teszt alatt egyszerűen lecseréltem az "/usr/sbin/smcroute" binárist egy saját fordítású, friss, 1.99-es verziójú binárisra, de minden mást meghagytam a repóból feltett csomagból.

Amennyiben fut a multicast démon (service smcroute start), azonnal életre kelnek a procfs-en a multicastos virtuális fájlok, a /proc/net/ip_mr_vif például tartalmazza a multicastra fogható interfészek jellemzőit:

root@trill:/# cat /proc/net/ip_mr_vif 
Interface  BytesIn  PktsIn  BytesOut PktsOut Flags Local    Remote
 0 eth0          0       0         0       0 00000 0101A8C0 00000000
 1 eth1          0       0         0       0 00000 010A0A0A 00000000
 2 tun1          0       0         0       0 00000 01FF1FAC 00000000

Mindössze annyi dolgunk marad még, hogy felvegyük a megfelelő helyre mutató multicast route-okat a „trill”-en és persze a „vulcan”-on, a következő paranccsal: „smcroute -a <in-ifname> <source-ip> <multicast-group>  <out-ifname> [<out-ifname> ...]”.

root@trill:/# smcroute -a eth0 192.168.1.100 225.1.2.3 tun1
---
root@vulcan:/# smcroute -a tun1 192.168.1.100 225.1.2.3 eth0 

A -r kapocsolóval törölhetők a korábban felvett multicast útvonalak, az éppen érvényben lévő listát pedig az ip mroute show paranccsal kérdezhetjük le. Ezzel a két statikus bejegyzéssel biztosítottuk, hogy a 192.168.1.100-as forrásról a 225.1.2.3-as csoportnak küldött adatok átjussanak a WAN-on. A következő részben a parancssorból teszteljük a megoldást.