Logstash Kurulumu ve Syslog SNMPTrap Konfigürasyonu

Merhabalar,

Araya koydugumuz süreye bakinca art arda iki yazi biraz garip ama madem hazirda var biraz düzenleyip neden koymayayim 🙂

Bu yazida aslinda tam olarak herhangi bir kategoriye koyamacagim logstash’tan bahsedecegim.
Logstash: Sunucu üzerinde soketler açarak istenilen verinin toplanmasini saglayan, bu veriyi isleyen ve düzenleyen, sonunda farkli sekillerde çikti üreten bir yazilimdir. Özellikle log toplama ve bunlari isleme ile ilgili çok fazla kullanim örnegi bulunmaktadir.
Logstash’in diger syslog uygulamalarindan farkli yani konfigürasyon ve veri düzenleme kisminin oldukça esnek olmasidir. Logstash sadece bir syslog uygulamasi degil. Bir sürü farkli girdi alabilen kümülatif bir servistir. Hangi servislerin aktif edilecegin kullanicinin olusturdugu konfigürasyon dosyasindan okunur.
Logstash gelen veri üzerinde çok genis yelpazeye sahip bir filtreleme ve düzenleme imkani sunar. Veri üzerinde degisik manipülasyonlar yaparak daha anlasilir bir çikti elde etmenizi saglar.
Logstash Bilesenleri:
Logstash 3 ana kisimdan olusur. Input,Filter ve Output. 3 ana kisima yardimci bir de Codec denilen bir alt kisim vardir.
Input’lar, bize gelecek olan verinin kaynagini belirler. Bu bir dosya da olabilir bir tcp/udp port olabilir veya bilinen bir servis veya baska bir uygulamadan gelen rastgele bir veri de olabilir.
Filter’lar, gelen verinin islenmesini,düzenlenmesini,gerekli veya gereksiz kisimlarinin ayristirilip, manipüle edilmesini, veriye tanimlayici bilgiler eklenmesini saglayan kisimdir. Logstash’in en güçlü taraflarindan biridir. Kullanici filtreler ile oldukça sistematik ve düzenli bir yapi elde edebilir.
Output’lar, veriler islendikten sonra logstash’in verdigi çiktinin tanimlandigi kisimdir. Bu kisimda bildirimler olusturma, veriyi dosyaya veya veritabanina kaydetme, veriyi baska bir logstash sunucusuna gönderme gibi islemler yapilabilir.
Codec’ler ise bu 3 ana kisimda görsellik ve düzenleme açisindan yardimci olan bilesendir. Verinin okunabilirligini arttirir.
Hizlica kuruluma geçelim.
Kurulum oldukça basit tek ihtiyaci olan java yüklemesi. Yükleme yapilmadan önce www.elastic.co sitesinden hangi java sürümü ile çalstigi kotnrol edilmeli.
Bu sürümde kullanilan logstash sürümü: 5.1.2. Sunucu ise Ubuntu 14.04.
Güncel sürüm buradan indirilebilir.

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
sudo apt-get install apt-transport-https
echo "deb https://artifacts.elastic.co/packages/5.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-5.x.list
sudo apt-get update
sudo apt-get install logstash

Kurulumumuz bitti :).
Yükleme dizini /usr/share/logstash altindadir.
Varsayilan kurulumlar tüm temel konfigürasyon dosyalari
/etc/logstash/
/etc/kibana/
/etc/elasticsearch/ altinda.
Buradaki logstash.yml logstash’in tanimlayici yapilandirmasini olusturuyor.
logstash.yml
Isimlendirme ve timerler kisminda çok da degisiklik yapmaya gerek yok. Varsayilan ayarlar deb ile kurdugunuz için buna göre düzenlenmis. Degisiksik halinde bu dosya yollarini düzenlemek gerekiyor. Zaten .yml dosyalari içerisinde o konfigürasyona ait açiklamalar gayet açiklayici.
node.name: Birden fazla logstash sunucusu cluster olarak çalisiyor ise bir isim verilebilir.
path.config: Logstash’in çalisacagin konfigürasyon dizini. /etc/logstash/conf.d/
config.reload.automatic: true Logstash bu seçenek aktif edilirse belirlenen aralikta konfigürasyon dosyasini yeniden yükler. Bunu sik sik degisiklikler yapiyor iseniz veya test asamasidna iseniz açmanizda ve kontrol araligini kisa tutmada fayda var.
config.reload.interval: Konfigürasyon dosyasini kontrol etme sikligi. Saniye biriminden büyüklük.
config.debug: true Konfigürasyon dosyasinin kontrolü asamasinda yapilan islemleri detaylica ekrana veya dosyaya döker. Bu seçenek sadece log.level = debug ise çalisir.
log.level : debug Özellikle tüm konfigürasyonu tamamlayana kadar oldukça faydali. Olan biten herseyi hatalari gösteriyor. Isaretlemesi oldukça anlasilir. Surada hata var diyebiliyor.
Diger temel ayar dizinleri:
/etc/init/logstash.conf
/etc/logstash/jvm.options : Java’nin parametrelerini degistirebilirsiniz. Özellikle RAM kullanim miktari siniri sisteminize göre ayarlanabilir.

