A következő címkéjű bejegyzések mutatása: linux. Összes bejegyzés megjelenítése
A következő címkéjű bejegyzések mutatása: linux. Összes bejegyzés megjelenítése

2015-08-25

sFlow beállítása régebbi HP Procurve típusokon

Bizonyára nem én vagyok az egyetlen, aki beleszaladt már abba a problémába, hogy némelyik régebbi Layer3-as HP Procurve típuson jól láthatóan van sFlow támogatás az OS-ben, létezik például a "show sflow all" parancs is, ám konfig módban mégsincs semmilyen sflow kezdetű parancsunk. Azaz: CLI-ből lekérdezni ugyan le tudjuk az sFlow agent állapotát, beállítani viszont nem. A teljesség igénye nélkül, ilyen tudomásom szerint az összes 2800-as sorozatú eszköz, pl. a 2824-es, illetve rémlik, mintha a 2610-esen is tapasztaltam volna ugyanezt.

Szerencsére minden beállítható, de kizárólag SNMP-n keresztül, a konfiguráláshoz szükség lesz SNMP írási jogra az eszközünkhöz. Ez már önmagában is elég érdekes koncepció, tulajdonképpen olyan, mintha valaki valamit elfelejtett volna az OS fejlesztése alatt, de a dologba sikerült még egy csavart is tenniük a fejlesztőknek: ha bekonfiguráltuk a megfelelő SNMP OID-eken keresztül az sFlow-t, az akkor sem fog örökké futni, van ugyanis az sFlow destination értékek között egy folyamatosan csökkenő "Timeout" paraméter is, ami azt mutatja, hogy hány másodpercig fog még az OS adatokat küldeni az adott sFlow collector számára. A Timeout maximális értéke "10000000" szekundum, vagyis legkésőbb 115 naponként újra be kell állítani a switchet, különben befejezi a collectorral a kommunikációt. Azon pedig igazán nem érdemes csodálkozni, hogy a beállításokat a switch elfelejti újrainduláskor: lehet hozzá barkácsolni mindenféle szkripteket, nyilván célszerű ezt a feladatot ízlés szerint egy napi/heti/havi cronjobbal megoldani, és rendszeres időközönként megnövelni a "Timeout" értéket is.

Ennyi bevezető után pedig következzen egy egyszerű shellszkript, ami egy I.10.101-es OS verziót futtató HP 2824-es 20-as portján beállítja az sFlow-t a 10.10.10.10:9996-os collectorhoz:

#!/bin/sh
 
# collector: IP hexában
snmpset -v1 -cpublic 10.3.2.2 1.3.6.1.4.1.14706.1.1.4.1.6.1 x 0a0a0a0a
sleep 1

# collector: port decimálisan
snmpset -v1 -cpublic 10.3.2.2 1.3.6.1.4.1.14706.1.1.4.1.7.1 i 9996
sleep 1

# collector owner info
snmpset -v1 -cpublic 10.3.2.2 1.3.6.1.4.1.14706.1.1.4.1.2.1 s sFlow_collector
sleep 1

# hány mp-ig fusson az sflow agent a switchen (ez a max ~115 nap)
snmpset -v1 -cpublic 10.3.2.2 1.3.6.1.4.1.14706.1.1.4.1.3.1 i 10000000
sleep 1

# sampling: minden 4096. packet a 20-as porton (a .1 előtt az OID legvégén)
snmpset -v1 -cpublic 10.3.2.2 1.3.6.1.4.1.14706.1.1.5.1.4.11.1.3.6.1.2.1.2.2.1.1.20.1 i 4096
sleep 1

# polling: 20 mp a 20-as porton (a .1 előtt az OID legvégén)
snmpset -v1 -cpublic 10.3.2.2 1.3.6.1.4.1.14706.1.1.6.1.4.11.1.3.6.1.2.1.2.2.1.1.20.1 i 20
sleep 1

# port sflow enable a 20-as porton
snmpset -v1 -cpublic 10.3.2.2 1.3.6.1.4.1.14706.1.1.5.1.3.11.1.3.6.1.2.1.2.2.1.1.20.1 i 1

exit


Ha minden klappol, akkor valami ilyesmi lesz a "show sflow all" kimenete:


HP2824# sh sflow all

 sflow agent

  Version       : 1.3;HP;I.10.101
  Agent Address : 10.11.12.13

 sflow destination

  sflow                     : Enabled
  Datagrams Sent            : 4935
  Destination Address       : 10.10.10.10
  Receiver Port             : 9996
  Owner                     : sFlow_collector
  Timeout (seconds)         : 9996908
  Max Datagram Size         : 1400
  Datagram Version Support  : 5

 sflow sampling-polling

 sflow destination Enabled

 Port  | Sampling                 Dropped    | Polling
       | Enabled  Rate     Header Samples    | Enabled Interval
 ----- + -------  -------- ------ ---------- + ------- --------
 1       No       0        128    0            Yes     20
 2       No       0        128    0            Yes     20
 3       No       0        128    0            Yes     20
 4       No       0        128    0            Yes     20
 5       No       0        128    0            Yes     20
 6       No       0        128    0            Yes     20
 7       No       0        128    0            Yes     20
 8       No       0        128    0            Yes     20
 9       No       0        128    0            Yes     20
 10      No       0        128    0            Yes     20
 11      No       0        128    0            Yes     20
 12      No       0        128    0            Yes     20
 13      No       0        128    0            Yes     20
 14      No       0        128    0            Yes     20
 15      No       0        128    0            Yes     20
 16      No       0        128    0            Yes     20
 17      No       0        128    0            Yes     20
 18      No       0        128    0            Yes     20
 19      No       0        128    0            Yes     20
 20      Yes      4096     128    0            Yes     20
 21      No       0        128    0            Yes     20
 22      No       0        128    0            Yes     20
 23      No       0        128    0            Yes     20
 24      No       0        128    0            Yes     20

2013-05-13

Tikpásztor

A Tikpásztor egy nem túl szofisztikált shell és expect szkript, a MikroTik ketyerékből álló tyúkudvarok rendben tartásának lehetséges eszköze. Azonnal használatba lehet venni, szereti az öreg, az SSH kulcsokról mit sem tudó (RouterOS 2.9.13 előtti) tikokat, mivel nem igényel előzetes SSH kulcs terítést, három dolgot azonban tudnia minden egyes eszközről: a management IP címet, az admin user nevét, illetve jelszavát. Ezen kívül természetesen az SSH szolgáltatásnak futnia kell a Tikpásztor által kezelt eszközökön. A szkript nem csodaszer, csak annyira hasznos, amennyire értünk a RouterOS CLI-jéhez, összesen két dologra képes ugyanis: RouterOS parancsot futtatni sok eszközön, illetve komplett beállításmentést készíteni (licenc, export, backup) sok eszközről.

 

Függőségek

Néhány elterjedt szoftvernek telepítve kell lennie, hogy a Tikpásztor működőképes legyen, a legfontosabb ezek közül az "expect" nevű, Tcl alapú, interaktív szkriptelést támogató csomag, ami nem része az alapértelmezett telepítésnek a legtöbb Linuxon. Szükség van továbbá olyan standard eszközökre mint a "bash", az "ssh" és az "sftp".

 

Csoportok

Az első, amit tudnunk kell a Tikpásztorról, hogy csoportokban kezeli az eszközeinket. Azt, hogy mi szerint szervezzük a csoportokat, a szkript szempontjából nem fontos. Ha nincsenek különböző jellegű feladatokat ellátó eszközeink, akkor elegendő egyetlen csoportot létrehoznunk, de készíthetünk csoportot az eszközök fizikai elhelyezkedése alapján (pl. egy csoportba kerülnek az azonos telephelyen lévő Mikrotikek) vagy az eszközök funkciója alapján (pl. egy csoportba kerülnek az AP-ként funkcionáló eszközök, egy másikba pedig a routeolást végző eszközök). A csoport egy szöveges, pontosvesszővel tagolt fájl, ami nem tartalmazhat üres sorokat és kommentárokat, csupán IP-t, usernevet és jelszót minden egyes sorban:

192.168.0.1;admin;bejohetsz
192.168.0.2;
admin;password
192.168.0.3;admin;admin


A csoport neve az lesz, amilyen néven elmentjük a fájlt, azzal az apró megkötéssel, hogy tartalmaznia kell a "csoport" prefixet, tehát "csoport.AP", "csoport.szamvitel", stb.

 

Felhasználónevek

Előre különösnek tűnik, de a felhasználónevekhez lehet hozzácsapni a RouterOS SSH login alkalmával, hogy miképp kezelje a konzolt a RouterOS, legyenek-e színek, hány sor, hány oszlop, detektáljon-e és társaik. Ha tudjuk a tikokról, hogy nem túl régiek, 4-es, 5-ös RouterOS-t futtatnak, akkor bátran véssük be a felhasználónév mögé, a "+ct" karaktersort a csoportfájlban, pl:

192.168.0.1;admin+ct;bejohetsz

A felhasználónév ettől még ugyanaz marad, csupán a login során átpasszolunk két olyan paramétert a RouterOS-nek, amelyek segítik az expect szkriptek és a RouterOS közötti együttműködést. Ez a funkció a 3-as RouterOS szériában mutatkozott be, 2-es verziókon viszont semmiképp ne használjuk, mert ott a felhasználónév részeként fogja kezelni a RouterOS a plusz karaktereket.

 