Logstash’i Çalistirmak:
Logstash’i servis olarak çalistirabilir veya komut satirindan parametre vererek kullanabilirsiniz. Test amaçli komut satiri kullanmak tüm islemler tamamlaninca servis olarak açmak mantikli.
Komut satirinda binary dosya ve konfigürasyon dosyasini göstererek basit bir çalistirmak saglayabiliriz. Elle konfigürasyon dosyasi belirtmek için –f parametresi kullanilir.

/usr/share/logstash/bin/logstash –log.level debug –f /etc/logstash/temp/test.conf

Bu komut ile test.conf dosyasindaki yapilandirma ile uygulamaniz çalisacaktir.
Uygulamayi burada kontrol etmeden çalistirmayi denemis olduk. Oysa konfigürasyon dosyasi hata içeriyor olabilir. Bunu kontrol etmek için –t parametresini vermek yeterli. Bu uygulamayi çalistirmadan dosya kontrolü sagliyor. Özellikle uzun konfigürasyon dosyalarinda oldukça faydali. Hatali buldugu noktayi isaretliyor.

/usr/share/logstash/bin/logstash –log.level debug –f /etc/logstash/temp/test.conf -t

Logstash Konfigürasyon Dosyasi:
Tabi önemli kisim konfigürasyon dosyasini hazirlamak.
Üstte de bahsettigim gibi konfigürasyon dosyamiz 3 ana kisimdan olusacak. Bunlardan ikisi kesin olmasi Input ve Output. Istege göre Filter’da eklenebilir.

Input olarak bir dosya, bir ip veya port verilebilir. Logstash otomatik olarak o ip ve portu dinleyen bir socket olusturacaktir.
Logstash konfigürasyon dosyasini tamamiyle kullaniciya birakir. Tüm yapilandirmayi kullanici kendine göre düzenler. Bu sagladigi esnekligin yaninda hazirlanmasi zorlu bir is yükünü de birlikte getiriyor.Baslamadan önce ben ne yapmak istedim ve ne oldu bir görelim. Topolojideki cihazlardan port Up/Down bilgisini alacak ve Spanning Tree Topoloji Change oldugunda bize bildirim göndermesini saglayacak bir logstash konfigürasyonu gerçeklestirdim.

input 
{
syslog {}
file {}
snmptrap{}
udp{}
tcp{}
}

Bu örnek bir girdi konfigürasyonu. Inceledigimizde logstash syslog, snmptrap, udp ve tcp içerisinde verilen ip ve port bilgileri için socket açip, ayni zamanda file ile verilen dosyayi belirli araliklar tarayip degisimini inceleyecek. Burada parantezler içerisinde o input’un detaylarini verebilirsiniz.

input
{
tcp
   {
       host => "192.168.1.1"
       port => "514"
       type => "syslog"
   }
 udp
    {
       host => "192.168.1.1"
       port => "514"
       type => "syslog"
    }
 snmptrap
     {
        community => "netoburus"
        host => "192.168.1.1"
        port => "162"
        type=> "snmptrap"
        yamlmibdir => "/usr/share/logstash/vendor/bundle/jruby/1.9/gems/snmp-1.2.0/data/ruby/snmp/mibs"
      }
}

Input için type sadece filtre amaçlidir. Herhangi bir tanim yapilabilir.
Gelen veri içerisinde tüm degiskenler “field” adi altinda toplaniyor; host field’i port field’i gibi.
Logstash her yeni sürümde input,codec,filter ve output bilesenlerini güncelliyor.
Asagidaki linkten tüm bu degisimler incelenebilir.
https://www.elastic.co/guide/en/logstash/current/index.html
Filter:
Filter kismi oldukça genis ve farkli sekillerde kullanilabilir. Gelen verinin istenilen herhangi bir kismi okunabilir, düzenlenebilir, yeni bilgi eklenebilir, etiketlenebilir vs. Logstash’i islevsel yapan en önemli kisimlarindan biri burasi.
Bizim dosyamiz içerisindeki filter bilesenlerini ve kullanim amaçlarini yazmak yeterli.
Kullandigimiz filter bilesenleri:
Grok,mutate,ruby,translate,
Grok: bir metin düzenleme ve filtreleme bileseni. Gelen veri içerisinde yazdigimiz regex ile eslesen kisimlari isaretlemek için kullandik.

grok
{
match => { "message" => "%{CISCOMNEMONIC:logid}\:%{GREEDYDATA:contentid}"}
}

Burada kaynak message “field” i içerisinde CISCOMNEMONIC ve GREEDYDATA regex’leri ile eslesen kisimlari ayirip onlara logid ve contentid olarak isaretliyor.