Használat

A csoportfájlok feltöltése után a Tikpásztor azonnal használható. A "tikpasztor.sh" legyen ugyanabban a könyvtárban, ahol a csoportfájlok, a /tmp könyvtáron pedig legyen írási jogunk, és már mehet is. A szkriptnek két  működési módja van, az egyikben az első paraméterként megadott csoport minden egyes eszközén a második paraméterben megadott RouterOS parancsot fogja lefuttatni:

root@tesztgep:~/mikrotik# ./tikpasztor.sh teszt "/system license print"

 * "teszt" csoport (3 eszköz)
 * "/system license print" RouterOS parancs

Folytatod (i/n)? i

###### 192.168.0.1 START #########################################################
spawn ssh -l admin 192.168.0.1
admin@192.168.0.1's password:

  MMM      MMM       KKK                          TTTTTTTTTTT      KKK
  MMMM    MMMM       KKK                          TTTTTTTTTTT      KKK
  MMM MMMM MMM  III  KKK  KKK  RRRRRR     OOOOOO      TTT     III  KKK  KKK
  MMM  MM  MMM  III  KKKKK     RRR  RRR  OOO  OOO     TTT     III  KKKKK
  MMM      MMM  III  KKK KKK   RRRRRR    OOO  OOO     TTT     III  KKK KKK
  MMM      MMM  III  KKK  KKK  RRR  RRR   OOOOOO      TTT     III  KKK  KKK

  MikroTik RouterOS 2.9.50 (c) 1999-2007       http://www.mikrotik.com/

Terminal xterm detected, using multiline input mode
[admin@MikroTik1] > /system license print
    software-id: "K8FN-PTT"
  upgradable-to: v4.x
         nlevel: 4
       features:
[admin@MikroTik1] > /quit
Connection to 192.168.0.1 closed.
########################################################## 192.168.0.1 STOP ######
Nyomj meg egy gombot a folytatáshoz...


###### 192.168.0.2 START #########################################################
spawn ssh -l admin+ct 192.168.0.2
admin@192.168.0.2's password:

  MMM      MMM       KKK                          TTTTTTTTTTT      KKK
  MMMM    MMMM       KKK                          TTTTTTTTTTT      KKK
  MMM MMMM MMM  III  KKK  KKK  RRRRRR     OOOOOO      TTT     III  KKK  KKK
  MMM  MM  MMM  III  KKKKK     RRR  RRR  OOO  OOO     TTT     III  KKKKK
  MMM      MMM  III  KKK KKK   RRRRRR    OOO  OOO     TTT     III  KKK KKK
  MMM      MMM  III  KKK  KKK  RRR  RRR   OOOOOO      TTT     III  KKK  KKK

  MikroTik RouterOS 5.25 (c) 1999-2013       http://www.mikrotik.com/

[admin@MikroTik2] > /system license print
    software-id: H0N3-48VJ
  upgradable-to: v7.x
         nlevel: 4
       features:
[admin@MikroTik2] > /quit
interrupted
Connection to 192.168.0.2 closed.
########################################################## 192.168.0.2 STOP ######
Nyomj meg egy gombot a folytatáshoz...


###### 192.168.0.3 START #########################################################
spawn ssh -l admin+ct 192.168.0.3
admin+ct@192.168.0.3's password:

  MMM      MMM       KKK                          TTTTTTTTTTT      KKK
  MMMM    MMMM       KKK                          TTTTTTTTTTT      KKK
  MMM MMMM MMM  III  KKK  KKK  RRRRRR     OOOOOO      TTT     III  KKK  KKK
  MMM  MM  MMM  III  KKKKK     RRR  RRR  OOO  OOO     TTT     III  KKKKK
  MMM      MMM  III  KKK KKK   RRRRRR    OOO  OOO     TTT     III  KKK KKK
  MMM      MMM  III  KKK  KKK  RRR  RRR   OOOOOO      TTT     III  KKK  KKK

  MikroTik RouterOS 5.25 (c) 1999-2013       http://www.mikrotik.com/

[admin@MikroTik3] > /system license print
    software-id: RGED-3LWV
  upgradable-to: v6.x
         nlevel: 4
       features:
[admin@MikroTik3] > /quit
interrupted
Connection to 192.168.0.3 closed.
########################################################## 192.168.0.3 STOP ######
Nyomj meg egy gombot a folytatáshoz...


root@tesztgep:~/mikrotik# 

Mielőtt egyszerre levágnánk az összes MikroTik eszközünket, javasolt átolvasni, hogy melyik csoportra, milyen parancsot futtatunk, ezt annyiban segíti a szkript, hogy futás előtt rákérdez, hogy valóban folytatni szeretnénk-e. Pozitív válasz esetén a csoportban lévő minden egyes eszközre, egymás után, for ciklusban ráereszti azt az expect szkriptet, ami bejelentkezik SSH-n, majd lefuttatja a megadott parancsot.

A másik működési mód mentést készít az eszközről. A mentés három dolog mentését jelenti, a RouterOS szoftverlicenc-klucsát, egy "/export" paranccsal készített szöveges konfigurációs fájlt, illetve egy "/system backup save" paranccsal készített bináris konfig mentést. Ez utóbbit csak azon az eszközön lehet visszaállítani ahol készült, míg az "/export" kimenete némi mókolást követően más MikroTiken is behúzható. A mentés során a MikroTikek flash memóriáján a három mentett dolognak megfelelő három fájl jön létre, egy ".key" kiterjesztésű fájl a licenckulccsal, egy ".rsc" fájl az exporttal, és egy ".backup" kiterjesztésű bináris fájl. A fájlok lementése SSH/SFTP protokollon keresztül történik, majd a másolás végeztével törlődnek is az eszközről. A mentés menete:

root@tesztgep:~/mikrotik# ./tikpasztor.sh teszt BACKUP
###### 192.168.0.1 START #########################################################
spawn ssh -l admin 192.168.0.1
admin@192.168.0.1's password: 

  MMM      MMM       KKK                          TTTTTTTTTTT      KKK
  MMMM    MMMM       KKK                          TTTTTTTTTTT      KKK
  MMM MMMM MMM  III  KKK  KKK  RRRRRR     OOOOOO      TTT     III  KKK  KKK
  MMM  MM  MMM  III  KKKKK     RRR  RRR  OOO  OOO     TTT     III  KKKKK
  MMM      MMM  III  KKK KKK   RRRRRR    OOO  OOO     TTT     III  KKK KKK
  MMM      MMM  III  KKK  KKK  RRR  RRR   OOOOOO      TTT     III  KKK  KKK

  MikroTik RouterOS 2.9.50 (c) 1999-2007       http://www.mikrotik.com/

Terminal xterm detected, using multiline input mode
[admin@MikroTik1] > /system license output

[admin@MikroTik1] > /system backup save name=2013-05-13
Saving system configuration
Configuration backup saved
[admin@MikroTik1] > /export file=2013-05-13
[admin@MikroTik1] > /quit
Connection to 192.168.0.1 closed.

FÁJLOK MENTÉSE:
spawn sftp admin@192.168.0.1
admin@192.168.0.1's password: 
Connected to 192.168.0.1.
sftp> get ????-???*.key 2013-05-13_192.168.0.1.key
Fetching /K8FN-PTT.key to 2013-05-13_192.168.0.1.key
/K8FN-PTT.key                                                100%  203     0.2KB/s   00:00    
sftp> get 2013-05-13.backup 2013-05-13_192.168.0.1.backup
Fetching /2013-05-13.backup to 2013-05-13_192.168.0.1.backup
/2013-05-13.backup                                           100%   10KB  10.5KB/s   00:00    
sftp> get 2013-05-13.rsc    2013-05-13_192.168.0.1.rsc
Fetching /2013-05-13.rsc to 2013-05-13_192.168.0.1.rsc
/2013-05-13.rsc                                              100%   13KB  12.8KB/s   00:00    
sftp> rm ????-???*.key
Removing /K8FN-PTT.key
sftp> rm 2013-05-13.backup
Removing /2013-05-13.backup
sftp> rm 2013-05-13.rsc
Removing /2013-05-13.rsc
sftp> exit
########################################################## 192.168.0.1 STOP ###### 

A mentés során az eszközökről lementett fájlok abba a könyvtárba kerülnek, ahol a "tikpasztor.sh" található. Backup módban a szkript folyamatosan fut, amint végzett egy eszközön, azonnal kezdi a következőt a csoportból, nem igényel interakciót.

Korlátok

A szkript nem kezeli le az SSH szerverek fingerprint változását (pl. formázással egybekötött RouterOS újratelepítés után), ezt nekünk kell megtennünk. Nincs külön összesítés vagy figyelemfelhívás a szkript lefutása közben/után ha egy MikroTik eszköz elérhetetlen, csupán az SSH kliens hibaüzenetét láthatjuk ilyenkor ("No route to host"). A szkript jelen formájában Debian / Ubuntu rendszereken fut, máshol nem is próbáltam. Stb. Stb. Stb.

2012-12-28

NTP szinkron ellenőrzése

Kétségbeejtően sokat foglalkozom Linuxszal mostanában, szerencsére itt is utolér néha egy-egy érdekesebb hálózati feladat. Nemrég például arra kellett választ adnom, hogy mekkora differenciával jár tetszőleges két Linux szerver órája egymáshoz képest egy adott LAN egy adott subnetjében. Természetesen van kiépített belső NTP infrastruktúra, szóval akár csípőből megválaszolható egy ilyen kérdés azzal, hogy általában LAN esetén egy-két ms körül lehet ez az érték, annál nem valószínű, hogy több lenne az eltérés bármelyik két hoszt között, ha jól működik az NTP. Ez persze egyrészt nem pontos válasz, másrészt ha nem elég meggyőző az ember, és nincs ott a prompt válasz előkészítve, amikor mondjuk egy konferenciahívás alatt felmerül a kérdés, könnyen olyan helyzetben találhatja magát, hogy már meg is kapta az egészet feladatként.

Ebben az esetben a fókusz tehát nem azon volt, hogy mennyire pontosak az órák vmilyen abszolútnak tekinthető stratum 1-es forráshoz képest, hanem hogy az adott subnet linuxos szerverein egymáshoz képest mennyire megbízhatók a logokban és adatbázisokban található timestampek, amely feladat első lépése annak a kiderítése, hogy mennyire pontosak a rendszerórák egymáshoz képest. Az NTP implementációval érkező diagnosztikai eszközök, pl. az ntpq ezeket az adatokat csak NTP szerver - NTP kliens viszonylatban tudja megmondani, nekünk általánosabb megoldásra volt szükségünk.

Egy rövid kis megbeszélés után arra jutottunk az egyik kollégával, hogy a legegyszerűbb talán az lenne, ha valamilyen multicast programmal szórnánk az aktuális timestampet valamelyik hostról (a timestamp lenne a tartalma a multicast a UDP csomagoknak), a többi szerveren meg sniffelnénk a hálózati forgalmat ngreppel, a multicast csomagok beérkezésének timestampjét pedig a csomagban lévő timestamppel összehasonlítanánk. Utána már csak a szerepeket kell forgatni a hostok közt, ha egy teljes mátrixot szeretnénk feltölteni az eredményekkel. Persze az eredmények nem lesznek teljesen pontosak, hiszen nem az órák közti differenciát fogják mutatni, benne lesz a timestamp feldolgozási ideje, UDP + IP + Ethernet csomagolása, az Ethernet késleltetése, stb. de azért adhat egy jó közelítést az órák pontosságáról. Ha például azt találjuk majd, hogy átlagosan +10 ms körüli az eltérés az átküldött timestamp és annak sniffelési ideje között, akkor az nem lesz túl rózsás eredmény, míg mondjuk ha csak 1 ms az átlagos eltérés az imént felsorolt feldolgozási idők hozzáadódása ellenére is, akkor nyugodtan hátradőlhetünk, minden rendben (üzleti oldalról az 1 ms-os pontosság az elvárás). El is kezdtem ilyesmire alkalmas programokat keresgélni, aztán persze addig faragtam a paramétereken, míg kiderült, hogy semmilyen extra programra nincs szükség, az egész tesztet meg lehet oldani az alap Ubuntu telepítéssel érkező programokkal.

A teszthez használt "szerver", ami az aktuális időbélyeget kiteszi hálózatra, nem kell hogy bonyolultabb legyen, mint egy date és netcat parancs, multicastra sincs szükség, hiszen subneten belül ugyanúgy megteszi a broadcast is:

date +%Y/%m/%d\ %k\:%M\:%S.%N | nc -b -u 192.168.0.255 6666

A parancs az ngrep kimenetének megfelelően formázott timestamp stringet fog elküldeni a megadott broadcast cím megadott portjára. Ubuntu 10.04-ben ez működik is, a 12.04-esben viszont lecserélték a netcat csomagot az OpenBSD netcatjére, ami sajnos nem tud broadcastolni, így Precise alatt a "netcat-traditional" csomagot is telepítenünk kell. A "kliens" oldal, ami a subnet összes gépén akár párhuzamosan is futhat, az ngrep megfelelően paraméterezve:

root@betazed:~# ngrep -q -t -d eth0 port 6666
interface: eth0 (192.168.0.0/255.255.255.0)
filter: (ip or ip6) and ( port 6666 )

U 2012/12/27 23:17:54.698920 192.168.0.4:60071 -> 192.168.0.255:6666
  2012/12/27 23:17:54.698705783.


U 2012/12/27 23:18:09.858924 192.168.0.4:36778 -> 192.168.0.255:6666
  2012/12/27 23:18:09.858708142.


U 2012/12/27 23:18:13.428859 192.168.0.4:38310 -> 192.168.0.255:6666
  2012/12/27 23:18:13.428650913.


Az adatok értelmezésére érdemes némi időt fordítani, az ngrep timestamp mikroszekundumban értendő, a közvetlenül alatta lévő sor pedig az UDP payload, ahol a date parancs által a másik hoszton előállított timestamp szerepel nanoszekundumos pontossággal. Itt például látszik, hogy az időbélyeg teljes feldolgozása, hálózaton átküldése és kliens oldali feldolgozása átlagban 213 mikroszekundum volt három különböző "szerver" futtatás alkalmával. Pontosan ugyanezek a a "szerver" lefutások természetesen más eredményt adnak egy másik hosztról nézve:

root@trill:~# ngrep -q -t -d eth0 port 6666
interface: eth0 (192.168.0.0/255.255.255.0)
filter: (ip or ip6) and ( port 6666 )

U 2012/12/27 23:17:54.699099 192.168.0.4:60071 -> 192.168.0.255:6666
  2012/12/27 23:17:54.698705783.

U 2012/12/27 23:18:09.859099 192.168.0.4:36778 -> 192.168.0.255:6666
  2012/12/27 23:18:09.858708142.


U 2012/12/27 23:18:13.429031 192.168.0.4:38310 -> 192.168.0.255:6666
  2012/12/27 23:18:13.428650913. 


Itt 388 mikroszekundum az átlagos eltérés a "szerver" által küldött időpont és az UDP szegmens "kliensre" beérkezésének időpontja között. Megint más lesz az eredmény egy harmadik "kliensről" vizsgálódva, ami sok tényezőtől függhet, például attól is, hogy hány switchen keresztül vezet az UDP broadcast útja, hiszen minden egyes switch hozzáadja a maga késleltetését. Rosszul járó órára akkor gyanakodhatunk, ha valamelyik hostról a küldött és fogadott adatok eredményei szignifikánsan eltérnek a többieken mértektől. A konklúzió nálunk az volt, hogy az órák egymáshoz képest meglepően pontosan járnak abban a subnetben, ahol a vizsgálatot végeztem, és a Wikipédián említett 1ms-os LAN-on elérhető NTP pontosságot messze túlteljesítjük. 

2012-10-12

Hogyan nem találtam hibát a TSharkban

Miután két napon keresztül bohóckodtam egy AWK szkripttel, ami TShark által lesniffelt, majd a TShark prokoll dekóderén áthajtott adatokat dolgoz fel, és capture file-ból már hibátlanul működött mind a TShark-os dekódolós rész, mint az AWK szkript, gondoltam ideje kipróbálni valódi környezetben is dolgot. Felkerült egy tesztrendszerre, pár módosítás a capture-t végző szkriptben, hogy valódi sniffelés legyen, ne capture fájlból olvasson, aztán mindenkit odacsődítettem, hogy na, ezt nézzétek, elkészült, és... kopp. Nem megy. Á... igen, rövid hegesztgetés a capture filteren, apróbb állítgatás a protokoll dekóderen, na, majd most... kopp. Még egy kis mókolgatás, és... kopp, kopp, kopp.

Egy jó másfél órás túrás után kiderült, hogy a szkript lelkének számító "tshark ... | magic.awk > /dev/tcp/1.1.1.1/1111" szerkezetű sorban (a /dev/tcp/IP/port Bash specifikus) már a legelején elkerülik a pipe-ot az adatok. Persze én a másik végéről visszafelé haladva ellenőriztem mindent, ez nem is kérdés. A probléma egyébként roppant egyszerű: capture filter használata esetén az STDOUT-ra nem ad semmit a TShark, ami nem valami szép dolog tőle. Az alábbi egyszerű példák megvilágítják, hogy mi is a gond. Tegyük fel, hogy folyamatos ICMP forgalmunk van a 192.168.0.1 és a 192.168.0.2 között.

Capture filter és pipe nélkül minden rendben:

betazed:~# tshark -i eth2
Running as user "root" and group "root". This could be dangerous.
Capturing on eth2
  0.000000 192.168.0.1 -> 192.168.0.2  ICMP Echo (ping) request
  0.000118  192.168.0.2 -> 192.168.0.1 ICMP Echo (ping) reply
  ...

Capture filterrel, de pipe nélkül is OK:

betazed:~# tshark -i eth2 icmp
Running as user "root" and group "root". This could be dangerous.
Capturing on eth2
  0.000000 192.168.0.1 -> 192.168.0.2  ICMP Echo (ping) request
  0.000103  192.168.0.2 -> 192.168.0.1 ICMP Echo (ping) reply
  ...

Capture filter nékül, pipe-pal:

betazed:~# tshark -i eth2 | grep .
Running as user "root" and group "root". This could be dangerous.
Capturing on eth2
  0.541318 192.168.0.1 -> 192.168.0.2  ICMP Echo (ping) request
  0.541418  192.168.0.2 -> 192.168.0.1 ICMP Echo (ping) reply
  ...