CISCOMNEMONIC %\w+\-\d+\-\w+
GREEDYDATA .*

Regex’ini isaret ediyor. CISCOMNEMONIC Cisco syslog’larindaki LINK-3-UPDOWN yapisindaki syloglari tanimlayan yapi. LINK-5-PROTO gibi.


Tüm bu regexler /usr/share/logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-4.0.2/patterns/ altinda tanimlanabilir.
Translate:
Translate bir sözlük gibi düsünebiliriz. Yaml formatinda verilen dosya içerisinden verileri okur ve karsiliklarini yeni bir “field” olusturarak saklar. Bu “field” “translation”dur. Yaml dosya tipi key:value ikilisinden olusur. AAA : 111 AAA ile gelen veriyi 111 olarak çevirir.

translate
  {
     field => "host"
     dictionary_path => "/etc/logstash/hosts/Routers.yaml"
     add_tag => "DC_3rd_Party"
  }

Kontrol edilecek “field” “host” kismi. Bu dosya içerisindeki IPADDRESS : HOSTNAME seklindeki veriler ile çözülüyor.
“add_tag” oldukça sik kullanilan veriye tanimlayici baska bir ibare ekleme sekli. Bu etiketi daha sonra kosullu kontrollerde kullaniyoruz.
Mutate:
Mutate veri içerisine “field” ekleme silme “tag” ekleme silme gibi degisiklikleri yapmamiza olanak saglar.

if "Router1" in [tags]
 {
   mutate
       {
           remove_tag => ["Router1"]
           add_tag => ["DC"]
           add_field => { "eventid" => "DC_Device" }
        }
  }

Burada bir önceki tag’i kaldirip yeni bir tag ekleyip ayrica “eventid” isimli bir field ekliyoruz.
Ruby:
Logstash zaten ruby temelli bir yazilim. Ve içerisinde istediginiz bir ruby kodunu çalistirmaniza izin veriyor.

ruby
{
  code => "
               temp=Time.new;
               temp=temp.localtime.strftime ('%d %B %Y %H:%M:%S.%L %z' );
               event.set('timeid',temp);
               "
}

Burada loglarin gelis zamanini düzenlemek için bir “timeid” field’i ekledik. Cihazlardan gelen süre ntp ayarina göre farklilik gösterecegi için sunucu zamanini baz aldim.
Diger Ruby kodu snmptrap için:

if [SNMPv2-MIB::snmpTrapOID.0] == "BRIDGE-MIB::topologyChange"
{
ruby
{
        code => "
                   v_array=Array.new;
                    i=0;
                   event.to_hash.values.each { |v| v_array.push(v); i=i+1;};
                    i=0;
                     j=0;
                     event.to_hash.keys.each { |k| event.set('vlanid',v_array[i]) if k.include?'VTP-MIB::vtpVlanIndexVlanID';
                    event.set('portid',v_array[j]) if k.include?'IF-MIB::ifName';
                   j=j+1; i=i+1;
                   };
                 temp=Time.new;
                 temp=temp.localtime.strftime ('%d %B %Y %H:%M:%S.%L %z' );
                  event.set('timeid',temp);
                    "
         add_tag => "Topo_Change"
        add_field => { "eventid" => "Topology_Change" }
            }
    }

Bu kodda gelen snmptrap mesajlarini degisken “field”lar içeriyor bu aslinda logstash’in yapisina aykiri. Bu yüzden gelen verinin key ve value degerlerini “field” ve karsiliklarini birer diziye atip dizi elemanlari içerisinde arama yapiyoruz. Index numaralari esit oldugu için herhangi bir sirada gelen veriyi dogru bir sekilde alabiliyoruz. Bunu yapmaz isek nexus ve ios’larda snmtrap mesajlari içerisinde veri siralari farkli. Tutarli bir veri elde edilemiyor.

Islenen veriyi logstash output’lar yardimi ile disari aktarabilir. Bu output; bir veritabani, baska bir uygulama, e-posta veya dosyaya kaydetmek olabilir.
Bizim konfigürasyonumuzda elasticsearch ve e-mail outputlari kullaniliyor.
Elasticsearch daha sonra bu verilere erismek ve arayüzde görüntülemek için kullanildi. E-posta ise filter’da isaretlenen önemli olaylari bildirmek için.

if [type] == "snmptrap"
 {
   email
       {
           to => ["musa.aydin@netoburus.com"]
           from =>["logstash@netoburus.com"]
           address => "192.168.1.2"
           port => "25"
           via => "smtp"
           domain => "INTER"
           subject => "LOG-STASH-%{eventid}"
           htmlbody => “ HTML IÇERIK BURAYA”
}
}

Bu konfigürasyonlar ile topolojiniz için basit bir alarm sistemi kurabilirsiniz. Ihtiyacinizi belirledikten sonra logstash’i düzenlemek hayal gücünüze ve ne kadar iyi google’layabilmenize bagli 🙂

Görüsmek üzere