Capture filterrel és pipe-pal:

betazed:~# tshark -i eth2 icmp | grep .
Running as user "root" and group "root". This could be dangerous.
Capturing on eth2
^C26 packets captured

Az STDERR-re kikerül a CTRL+C megnyomása után, hogy 26 csomagot fogott a TShark. Szép, szép, de hová tette azt a 26 csomagot? A grep tutira nem nyeli le őket, hiszen ebben a formában mindent átenged, ergo meg sem kapja az STDIN-jén az adatokat. Akkor vajon mi lehet gond? Rövid töprengés után (vö. Gyalog galopp boszorkányégetős jelenet) megvan az itélet: biztosan a TShark vacak, máglyára vele. Nincs is szebb annál, mint amikor a hülyeség szorgalommal párosul, lejelentettem hibára a bugs.wireshark.org-on. Nem tudom, hogy a véletlenül kapott mágikus erejű bug ID (7777) hatására, vagy azért, mert egyébként is jól felépített szervezetet tolt a Riverbed a Wireshark alá, de húsz perc múlva volt megoldás: user error. Khm... nos, igen, körülbelül iyen "Operációs rendszerek" szeminárium első évfolyam, első félév, második alkalom szintű dologról van szó, nem tudtam, hogy az STDOUT pufferelt, és ha nincs elég sok adat a TShark kimeneten, akkor bizony sokáig a pufferben ragadnak a dolgok. Ezért abban az esetben, ha TShark van a pipe elején, "-l" kapcsolóval érdemes elindítani, akkor azonnal ürül a puffer minden egyes csomag feldolgozása után. Innen persze már működött a csoda szkriptem is, az más kérdés, hogy a végső változatban mégsem TShark-kal sniffeltem, hanem ngrep-pel, és a TShark parancssori protokoll dekódere helyett mindent AWK-val oldottam meg, nem is ez a fontos, hanem az, hogy a szakmában töltött évek száma semmilyen kapcsolatban nincs az ember valós vagy inkább vélt tévedhetetlenségével.

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.

2012-08-23

Interaktív SSH wrapper parancssorból

Egy volt kollégám többször bizonygatta, hogy SecureCRT nélkül ebben a szakmában manapság már nem lehet meglenni, hogy enélkül nem veszik komolyan az embert. Valóban, az említett program legalább akkora változást hozott a remote shell hozzáférések egyszerű kezelésében Windows alatt, mint annak idején a PuTTY. A két programot igazából nem is érdemes hasonlítgatni, annyival okosabb, szebb, modernebb a SecureCRT, hogy a PuTTY csak egyetlen területen veheti fel a versenyt vele: az árában, merthogy ez utóbbi ingyenes. Minden másban, pl. hostok csoportosítása, jelszavak megjegyzése, alapból megnyíló sessionök stb. a SecureCRT viszi a prímet.

Arról azonban sosem sikerült meggyőznöm a kollégát, hogy Linuxon azért van élet a SecureCRT-n kívül is. Persze olyan szintű dolog nincs, mint amilyen a SecureCRT, illetve azt úgy hívják, hogy SecureCRT for Linux, de azért csak fel lehet a bash-t okosítani, hogy menjen az a Tab-os kiegészítés gyakran használt hostnevekre vagy ilyesmi. Nyilván az ember elsősorban már csak SSH-t használ, meg általában parancssort, még ha Linux desktop is fut a gépen, legtöbbször a terminálablak takar ki minden mást. A GNOME 2-es környezetben volt egy klassz kis app, az "SSH Menu", az egész élhető volt, közvetlenül a panelből lehetett kiválasztani a hostokat, de a mostani új desktopokból (GNOME 3, Unity) fájóan hiányzik egy igazán ütős alkalmazás erre. A Remmina lehet, hogy egyszer jó lesz, egyáltalán nem ördögtől való ötlet egyetlen kliensben integrálni az összes hasonló célú funkciót (SSH, VNC, RDP...), de jelen állapotában a Remmina CLI-s felületek használatához meglehetősen kényelmetlen. Szóval mostanában egyre inkább kezd igaza lenni a volt kollégának.

Egészen eddig a percig. Közzéteszem ugyanis a pótolhatatlan, teljesen CLI-s, interaktív SSH indító felületet, amit csak feldobunk egy jump szerverre, és okostelefonról, Windowsról, Linuxról egyaránt használhatjuk, itt van kérem a csodálatos, hasznos, mc-kék SSH menü szkript:


Még akár felhasználónevet is választhatunk (az alapértelmezett a $USER) egy előre megadott listából, vagy beírhatunk tetszés szerinti nevet:


Khm... nos, itt nagyjából véget is ér a szkript tudása, én jelenleg egy kb. 80 hosztos listával használom, és már annyira a szívemhez nőtt, hogy el sem tudnám képzelni a napi munkát nélküle. Különösebb függősége nincs, szükség van a "dialog" csomagra, "ncurses"-re. Kód:

#!/bin/sh

if ! $(which dialog); then
   echo "Can't find \"dialog\" binary on PATH."
   exit 1
fi

SSHHOST=$(dialog --stdout --title " SSH Menu " --menu "       IP............Hostname...............Function/Description" 22 74 100 \
192.168.0.1      "domain-name-host1      Comment for host1" \
192.168.0.2      "domain-name-host2      Comment for host2" \
192.168.0.3      "domain-name-host3      Comment for host3" \
192.168.0.4      "domain-name-host4      Comment for host4" \
192.168.0.5      "domain-name-host5      Comment for host5" \
192.168.0.6      "domain-name-host6      Comment for host6" \
192.168.0.7      "domain-name-host7      Comment for host7" \
192.168.0.8      "domain-name-host8      Comment for host8" \
192.168.0.9      "domain-name-host9      Comment for host9" \
192.168.0.10     "domain-name-host10     Comment for host10" \
192.168.0.11     "domain-name-host11     Comment for host11" \
192.168.0.12     "domain-name-host12     Comment for host12" \
192.168.0.13     "domain-name-host13     Comment for host13" \
192.168.0.14     "domain-name-host14     Comment for host14" \
192.168.0.15     "domain-name-host15     Comment for host15" \
192.168.0.16     "domain-name-host16     Comment for host16" \
)

if test -z $SSHHOST; then
   exit 1
fi

REMOTEUSR=$(dialog --stdout --title " Select remote user name " --menu "If you would like to type in a username select \"Cancel\"" 15 40 10 \
$USER "" \
root "" \
admin "" \
cisco "" \
vyatta "" \
)

if test -z $REMOTEUSR; then
   REMOTEUSR=$(dialog --stdout --title " Enter remote user name " --inputbox "" 7 40 )
fi

if test -z $REMOTEUSR; then
   exit 1
fi

clear
exec ssh -l $REMOTEUSR $SSHHOST

2012-03-21

Egymásba ágyazott ismétlődések kezelése TShark field print opciókkal

Tegyük fel, hogy szkriptet kell írnunk, ami valamiféle statisztikát készít mondjuk IPIP vagy GRE tunnelezett forgalomról. Mintának egyből használhatjuk a packetlife.net-ről a GRE.cap-ot. A tunnel ebben az esetben a 10.0.0.1 és a 10.0.0.2 közt van kihúzva, a tunnelen belül pedig az 1.1.1.1 és a 2.2.2.2 kommunikál egymással:


Ha mindezt CLI-ben szeretnénk feldolgozni, akkor persze TSharkra lesz szükség, és egy kicsit állítgatni kell az alapértelmezett outputon. Egyszerűsítsük le a végletekig a dolgot, csak a forrás, illetve a cél IP-ket jelenítsük meg:
karsair@betazed:~$ tshark -r GRE.cap -T fields -e ip.src -e ip.dst -E separator=\;
1.1.1.1;2.2.2.2
2.2.2.2;1.1.1.1
1.1.1.1;2.2.2.2
2.2.2.2;1.1.1.1
1.1.1.1;2.2.2.2
2.2.2.2;1.1.1.1
1.1.1.1;2.2.2.2
2.2.2.2;1.1.1.1
1.1.1.1;2.2.2.2
2.2.2.2;1.1.1.1
Nos, ez nem egészen az, amire szükség van, hiszen itt csak a GRE payload IP-k látszanak, azaz az ip.src és az ip.dst mezők utolsó előfordulásai minden egyes keretben. Ettől többet sajnos nem is várhatunk egészen a Wireshark 1.6-os verziójáig. Az új stabil Wireshark ágban azonban már gondoltak a rekurzivitás barátaira, új opciók vannak ugyanis a hasonló esetek kezelésére. Egyrészt megváltozott az alapértelmezett viselkedés a TShark-ban, -e után megadott mező összes előfordulását kilistázza a program vesszővel elválasztva:
karsair@betazed:~$ /opt/wireshark-1.6.5/bin/tshark -r GRE.cap -T fields -e ip.src \
-e ip.dst -E separator=\;
10.0.0.1,1.1.1.1;10.0.0.2,2.2.2.2
10.0.0.2,2.2.2.2;10.0.0.1,1.1.1.1
10.0.0.1,1.1.1.1;10.0.0.2,2.2.2.2
10.0.0.2,2.2.2.2;10.0.0.1,1.1.1.1
10.0.0.1,1.1.1.1;10.0.0.2,2.2.2.2
10.0.0.2,2.2.2.2;10.0.0.1,1.1.1.1
10.0.0.1,1.1.1.1;10.0.0.2,2.2.2.2
10.0.0.2,2.2.2.2;10.0.0.1,1.1.1.1
10.0.0.1,1.1.1.1;10.0.0.2,2.2.2.2
10.0.0.2,2.2.2.2;10.0.0.1,1.1.1.1
Másrészt vadonatúj field print opcióként itt az "occurrence". Az eddigi field print opciókkal be lehetett állítani, hogy legyen-e az outputban fejléc (-E header=y), a fenti példákban már bemutatott separator opcióval megadhattunk mezőelválasztó karaktert (-E separator=\;), illetve kérhettünk idézőjeleket a mező tartalma köré (pl. -E quote=d). Most viszont azt is megadhatjuk az occurrence opcióval, hogy az adott nevű mező első (f), utolsó (l) vagy összes (a) előfordulását szeretnénk látni, így akár imitálhatjuk az 1.6-os verziók előtti viselkedést (-E occurrence=l):
karsair@betazed:~$ /opt/wireshark-1.6.5/bin/tshark -r GRE.cap -T fields -e ip.src \
-e ip.dst -E separator=\; -E header=y -E quote=d -E occurrence=l
ip.src;ip.dst
"1.1.1.1";"2.2.2.2"
"2.2.2.2";"1.1.1.1"
"1.1.1.1";"2.2.2.2"
"2.2.2.2";"1.1.1.1"
"1.1.1.1";"2.2.2.2"
"2.2.2.2";"1.1.1.1"
"1.1.1.1";"2.2.2.2"
"2.2.2.2";"1.1.1.1"
"1.1.1.1";"2.2.2.2"
"2.2.2.2";"1.1.1.1"
Ami még ide tartozik, mégis kimaradt az eddigi példákból, az az aggregator field print opció, ami az -e után megadott nevű mező(k)nek az adott keretben való előfordulásait elválasztó karaktert definiálja, az alábbi példában ez a kettőspont:
karsair@betazed:~$ /opt/wireshark-1.6.5/bin/tshark -r GRE.cap -T fields -e ip.src \
-e ip.dst -E separator=\; -E quote=d -E occurrence=a -E aggregator=:
"10.0.0.1:1.1.1.1";"10.0.0.2:2.2.2.2"
"10.0.0.2:2.2.2.2";"10.0.0.1:1.1.1.1"
"10.0.0.1:1.1.1.1";"10.0.0.2:2.2.2.2"
"10.0.0.2:2.2.2.2";"10.0.0.1:1.1.1.1"
"10.0.0.1:1.1.1.1";"10.0.0.2:2.2.2.2"
"10.0.0.2:2.2.2.2";"10.0.0.1:1.1.1.1"
"10.0.0.1:1.1.1.1";"10.0.0.2:2.2.2.2"
"10.0.0.2:2.2.2.2";"10.0.0.1:1.1.1.1"
"10.0.0.1:1.1.1.1";"10.0.0.2:2.2.2.2"
"10.0.0.2:2.2.2.2";"10.0.0.1:1.1.1.1"
Eljutottunk tehát odáig, hogy a TShark egy jól konfigurálható kimentet ad a poszt elején vázolt szkript számára, az IP-ket pakolgathatjuk tömbökbe, ide-oda, számolgathatjuk, hogy melyik hányszor fordult elő ilyen külső IP, amolyan belső IP mellett, de az már egy másik történet.

2012-03-14

NAT connection tracking naplózás Linuxon

Gyakran felmerülő probléma, hogy miképp lehet azonosítani linuxos SRC NAT mögötti gépeket megbízhatóan. Az ugye viszonylag egyértelmű, hogy címfordítást végző rendszeren valamit kezdenünk kell a kernel által vezetett conntrack táblával, amihez van egy sztenderd interfész minden Linuxon: a /proc/net/ip_conntrack-ből mindig ki lehet olvasni az éppen aktuális bejegyzéseket. Ez azonban igencsak behatárolt lehetőség. Tegyük fel, hogy percenként mentjük a táblázatot! Még így is igen könnyen lehetnek olyan NAT-olt kapcsolatok, amelyek az előző lekérdezés óta épültek ki, de azóta már kikerültek a conntrack táblázatból, ezért a percenkénti logjainkban semmilyen nyomuk nem marad, arról nem is beszélve, hogy rengeteg felesleges információt is eltárolunk, mert a conntrack bejegyzések jelentős része - a megnyitott, kiépített TCP sessionök - tipikusan több percen át élnek, és ezeket mindig újra és újra tárolgatjuk a percenkénti logokban.

Jobb lenne az eseményalapú megközelítés, csak akkor naplózni a conntrack bejegyzéseket, ha új kapcsolat épül ki, vagy ha az adott conntrack bejegyzés kikerül a conntrack táblázatból. Szerencsére ilyesmi létezik Linuxra, a szoftvercsomag neve conntrack-tools, a benne lévő eszközök pedig kiváló, dinamikus, userspace interfészt biztosítanak a kernel conntrack táblájához. A csomag két fontos eleme a conntrack és a conntrackd nevű program. Az előbbivel listázni, naplózni, létrehozni, módosítani, törölni lehet conntrack bejegyzéseket, az utóbbi (a démon) pedig redundáns NAT rendszerek közt képes a conntrack információk szinkronizálására. A conntrack naplózás tesztjéhez az alábbi topológiát használtam:



A "denobula" beállításait nem vittem túlzásba, egy teljesen alap Ubuntu 10.04 LTS telepítést kell elképzelni, ahol két paranccsal beállítható a 10.1.1.0/24 subnetből érkező csomagok forráscímeinek NAT-olása az eth0-ra aggatott külső IP-re, feltételezve, hogy az alapértelmezett ACCEPT iptables policy-ket senki és semmi nem állította át:
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o eth0 -s 10.1.1.0/24 -j MASQUERADE
Az interfészeket kell még beállítani, az /etc/network/interfaces fájlba kerüljenek a következők:
auto lo eth0 eth1

iface lo inet loopback

iface eth0 inet static
address 10.0.2.15
netmask 255.255.255.0
gateway 10.0.2.2

iface eth1 inet static
address 10.1.1.1
netmask 255.255.255.0
Majd állítsuk be a DNS-t, végül húzzuk fel az interfészeket (újraindítás után ez már az init alatt megtörténik az előbbi auto bejegyzés miatt):
echo "nameserver 8.8.8.8" > /etc/resolv.conf
ifup eth0
ifup eth1
Következik a lényeg, a conntrack-tools telepítése (valójában csak a conntrack csomag szükséges ahhoz, amiről ebben a posztban szó lesz):
apt-get update
apt-get install conntrack conntrackd
A "denobula" beállítása ezzel meg is van, a tesztkörnyezetből még hiányzik a NAT mögötti kliens, az "andoria", ez bármi lehet, Live CD-s Linux, akármi, a lényeg, hogy konfiguráljunk rajta egy 10.1.1.2/24-es IP-t, majd a 10.1.1.1-et gatewaynek, valamint egy DNS szervert (pl. 8.8.8.8). Ezek után nincs más hátra, mint beröffenteni a NAT-os gépen a connttrack programot, a sok opció közül most a -E lesz az, amire szükségünk lesz, további opcióként megadtam a -o id,timestamp-et, így az egyes bejegyzések pontos időbélyege és az adott NAT-olt kacsolat belső ID-je is látszani fog a kimenetben:
root@denobula:~# conntrack -E -o id,timestamp,extended
[1331710267.511683]        [NEW] ipv4     2 tcp      6 120 SYN_SENT src=10.1.1.2 dst=74.125.232.247 sport=39059 dport=80 [UNREPLIED] src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39059 id=3607679456
[1331710267.513939]        [NEW] ipv4     2 tcp      6 120 SYN_SENT src=10.1.1.2 dst=74.125.232.247 sport=39060 dport=80 [UNREPLIED] src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39060 id=3607679216
[1331710267.513992]     [UPDATE] ipv4     2 tcp      6 60 SYN_RECV src=10.1.1.2 dst=74.125.232.247 sport=39059 dport=80 src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39059 id=3607679456
[1331710267.514021]     [UPDATE] ipv4     2 tcp      6 60 SYN_RECV src=10.1.1.2 dst=74.125.232.247 sport=39060 dport=80 src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39060 id=3607679216
[1331710267.514047]     [UPDATE] ipv4     2 tcp      6 432000 ESTABLISHED src=10.1.1.2 dst=74.125.232.247 sport=39059 dport=80 src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39059 [ASSURED] id=3607679456
[1331710267.514076]     [UPDATE] ipv4     2 tcp      6 432000 ESTABLISHED src=10.1.1.2 dst=74.125.232.247 sport=39060 dport=80 src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39060 [ASSURED] id=3607679216
[1331710272.506759]     [UPDATE] ipv4     2 tcp      6 120 FIN_WAIT src=10.1.1.2 dst=74.125.232.247 sport=39060 dport=80 src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39060 [ASSURED] id=3607679216
[1331710272.507065]     [UPDATE] ipv4     2 tcp      6 60 CLOSE_WAIT src=10.1.1.2 dst=74.125.232.247 sport=39060 dport=80 src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39060 [ASSURED] id=3607679216
[1331710272.507135]     [UPDATE] ipv4     2 tcp      6 30 LAST_ACK src=10.1.1.2 dst=74.125.232.247 sport=39060 dport=80 src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39060 [ASSURED] id=3607679216
[1331710272.507208]     [UPDATE] ipv4     2 tcp      6 120 TIME_WAIT src=10.1.1.2 dst=74.125.232.247 sport=39060 dport=80 src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39060 [ASSURED] id=3607679216
A kimenetben megtalálhatók a kért paraméterek, az első mező a timestamp, az utolsó mező a conntrack ID, a sorok egyébként elég beszédesek, minden sorban a második mező a conntrack esemény, amiből összesen három létezik, a NEW értelemszerűen egy új conntrack bejegyzés létrejöttekor generálódik, az UPDATE egy már létező bejegyzésben valamiféle változást jelez, például az UPDATE bejegyzésekben a TCP állapotátmenet-változások kiválóan követhetők. A harmadik, DESTROY nevű esemény pedig azt jelzi (a fenti példában épp nincs ilyen), hogy egy bejegyzés kikerül a conntrack táblából.

Ez a fajta eseményvezérelt kimenet már egészen közel van ahhoz, hogy használható legyen, két apróságra térnék még ki. Az első, hogy az STDOUT-ra küldött log nem tekinthető valódi log-nak, valahova át kell irányítanunk, a következő példában a tee-t használom, amivel így, ahogy van, ott lehet hagyni egy ötös vagy hatos szöveges terminálon, úgysem nyúl hozzá soha senki ;). A másik dolog, hogy általában az UPDATE eseményekre nincs szükség, hiszen az ilyesfajta logoknak az a lényege, hogy ki lehessen hámozni belőlük, hogy egy SRC NAT mögötti gép mettől meddig, milyen külső IP-vel, hová kommunikált, ehhez pedig elég a bejegyzés létrejöttét (NEW) és a bejegyzés végét (DESTROY) naplózni, ami közben történt a bejegyzéssel, nem érdekes. A "végső" NAT naplózó parancs tehát, amit természetesen ezer módon tovább lehet még fejlesztgetni, így néz ki:
conntrack -E -o id,timestamp,extended -e NEW,DESTROY | tee /var/log/ctrack.log

2012-01-24

Interfész információk Vyattán

Elképzelni is nehéz, mit össze nem keresgéltem a múltkor, hogy miképp lehet Vyatta alatt megnézni egy Ethernet interfészen a hozzá tartozó speed és duplex beállításokat. A legtöbb network OS alatt ugye ez eléggé egyértelmű, egy sima show interface vagy mondjuk 3Com/HP/Huawei vonalon egy display interface parancs kiírja, hogy 10, 100 vagy 1000 M, full vagy half duplex, auto, nem auto. A Vyatta OS azonban nem követi ezt a konvenciót, úgyhogy eddig, ha szükségem volt ilyen jellegű információra, mindig "kiléptem" a Vyatta shellből sudo -i-vel és vagy a mii-tool vagy az ethtool parancsot használtam:

root@Vyatta:~# mii-tool eth1
eth1: negotiated 1000baseT-FD flow-control, link ok


root@Vyatta:~# ethtool eth1
Settings for eth1:
        Supported ports: [ TP ]
        Supported link modes:   10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
                                1000baseT/Half 1000baseT/Full
        Supports auto-negotiation: Yes
        Advertised link modes:  10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
                                1000baseT/Half 1000baseT/Full
        Advertised pause frame use: No
        Advertised auto-negotiation: Yes
        Speed: 1000Mb/s
        Duplex: Full
        Port: Twisted Pair
        PHYAD: 1
        Transceiver: internal
        Auto-negotiation: on
        MDI-X: Unknown
        Supports Wake-on: g
        Wake-on: g
        Current message level: 0x000000ff (255)
        Link detected: yes


Szép, szép, de ezek mégiscsak linuxos parancsok, tulajdonképpen mindig is bosszantott, hogy miért nem lehet ezt a sima Vyatta shellben megnézni. Aztán persze tök véletlenül kiderült, hogy a user a béna, természetesen  benne van ez a Vyatta shellben is, csak nem egészen ott kerestem eddig, ahol kellett volna; az ethtool kimenetét adja a a következő parancs:


admin@Vyatta:~$ show interfaces ethernet eth1 physical
Settings for eth1:
        Supported ports: [ TP ]
        Supported link modes:   10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
                                1000baseT/Half 1000baseT/Full
        Supports auto-negotiation: Yes
        Advertised link modes:  10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
                                1000baseT/Half 1000baseT/Full
        Advertised pause frame use: No
        Advertised auto-negotiation: Yes
        Speed: 1000Mb/s
        Duplex: Full
        Port: Twisted Pair
        PHYAD: 1
        Transceiver: internal
        Auto-negotiation: on
        MDI-X: Unknown
        Supports Wake-on: g
        Wake-on: g
        Current message level: 0x000000ff (255)
        Link detected: yes
driver: tg3
version: 3.115
firmware-version: 5703-v2.22
bus-info: 0000:02:02.0

2011-11-16

Parancssori SNMP eszközök (5.) - STP

A korábbi részekben (első, második és harmadik) ezt-azt már kiolvasgattunk az SNMP fából, a negyedikben írtunk is bele alapvető dolgokat, a mai részben újra előveszem a BRIDGE MIB-et, van ebben ugyanis egy fontos ág, amit eddig nem érintettünk, az .1.3.6.1.2.1.17.2, azaz a dot1dStp, ami minden lényeges információt tartalmaz az eszközünkön futó feszítőfa (feszítőfák) állapotáról, illetve annak (azoknak) időbeli változásairól.

Kezdjük a Bridge ID prioritás mezőjének kiolvasásával, ennek az értéke az .1.3.6.1.2.1.17.2.2.0 OID-jű levélre van írva (dot1dStpPriority). Egyébként ez is read-write objektumként van a MIB-ben definiálva, így visszautalva az előző, snmpwrite-os részre: tényleg figyeljünk az eszközeinkre az SNMP RW jogosultságok tekintetében, legyünk rettenetesen szűkmarkúak, és ahol csak módunk van rá, használjuk az SNMP v3 titkosítási lehetőségeit. Gondoljunk csak bele, hogy mekkora galibát tud okozni egy olyan szkript, ami időnként ciklusban végigfut egy subnet minden hostján és ahol tudja, átírogatja a Bridge ID-kat... szinkronizálatlan SQL adatbázisok, szétesett clusterek, TCP sessionök véres cafatkái maradnak mindenhol a nyomában. Ehelyett mi inkább újra csak olvasunk SNMP-n keresztül:

admin@NMS:~$ snmpwalk -v1 -cpublic 10.10.10.250 .1.3.6.1.2.1.17.2.2.0
SNMPv2-SMI::mib-2.17.2.2.0 = INTEGER: 32769


Ez nagyjából minden nagyobb gyártónál hasonlóan működik, ugyanakkor vegyük azt is figyelembe, hogy nem minden gyártónál van alapból bekapcsolva az STP/RSTP/MSTP támogatás, például a HP ProCurve szériákon, így az általam teszteszközként használt 2824-esen sincs, ennek megfelelően amíg be nem kapcsoljuk az STP-t, természetesen nem lehet kiolvasni semmit erről az OID-ről. A közvetlen ezután következő két levél (dot1dStpTimeSinceTopologyChange, illetve a dot1dStpTopChanges) is informatív, ha ismeretlen rendszereket térképezünk fel:

admin@NMS:~$ snmpwalk -v1 -cpublic 10.10.10.250 .1.3.6.1.2.1.17.2.3.0
SNMPv2-SMI::mib-2.17.2.3.0 = Timeticks: (134700) 0:22:27.00

admin@NMS:~$ snmpwalk -v1 -cpublic 10.10.10.250 .1.3.6.1.2.1.17.2.4.0
SNMPv2-SMI::mib-2.17.2.4.0 = Counter32: 78


A példa szerint a 10.10.10.250 feszítőfája 22 perce változatlan és az SNMP processz elindulása óta 78 alkalommal történt a STP topológiaváltozás. Talán egy kicsit kevésbé érdekes, de legalább annyira fontos a többi adat is, ami még innen kiolvasható:

admin@NMS:~$ snmpwalk -m +BRIDGE-MIB -v1 -cpublic 10.10.10.250 .1.3.6.1.2.1.17.2
BRIDGE-MIB::dot1dStpProtocolSpecification.0 = INTEGER: ieee8021d(3)
BRIDGE-MIB::dot1dStpPriority.0 = INTEGER: 32769
BRIDGE-MIB::dot1dStpTimeSinceTopologyChange.0 = Timeticks: (255600) 0:22:36.00
BRIDGE-MIB::dot1dStpTopChanges.0 = Counter32: 78
BRIDGE-MIB::dot1dStpDesignatedRoot.0 = Hex-STRING: 00 00 00 16 E0 18 74 00
BRIDGE-MIB::dot1dStpRootCost.0 = INTEGER: 39
BRIDGE-MIB::dot1dStpRootPort.0 = INTEGER: 1
BRIDGE-MIB::dot1dStpMaxAge.0 = INTEGER: 2000
BRIDGE-MIB::dot1dStpHelloTime.0 = INTEGER: 200
BRIDGE-MIB::dot1dStpHoldTime.0 = INTEGER: 100
BRIDGE-MIB::dot1dStpForwardDelay.0 = INTEGER: 1500
BRIDGE-MIB::dot1dStpBridgeMaxAge.0 = INTEGER: 2000
BRIDGE-MIB::dot1dStpBridgeHelloTime.0 = INTEGER: 200
BRIDGE-MIB::dot1dStpBridgeForwardDelay.0 = INTEGER: 1500
...


A kimenetből megtudhatjuk, hogy az STP root egy 0 prioritású 00 16 E0 18 74 00 MAC című eszköz, ami közvetve csatlakozik csupán, 100Mbit/s-os nagyságrendű linkeken (távolság: 39, emlékeztetőül az IEEE cost értékek: 100 - 10Mb/s, 19 - 100Mb/s, 4 - 1Gb/s, 2 - 10Gb/s) a port 1-en keresztül, illetve láthatjuk az STP időzítési adatait. Ezek után egy táblázat következik (dot1dStpPortTable, 1.3.6.1.2.1.17.2.15) az egyes portok STP állapotairól, a porthoz társított költségekről stb. amit csak három ponttal jelöltem, hiszen ahhoz külön parancs dukál:

admin@NMS:~$ snmptable -m +BRIDGE-MIB -Cl -Cb -v1 -cpublic 172.17.136.250 .1.3.6.1.2.1.17.2.15

Ám ezzel még nincs vége, a legtöbb eszköz, ha képes per VLAN STP-re, MSTP-re akkor is belegyömöszöli az egyes portok státusz információit egyetlen .1.3.6.1.2.1.17.2, azaz dot1dStp ágba, ami időnként félrevezető lehet, hiszen elvileg előfordulhat olyan eset mondjuk, hogy a VLAN1-en egy adott port forwarding státuszban van, míg mondjuk VLAN2-ben pedig blokkol. A Cisco eszközökön ez a dilemma megintcsak a VLAN ID alapján indexelt community stringekkel, illetve a VLAN-onként külön nyilvántartott BRIDGE MIB adatokkal van feloldva, így nem mindegy, hogy a community stringünk public (=public@1) vagy éppen public@2, hiszen az első a VLAN1-ben futogató feszítőfa adatairól ad információkat, a másik pedig a VLAN2-es feszítőfáról:

admin@NMS:~$ snmpwalk -m +BRIDGE-MIB -v1 -cpublic 172.17.136.250 .1.3.6.1.2.1.17.2
BRIDGE-MIB::dot1dStpProtocolSpecification.0 = INTEGER: ieee8021d(3)
BRIDGE-MIB::dot1dStpPriority.0 = INTEGER: 32769
BRIDGE-MIB::dot1dStpTimeSinceTopologyChange.0 = Timeticks: (491200) 1:21:52.00
BRIDGE-MIB::dot1dStpTopChanges.0 = Counter32: 78
BRIDGE-MIB::dot1dStpDesignatedRoot.0 = Hex-STRING: 00 00 00 16 E0 18 74 00
BRIDGE-MIB::dot1dStpRootCost.0 = INTEGER: 39
BRIDGE-MIB::dot1dStpRootPort.0 = INTEGER: 1
BRIDGE-MIB::dot1dStpMaxAge.0 = INTEGER: 2000
BRIDGE-MIB::dot1dStpHelloTime.0 = INTEGER: 200
BRIDGE-MIB::dot1dStpHoldTime.0 = INTEGER: 100
BRIDGE-MIB::dot1dStpForwardDelay.0 = INTEGER: 1500
BRIDGE-MIB::dot1dStpBridgeMaxAge.0 = INTEGER: 2000
BRIDGE-MIB::dot1dStpBridgeHelloTime.0 = INTEGER: 200
BRIDGE-MIB::dot1dStpBridgeForwardDelay.0 = INTEGER: 1500
BRIDGE-MIB::dot1dStpPort.1 = INTEGER: 1
BRIDGE-MIB::dot1dStpPort.45 = INTEGER: 45
BRIDGE-MIB::dot1dStpPortPriority.1 = INTEGER: 128
BRIDGE-MIB::dot1dStpPortPriority.45 = INTEGER: 128
BRIDGE-MIB::dot1dStpPortState.1 = INTEGER: forwarding(5)
BRIDGE-MIB::dot1dStpPortState.45 = INTEGER: forwarding(5)
BRIDGE-MIB::dot1dStpPortEnable.1 = INTEGER: enabled(1)
BRIDGE-MIB::dot1dStpPortEnable.45 = INTEGER: enabled(1)
BRIDGE-MIB::dot1dStpPortPathCost.1 = INTEGER: 19
BRIDGE-MIB::dot1dStpPortPathCost.45 = INTEGER: 19
BRIDGE-MIB::dot1dStpPortDesignatedRoot.1 = Hex-STRING: 00 00 00 16 E0 18 74 00
BRIDGE-MIB::dot1dStpPortDesignatedRoot.45 = Hex-STRING: 00 00 00 16 E0 18 74 00
BRIDGE-MIB::dot1dStpPortDesignatedCost.1 = INTEGER: 20
BRIDGE-MIB::dot1dStpPortDesignatedCost.45 = INTEGER: 39
BRIDGE-MIB::dot1dStpPortDesignatedBridge.1 = Hex-STRING: 80 00 00 1A C1 56 10 40
BRIDGE-MIB::dot1dStpPortDesignatedBridge.45 = Hex-STRING: 80 01 00 23 AC 33 3B 00
BRIDGE-MIB::dot1dStpPortDesignatedPort.1 = Hex-STRING: 80 DE
BRIDGE-MIB::dot1dStpPortDesignatedPort.45 = Hex-STRING: 80 2D
BRIDGE-MIB::dot1dStpPortForwardTransitions.1 = Counter32: 1
BRIDGE-MIB::dot1dStpPortForwardTransitions.45 = Counter32: 1
 

admin@NMS:~$ snmpwalk -m +BRIDGE-MIB -v1 -cpublic@2 172.17.136.250 .1.3.6.1.2.1.17.2
BRIDGE-MIB::dot1dStpProtocolSpecification.0 = INTEGER: ieee8021d(3)
BRIDGE-MIB::dot1dStpPriority.0 = INTEGER: 32770
BRIDGE-MIB::dot1dStpTimeSinceTopologyChange.0 = Timeticks: (4994600) 13:52:26.00
BRIDGE-MIB::dot1dStpTopChanges.0 = Counter32: 0
BRIDGE-MIB::dot1dStpDesignatedRoot.0 = Hex-STRING: 00 00 00 16 E0 18 74 00
BRIDGE-MIB::dot1dStpRootCost.0 = INTEGER: 39
BRIDGE-MIB::dot1dStpRootPort.0 = INTEGER: 3
BRIDGE-MIB::dot1dStpMaxAge.0 = INTEGER: 2000
BRIDGE-MIB::dot1dStpHelloTime.0 = INTEGER: 200
BRIDGE-MIB::dot1dStpHoldTime.0 = INTEGER: 100
BRIDGE-MIB::dot1dStpForwardDelay.0 = INTEGER: 1500
BRIDGE-MIB::dot1dStpBridgeMaxAge.0 = INTEGER: 2000
BRIDGE-MIB::dot1dStpBridgeHelloTime.0 = INTEGER: 200
BRIDGE-MIB::dot1dStpBridgeForwardDelay.0 = INTEGER: 1500
BRIDGE-MIB::dot1dStpPort.3 = INTEGER: 3
BRIDGE-MIB::dot1dStpPortPriority.3 = INTEGER: 128
BRIDGE-MIB::dot1dStpPortState.3 = INTEGER: forwarding(5)
BRIDGE-MIB::dot1dStpPortEnable.3 = INTEGER: enabled(1)
BRIDGE-MIB::dot1dStpPortPathCost.3 = INTEGER: 19
BRIDGE-MIB::dot1dStpPortDesignatedRoot.3 = Hex-STRING: 00 00 00 16 E0 18 74 00
BRIDGE-MIB::dot1dStpPortDesignatedCost.3 = INTEGER: 20
BRIDGE-MIB::dot1dStpPortDesignatedBridge.3 = Hex-STRING: 80 00 00 1A C1 56 10 40
BRIDGE-MIB::dot1dStpPortDesignatedPort.3 = Hex-STRING: 80 D9
BRIDGE-MIB::dot1dStpPortForwardTransitions.3 = Counter32: 1

2011-10-31

Parancssori SNMP eszközök (4.) - snmpset

Az első, második és harmadik részben hol keveset, hol sokat, de mindig csak olvastuk az adatokat az SNMP fából, pedig ez olyan, mint a karácsonyfa, nem csak szedegetni lehet róla a dolgokat, de ráaggatni is. Természetesen van parancssori eszköz erre is, snmpset a program neve, és éppúgy a Net-SNMP csomag része, mint az snmpget, az snmpwalk, snmptable.

Az snmpset néhány paraméterrel többet igényel mint az egyéb eszközök. Az első és talán a legfontosabb különbség, hogy olyan community stringet kell megadnunk neki, amellyel írni is lehet a fába. Tipikusan az alapértelmezett RO string a "public" szokott lenni, az alapértelmezett RW string pedig a "private". Ökölszabály, hogy soha nem használjuk az RW stringet (főleg SNMPv1 és SNMPv2 esetén), csak akkor, amikor tényleg írunk is a fába -- de erre még később visszatérünk. Persze önmagában a community string nem elég, pontosan meg kell adnunk, hogy hol, illetve azt is, hogy milyen típusú adatot szeretnénk tárolni. A következő példában egy Nortel 5510-esen a system ágat kilistázzuk, majd átírjuk az egyik levelét és újra kilistázzuk:

admin@NMS:~$ snmpwalk -v1 -cpublic 10.10.10.1 system
SNMPv2-MIB::sysDescr.0 = STRING: Ethernet Routing Switch 5510-24T  HW:32  FW:4.2.0.12  SW:v4.2.0.002
SNMPv2-MIB::sysObjectID.0 = OID: SNMPv2-SMI::enterprises.45.3.52.1
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (1132653378) 131 days, 2:15:33.78
SNMPv2-MIB::sysContact.0 = STRING: Telecom Team
SNMPv2-MIB::sysName.0 = STRING: TESTSW-01
SNMPv2-MIB::sysLocation.0 = STRING: Testlab
SNMPv2-MIB::sysServices.0 = INTEGER: 3


admin@NMS:~$ snmpset -v1 -cprivate 10.10.10.1 SNMPv2-MIB::sysContact.0 s NINCS
SNMPv2-MIB::sysContact.0 = STRING: NINCS


admin@NMS:~$ snmpwalk -v1 -cpublic 10.10.10.1 system
SNMPv2-MIB::sysDescr.0 = STRING: Ethernet Routing Switch 5510-24T  HW:32  FW:4.2.0.12  SW:v4.2.0.002
SNMPv2-MIB::sysObjectID.0 = OID: SNMPv2-SMI::enterprises.45.3.52.1
DISMAN-EVENT-MIB::sysUpTimeInstance =
Timeticks: (1132667603) 131 days, 2:17:56.03
SNMPv2-MIB::sysContact.0 = STRING: NINCS
SNMPv2-MIB::sysName.0 = STRING: TESTSW-01
SNMPv2-MIB::sysLocation.0 = STRING: Testlab
SNMPv2-MIB::sysServices.0 = INTEGER: 3


Az snmpset paraméterei a példa alapján nagyjából egyértelműek lehetnek, az egyetlen kérdéses elem az az adattípus megadása, ez közvetlenül az érték előtt szerepel a parancssori paramétereinkben, ami esetünkben egy "s", azaz string érték volt. Értelemszerűen egy adott OID-be csak a MIB-ben definiált típusú adatot tudunk beírni. Az egyéb lehetséges típusok felsorolása az snmpset --help outputjának a végéről:

  TYPE: one of i, u, t, a, o, s, x, d, b
    i: INTEGER, u: unsigned INTEGER, t: TIMETICKS, a: IPADDRESS
    o: OBJID, s: STRING, x: HEX STRING, d: DECIMAL STRING, b: BITS
    U: unsigned int64, I: signed int64, F: float, D: double


Nem csak a típuson csúszhat meg az írás. Vannak ugyanis a fában igen terbélyes ágak, ahová egyáltalán nem írhatunk be semmit, még RW community stringgel sem, ezen OID-k esetén a MIB-ben a MAX-ACCESS tulajdonság "read-only" értékű, így a felülírásuk nem lehetséges, például nem tudjuk átírni egyebek mellett az interfészek neveit sem, pedig a string mint adattípus stimmelne:

admin@NMS:~$ snmpwalk -v1 -cpublic 10.10.10.1 IfName
IF-MIB::ifName.1 = STRING: ifc1 (Slot: 1 Port: 1)
IF-MIB::ifName.2 = STRING: ifc2 (Slot: 1 Port: 2)
IF-MIB::ifName.3 = STRING: ifc3 (Slot: 1 Port: 3)
IF-MIB::ifName.4 = STRING: ifc4 (Slot: 1 Port: 4)
IF-MIB::ifName.5 = STRING: ifc5 (Slot: 1 Port: 5)
IF-MIB::ifName.6 = STRING: ifc6 (Slot: 1 Port: 6)
IF-MIB::ifName.7 = STRING: ifc7 (Slot: 1 Port: 7)
IF-MIB::ifName.8 = STRING: ifc8 (Slot: 1 Port: 8)
IF-MIB::ifName.9 = STRING: ifc9 (Slot: 1 Port: 9)
IF-MIB::ifName.10 = STRING: ifc10 (Slot: 1 Port: 10)
IF-MIB::ifName.11 = STRING: ifc11 (Slot: 1 Port: 11)
IF-MIB::ifName.12 = STRING: ifc12 (Slot: 1 Port: 12)
IF-MIB::ifName.13 = STRING: ifc13 (Slot: 1 Port: 13)
IF-MIB::ifName.14 = STRING: ifc14 (Slot: 1 Port: 14)
IF-MIB::ifName.15 = STRING: ifc15 (Slot: 1 Port: 15)
IF-MIB::ifName.16 = STRING: ifc16 (Slot: 1 Port: 16)
IF-MIB::ifName.17 = STRING: ifc17 (Slot: 1 Port: 17)
IF-MIB::ifName.18 = STRING: ifc18 (Slot: 1 Port: 18)
IF-MIB::ifName.19 = STRING: ifc19 (Slot: 1 Port: 19)
IF-MIB::ifName.20 = STRING: ifc20 (Slot: 1 Port: 20)
IF-MIB::ifName.21 = STRING: ifc21 (Slot: 1 Port: 21)
IF-MIB::ifName.22 = STRING: ifc22 (Slot: 1 Port: 22)
IF-MIB::ifName.23 = STRING: ifc23 (Slot: 1 Port: 23)
IF-MIB::ifName.24 = STRING: ifc24 (Slot: 1 Port: 24)
IF-MIB::ifName.10001 = STRING: ifc10001 VLAN #1
IF-MIB::ifName.10101 = STRING: ifc10101 VLAN #101
IF-MIB::ifName.10111 = STRING: ifc10111 VLAN #111
IF-MIB::ifName.10112 = STRING: ifc10112 VLAN #112
IF-MIB::ifName.11099 = STRING: ifc11099 VLAN #1099
 

admin@NMS:~$ snmpset -v1 -cprivate 10.10.10.1 IF-MIB::ifName.1 s IFACE1
Error in packet.
Reason: (noSuchName) There is no such variable name in this MIB.
Failed object: IF-MIB::ifName.1


Hiába van azonban korlátozva már MIB szinten az SNMP fába való írás, nem rohangászhatunk állandóan SNMP RW stringekkel a hálózaton, hiszen SNMP v3 alatt minden kódolatlanul jön és megy, ami a legtöbb környezetben kockázatokat hordoz. Hogy ez mennyire így van, megosztok egy konkrét példát, ami a jelenlegi H3C / HPN eszközök nagyjából két generációval ezelőtti felmenőit érinti. Konkrétan a 3Com 4000-es széria darabjairól van szó, pl. a 4050-es, 4060-as, 4070-es, 4400-as, 4900-as stb. eszközökről, amelyek kb. 2004-2006-ban számítottak frissnek a piacon. Ezeken az eszközökön alapértelmezetten létezik az "admin", a "manager" és a "monitor" nevű felhasználó, és ha emlékeim nem csalnak, akkor az SNMP is alapértelmezetten be van kapcsolva, ráadásul olyan szörnyen "valószerűtlen" alapértékekkel, mint a "public" RO és a "private" RW community string. Ha pedig ismerjük az RW stringet, akkor tudunk írni az SNMP fába, például arra a helyre is, ahol a "monitor" nevű felhasználó jelszava van:

root@NMS:~# snmpset -v1 -cprivate 10.10.10.2 .1.3.6.1.4.1.43.10.4.2.1.4.7.109.111.110.105.116.111.114 s titok
SNMPv2-SMI::enterprises.43.10.4.2.1.4.7.109.111.110.105.116.111.114 = STRING: "titok"
root@NMS:~# telnet 10.10.10.2

Entering character mode
Escape character is '^]'.

Login: monitor
Password: titok

Menu options: ---------------------3Com Switch 4070---------------------
 bridge             - Administer bridge-wide parameters
 fabric             - Administer XRN fabrics
 feature            - Administer system features
 logout             - Logout of the Command Line Interface
 physicalInterface  - Administer physical interfaces
 protocol           - Administer protocols
 system             - Administer system-level functions
 trafficManagement  - Administer traffic management

Type  ? for help
-------------------------------------TESTSW-2 (1)-----------------------
Select menu option: logout

exiting session....
Connection closed by foreign host
root@NMS:~#


Még egy érdekesség a 3Com-os felhasználónevekkel kapcsolatban, ha megnézzük az OID-t ahová írtunk, láthatjuk, hogy az OID vége az, hogy: "109.111.110.105.116.111.114". Ha most utánanézünk, hogy mi is az ASCII kódja a "monitor" egyes karaktereinek, akkor már nem is olyan nehéz kitalálni, hogyan lehet a jóval több jogosultsággal bíró "manager" felhasználó jelszavát átírni. Az "admin" OID-je egy picit különbözik, de nem sokban: