24 Aralık 2016 Cumartesi

AMQP protokolü ve Apache-QPID uygulama incelemesi

advanced messaging queue protokolü, mqtt protokolü gibi mesaj bazlı çalışmaktadır. mqtt den daha karmaşık bir yapısı mevcuttur. buffer yaklaşımı vardır. tasarım olarak daha kapsamlı sunucularda asenkron haberleşme için tasarlanmıştır. 
Az enerji ile cihazlarımızda iş yapacağımızı düşünürsek mqtt bu konuda ön planda olabilir ama güvenlik, performans, süreklilik gibi konular üzerinde mqtt ye göre daha yetenekli olan amqp protokolü de daha kritik iot uygulamalarında kullanılabilir.

Bu yazıda apache nin geliştirdiği qpid üzerinden protokolün incelemesini yaptık.

apache-qpid kurulumu için debian sistemlerde aşağıdaki iki komut girilerek kurulum gerçekleştirilir[1].

apt-get install -y qpidd qpid-tools
apt-get install -y libqpidmessaging2-dev python-qpid

Kurulum bittikten sonra mqtt gibi hemen veri alışverişine başlayamıyoruz. amqp protokolü incelemenin başında söylediğimiz gibi daha güvenli bir protokoldür. Kendi sağlamış olduğu authentication, authorization yapısı mevcuttur. ilk önce kullanıcı ve bu kullanıcının bağlı olduğu bir realm yaratacağız. 
Kullanıcıyı yaratırken qpid bizden şifre isteyecektir.
amqp broker larına bağlanırken kullanıcı adı, şifre ikilisini kullanacağız. Veri tabanı jdbc bağlantıları gibi düşünülebilir.

Aşağıdaki komut ile "admin" realm i olan "firat" isminde bir kullanıcı yaratıyoruz. 

saslpasswd2 -f qpidd.sasldb -u admin firat

Yaratılan kullanıcılar qpidd.sasldb dosyasında binary bir şekilde tutulmaktadır. bu dosyaya erişmek için debian sistemlerde;

 sasldblistusers2 -f /etc/qpidd/qpidd.sasldb

komutu kullanılır. Bu komutta yaratılan kullanıcılar ve ait olduğu realm leri görülebilir.

root@debian-1gb-fra1-01:~/# sasldblistusers2 -f /etc/qpid/qpidd.sasldb
admin@QPID: userPassword
firat@admin: userPassword

Authentication safhasında farklı modları desteklemektedir. Bu modlar; md5, ssl, plain,kerberos olabilmektedir.

Bu çalışmada authentication modunu PLAIN olarak kullanacağız. PLAIN modunda veriler görülebilir ve sadece kullanıcı adı, şifre ile broker üzerinde mesajlaşma yapılabilir.

authentication modunu seçmek için

/etc/sasl2/qpidd.conf

içindeki mech_list parametresine PLAIN değeri verilir.

.
.
pwcheck_method: auxprop
auxprop_plugin: sasldb
sasldb_path: /etc/qpid/qpidd.sasldb
mech_list: PLAIN
.
.

Bu kullanıcıyı yarattıktan sonra authorization aşamasından geçmek için /etc/qpid klasöründeki  qpid.acl dosyasına erişilir.
Kısaltmasından anlaşıldığı gibi bu bir access control list dosyasıdır.  


# QPID policy file
.
.
.
# Group definitions
group admin admin@QPID
group firat firat@admin

# Admin is allowed to do everything
acl allow admin all
acl allow firat all

# Deny everything else by default
acl deny all all

Yarattığımız kullanıcıyı "sorunsuz" bir şekilde kullanmak için root ile eş değer acl allow firat all deyimini giriyoruz. 

qpid broker ı üzerinde kullanıcımızı test etmek için
qpid-config -b kullaniciadi/şifre@host:port
komut taslağını takip edilir.
qpid-config -b firat/XXXXXX@XXX.XXX.XXX.XXX:5672 

broker üzerinde topic yaratmak aşağıdaki komut kullanılır.

qpid-config -b firat/XXXXXX@XXX.XXX.XXX.XXX:5672 add exchange topic helloTopic

helloTopic isimli bir topic yaratmış olduk.

topic e subscribe olmak için ilk başta topic e bağlı bir kuyruk yaratılır. Kuyruk mantığı amqp protokolünün sağladığı bir yapıdır.




mqtt den farklı olarak bu kuyruklar dinamik olarak yaratılabilir ve birden fazla topic e atanabilir.

qpid-config -b firat/XXXXXX@XXX.XXX.XXX.XXX:5672 add queue helloQueue

helloQueue isminde bir kuyruk yaratmış olduk. yaratılan bu kuyruk topic ile ilişkilendirilir

qpid-config -b firat/XXXXXX@XXX.XXX.XXX.XXX:5672 bind helloTopic helloQueue

topic yaratıldıktan sonra aşağıdaki python un qpid kütüphanesi ile sunucumuza yarattığımız topic te mesaj publish edelim

#!/usr/bin/env python
import sys
from qpid.messaging import *
broker = "firat/XXXXXX@XXX.XXX.XXX.XXX:5672"
address="helloTopic"
mes="Hello world"
connection = Connection(broker)
try:
  connection.open()
  session = connection.session()
  sender = session.sender(address)
  receiver = session.receiver(address)
  sender.send(Message(mes));
  message = receiver.fetch()
  print message.content
  session.acknowledge()
except MessagingError,m:
  print m
connection.close()


sunucuda çalıştırılan python scripti ile sunucuda yarattığımız helloTopic, parametre verilerek bu topic e gelen mesajlar görüntülenir.

import optparse, sys, traceback
from qpid.messaging import *
from qpid.util import URL
from subprocess import Popen, STDOUT, PIPE

broker = "firat/XXXXXX@XXX.XXX.XXX.XXX:5672"
addr="helloTopic"

conn = Connection(broker)

def dispatch(msg):
  msg_type = msg.properties.get("type")
  if msg_type == "shell":
    proc = Popen(msg.content, shell=True, stderr=STDOUT, stdin=PIPE, stdout=PIPE)
    output, _ = proc.communicate()
    result = Message(output)
    result.properties["exit"] = proc.returncode
  elif msg_type == "eval":
    try:
      content = eval(msg.content)
    except:
      content = traceback.format_exc()
    result = Message(content)
  else:
    result = Message("unrecognized message type: %s" % msg_type)
  return result

try:
  conn.open()
  ssn = conn.session()
  rcv = ssn.receiver(addr)

  while True:
    msg = rcv.fetch()
    print msg
    response = dispatch(msg)
    print response
    ssn.acknowledge()
except ReceiverError, e:
  print e
except KeyboardInterrupt:
  pass

conn.close()



Kaynaklar

kod örnekleri aşağıdaki linkten referans alınarak düzenlenmiştir.

18 Aralık 2016 Pazar

MQTT Tutorial

Bu dökümanda IoT cihazları için kullanılmaya tasarlanmış MQTT[1] protokolü pratikte nasıl çalıştığı gösterilecektir. 
Senaryo olarak Debian üzerinde çalışan sunucu ve aynı sunucu üzerinde farklı process te çalışan bir adet sanal istemci ve raspberry pi cihazı üzerinde çalışan fiziksel bir istemci kullanılmıştır.

MQTT uygulaması olarak mosquitto[2] kullanılmıştır.


apt-get install mosquitto
mosquitto mqtt sunucusu indirilir

/etc/mosquitto/mosquitto.conf
 dosyası aşağıdaki gibi ayarlanır

# Place your local configuration in /etc/mosquitto/conf.d/
#
# A full description of the configuration file is at
# /usr/share/doc/mosquitto/examples/mosquitto.conf.example

pid_file /var/run/mosquitto.pid

persistence true
persistence_location /var/lib/mosquitto/

log_dest file /var/log/mosquitto/mosquitto.log

include_dir /etc/mosquitto/conf.d

listener 1883 XXX.XXX.XXX.XXX
connection_messages true
log_timestamp true
log_type error
log_type warning
log_type notice
log_type information
listener 1883 XXX.XXX.XXX.XXX satırı port-ip ikilisidir. Çalışmasını istediğiniz ip ve port numarası girilebilir.

service mosquitto start
 veya 
mosquitto -c /etc/mosquitto/mosquitto.conf

komutlarıyla mosquitto sunucusu çalıştırılır.
mosquitto sunucusuna gelen hareketler 
tail -1000f /var/log/mosquitto/mosquitto.log
komutuyla takip edilebilir.

MQTT protokolü publisher/subscriber mantığı ile çalışmaktadır. Bu sebeple demo için aynı sunucu üzerinde bir adet subscriber client i çalıştıracağız.
Client için 
apt-get install mosquitto-clients
ile mosquitto clients eklentisi indirilir.
Aynı sunucu üzerinde subscriber istemcisi çalıştıracağımız için girilecek komutta IP parametresi olarak 127.0.0.1 gireceğiz.
subscriber için mosquitto_sub komutunu kullanılır.

mosquitto_sub -t hello -h 127.0.0.1

subscriber bağlantısı sağlanınca mosquitto.log dosyasına aşağıdaki kayıtlar düşer. Bu kayıtlar subscribe işleminin başarıyla gerçekleştirdiğini belirtir.
Burada dikkat edin subscriber istemcisi mosqsub ile bağlanmaktadır.

1482096960: New connection from 127.0.0.1 on port 1883.
1482096960: New client connected from 127.0.0.1 as mosqsub/11445-debian-1g (c1, k60).

Şimdi raspberry pi cihazımız publisher clienti olarak çalışacak. Publisher olarak "hello" konulu bir mesaj yayınlayacağız.
bunun için mosquitto-clients komut seti raspberry pi üzerinde çalışan işletim sistemi için de indirilmelidir. 
Biz demomuzda debian tabanlı raspbian işletim sistemi üzerinde çalıştık. Raspbian, Debian işletim sistemindeki apt-get paket indirme komutunu kullanmaktadır. Bu sebeple debian sunucumuzda indirdiğimiz
apt-get install mosquitto
komutunu burada da girebiliriz.
İndirme işlemi tamamlandıktan sonra publish işlemi için mosquitto_pub komutunu kullanacağız.

mosquitto_pub -t hello -h XXX.XXX.XXX.XXX -m "Hello from Raspberry PI"

Yukarıdaki komutta -t topic parametresi. Debian subscriber da hello topic ini açtık. Bu topic üzerinden "Hello from Raspberry PI" mesajını, bu topic e kayıtlı kullanıcılara yayınlayacağız.
Komutu girdikten sonra işlemin başarıyla bitip bitmediğini 
echo $?
komutunun çıktısını istemci tarafında kontrol ederek öğrenebiliriz. Bu komut sonuç olarak 0(sıfır) değerini döndürürse işlemimiz raspberry pi tarafında başarıyla gerçekleşmiştir.

root@raspberrypi:~# mosquitto_pub -t hello -h 139.59.145.205 -m "Hello from Raspberry PI 2"
root@raspberrypi:~# echo $?
0
Bu komut çalıştırıldıktan sonra mosquitto.log dosyasına aşağıdaki satır kayıtları gelmektedir. 
Publisher istemcisi sunucuya mosqpub ile bağlanmaktadır

1482097004: New client connected from 85.102.169.241 as mosqpub/1456-raspberryp (c1, k60).
1482097004: Client mosqpub/1456-raspberryp disconnected.

Subscriber tarafında baktığımız vakit raspberry üzerinden gönderdiğimiz mesaj konsola düşmüş gözükecektir.

root@debian-1gb-fra1-01:/var/log/mosquitto# mosquitto_sub -t hello
Hello from Raspberry PI

şimdi aynı topic e raspberry pi üzerinden subscribe oluyoruz.

root@raspberrypi:~# mosquitto_sub -t hello -h XXX.XXX.XXX.XXX

Ve debian sunucumuz üzerinden hello topicli bir mesaj yayınlıyoruz. MQTT gereği yayınladığımız mesaj raspberry pi ve sunucu üzerinde açılmış subscriber istemcilerine gidecektir.

root@debian-1gb-fra1-01:~# mosquitto_pub -t hello -h 127.0.0.1 -m "Welcome to Team Raspberry PI"
Raspberry pi daki istemcimize düşen mesaj

root@raspberrypi:~# mosquitto_sub -t hello -h XXX.XXX.XXX.XXX
Welcome to Team Raspberry PI

Debian sunucu üzerinde çalışan subscriber a iletilen mesaj
root@debian-1gb-fra1-01:/var/log/mosquitto# mosquitto_sub -t hello
Hello from Raspberry PI
Welcome to Team Raspberry PI

30 Mayıs 2015 Cumartesi

OutOfMemory hatasına bağlı Thread Hung durumu

Threadlerin hung durumunda kalması müşterilerin ve yazılımcılarını en çok başını ağrıtan durumlardan birisidir.

Problemin kaynağını incelerken outofmemory almasına sebep olan durumu incelememiz gerekiyor. Anlık artan isteklerde sistemin kapasitesine bağlı yetersiz olması ya da memory üzerinde çalışan yazılımların kodlamasından kaynaklı olabilir.


Buradaki durumda monitor objesine sahip thread monitor objesini bırakmamaktadır. Aynı zamanda kuyrukta bekleyen threadlerde iş yapması için monitor objesini beklemektedir. Bu threadler belirli bir sayıyı geçince uygulama sunucusu alert vermeye başlar.İşte olay bu noktadan sonra kopmaya başlar J

JVM Analizinde “Hung” durumundaki threadler


Hung durumunda uygulama sunucusu(WebSphere AppServer örnek alındı) aşağıdaki gibi bir hata mesajı fırlatmaktadır.

Hung durumundaki threadlerin tespit edilmesi ayrı bir inceleme konusudur. Uygulama sunucuları burada kullanıcının da müdahale edebileceği çeşitli poliçeler yürütür. Örnek olarak WebSphere App Server da bir thread 10 dakikadan fazla wait durumunda kalırsa sunucu direk konsola hata logu fırlatmaya başlar. 

ThreadMonitor W   WSVR0605W: Thread "WebContainer : 0" (00000029) has been active for 647279 milliseconds and may be hung.  There is/are 49 thread(s) in total in the server that may be hung.


Hung durumundaki threadlerin memory segment analizine bakıldığında Free Memory oranları %10 un altına düşmüş bir seviyededir. Aşağıdaki tablo jvm in heap memory si değildir. Non-heap[1] memory kategorisindedir.


Threadlere dönecek olursak başımıza gelen senaryoyu ilk paragrafta özet olarak söylemiştim. Detayına inersek olay şöyle gerçekleşti. Block durumundaki bir threadin stacktrace ine bakıldığında,


WebContainer:333 threadinin iş yapması için Monitor nesnesini beklediğini belirtmektedir. Monitor nesnesi, thread senkronizasyonunda kullanılmaktadır. Veri tabanı sistemlerindeki “lock” gibi düşünebiliriz. Monitor e sahip olan thread işini bitirene kadar bu nesneyi bırakmaz. Bu sırada diğer threadler kuyrukta “blocked” durumunda ve “notify” edilmeyi beklerler.



Monitor nesnesine sahip olan thread e bakıldığında burada ilgili kod bloğuna bakılması gerekilir.


Kod bloğuna gidildiği vakit hatanın sebebi ortaya çıkmaktadır. Monitor nesnesi memoryde bir problem olduğunu tespit etmiştir bu sebeple hiç bir şekilde imageThreadMonitor.notifyAll() satırına erişememektedir. Bu satıra erişebilseydi “block” durumundaki threadleri tekrar çalışır duruma ve sistemi hizmet verebilir duruma getirebilirdi.      

16 Ağustos 2014 Cumartesi

GÜVENLİ KOD GELİŞTİRME-1 ERROR MESAJLARININ İŞLENMESİ

TANIM


Uygulama esnasında oluşacak hatanın detayları(yığın bilgisi) mutlaka gizlenmelidir. Bir veri sızıntısı güvenlik(data leaking) çeşididir. Sisteme hakim bir uzak kullanıcının sisteme müdahale etme ihtimali artmaktadır.

SENARYO -1- KÖTÜ DURUM 

Örnek kod bloğunda bir click event sonrasında bir veri tabanı bağlantısı gerçekleştirilmektedir.

public SQLContainer getMaleCustomer()
    {
        try
        {
            connectionPool = new SimpleJDBCConnectionPool(DRIVER_NAME,
                    DATABASE_URL, DATABASE_USERNAME, DATABASE_PWD);
            String query = "select * from t_customer where gender='Male'";
            prepareConnection();
            FreeformQuery freequery = new FreeformQuery(query, connectionPool,
                    "id");
            sqlContainer = new SQLContainer(freequery);
            connection.close();
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
       
        return sqlContainer;
       
    }
Veri tabanı bağlantısı gerçekleştiren modüllerden birine baktığımız vakit try-catch kullanılmış ve e.printStackTrace() metodu kullanılarak hata catch edilmiştir.

TESPİT 

catch bloğuna printStackTrace() metodu kullanıldığı için exception mesajları olduğu gibi kullanıcı arayüz tarafına yansayacaktır(Şekil 1).

Şekil.1 Catch bloğunda data leaking



 ÇÖZÜM

public SQLContainer getMaleCustomer()
    {
        try
        {
            connectionPool = new SimpleJDBCConnectionPool(DRIVER_NAME,
                    DATABASE_URL, DATABASE_USERNAME, DATABASE_PWD);
            String query = "select * from t_customer where gender='Male'";
            prepareConnection();
            FreeformQuery freequery = new FreeformQuery(query, connectionPool,
                    "id");
            sqlContainer = new SQLContainer(freequery);
            connection.close();
        }
        catch (SQLException e)
        {
           
            Notification.show("Hata oluştu",
                    Type.HUMANIZED_MESSAGE);
            StringWriter sw = new StringWriter();
            e.printStackTrace(new PrintWriter(sw));
            System.err.println(sw.toString());
           
        }
       
        return sqlContainer;
      
  }

Yukarıdaki kod bloğunda Senaryo -1- deki kod örneğine göre catch bloğuna kullanıcıya “Hata oluştu” gerekçesinde bir hata mesajı verilmiştir. Bunun yanında Senaryo-1- deki hata stack kısmı konsol tarafına StringWriter ve PrintWriter nesneleri kullanılarak yazılmıştır.Bu loglar log4j gibi 3.parti eklentilerle daha işlevsel, okunabilir hale getirilebilir.

Şekil.2 Doğru bir hata yönetimi



REFERANSLAR VE DETAYLI BİLGİ İÇİN





10 Ağustos 2014 Pazar

DOS-DDOS Saldırısı Nedir ?


DoS aslında sistemi ele geçiren bir saldırı değildir.Amacına göre iki türlü DoS saldırısı vardır.Bunlar

·         Bandwith tüketimine yönelik saldırı
·         CPU,RAM,disk,buffer gibi sistem kaynaklarını tüketmeye yönelik saldırı

DDoS un DoS saldırılarından tek farkı çok noktadan(farklı IP adreslerinden) saldırının gerçeklenmesidir.
Belli başlı saldırı türleri;
  • SYN Flooding
  • UDP Flooding
  • ICMP Flooding
  • HTTP-GET Flooding
  • Smurfing

Çoğunluğu flood yani sel gibi birim zamanda yüksek şiddette zarar verecek şekilde sistemin kaynaklarının kullanılmasıdır.
SYN Flooding

SYN saldırısı,TCP katmanında(OSI seviye 7) gerçekleşen bir saldırıdır.TCP paketlerinin değiştirilip karşı tarafın üçlü el sıkışması mekanizmasını bozacak şekilde gerçekleşir.Üçlü el sıkışması TCP bağlantısının gerçekleşmesi için yapılan bir alt bağlantıdır.



    
Üçlü el sıkışmanın aşamaları soldaki gibidir.Resmin soldaki şekline A noktası, sağdakine ise B noktası diyelim.
A noktası SYN pakedini gönderir.
B noktası SYN-ACK pakedini 
ve son olarak A noktası tekrardan ACK pakedi göndererek üçlü el sıkışması gerçekleştirilir






Bu noktada SYN Flooding saldırısı üçüncü aşamada gerçekleştirilir.İkinci aşamada SYN-ACK pakedi geldikten sonra alan taraf asla ACK pakedi göndermez bu şekilde karşı taraf ACK pakedini alamadığı için TCP mimarisi gereği SYN-ACK pakedini tekrar tekrar göndermeye çalışacaktır.Burada hem ağ hemde sistem yorulmaktadır.Ağın yorulması,ağ üzerinde giden SYN-ACK paketleri bantgenişliğini doldurmaktadır.Sistem tarafında ise pakedi SYN-ACK pakedini gönderen makine her pakedi üretimde işlemci zamanını harcar ve gönderdiği SYN-ACK pakedi başına TCP bufferı dolmaya başlar.İşte SYN saldırısının etkili tarafı buradadır.Hem ağı hemde ağa bağlı bir bilgisayarı hizmet dışı bırakabilmektedir.
Bir SYN Flooding saldırısı




12 Mayıs 2014 Pazartesi

Android Cihazlardan Lokaldeki Apache Server'a Erişim(Permission Denied hatası için)

Android cihazlarıyla MySQL iletişim kurarken genellikle Apache server kullanılmaktadır.
Geliştirme sırasında aynı network içindeki Android cihazın MySQL veritabanıyla işlemler yaptırılması için cihaz Apache server da bulunan .php scriptleriyle iletişime geçmesi gereklidir.Bu scriptler aracılığıyla Android ile MySQL üzerindeki veri tabanlarıyla işlem yapılmaktadır.
Buradaki sıkıntı Apache server ın ilklendirilmiş ayarlarında lokaldeki bağlantılara erişiminin kapalı olmasıdır.
Windows sistemleri için;
WAMP kurulduktan sonra

<wamp_dosya_yolu>/bin/apache/apache2.4.9/conf

klasörü içerisinde httpd.conf dosyasında "Directory" düğümlerinin içine koyu yazılanlar eklenmelidir.

<Directory />
    Options Indexes FollowSymLinks Includes ExecCGI
    AllowOverride All
Order deny,allow
    Allow from all
    Require all granted
</Directory>

<Directory  "c:/wamp/www/">
#
    # Possible values for the Options directive are "None", "All",
    # or any combination of:
    #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
    #
    # Note that "MultiViews" must be named *explicitly* --- "Options All"
    # doesn't give it to you.
    #
    # The Options directive is both complicated and important.  Please see
    # http://httpd.apache.org/docs/2.4/mod/core.html#options
    # for more information.
    #
    Options Indexes FollowSymLinks

    #
    # AllowOverride controls what directives may be placed in .htaccess files.
    # It can be "All", "None", or any combination of the keywords:
    #   AllowOverride FileInfo AuthConfig Limit
    #
    AllowOverride all
    Order deny,allow
    Allow from all


    #
    # Controls who can get stuff from this server.
    #
    #onlineoffline tag - don't remove
    Require all granted
    #Require local

</Directory>

İşlemler yapıldıktan sonra Apache Server yeniden başlatılır.
Cihazınızdan bilgisayarınızın localhost undaki apache server a bağlanırken,cihaz üzerinde localhost:80 olacak şekilde adres girmeyiniz.
bilgisayar_ip_no:80
örneğin 192.168.1.20:80
olacak şekilde telefonunuzdan bilgisayarınızdaki apache server a erişim sağlayabilirsiniz.
Bu ayarlar sonucunda hala erişim sağlanamıyorsa işletim sisteminizin güvenlik duvarı ayarlarından TCP 80 portunun erişimine izin vermeniz gerekmektedir.

30 Nisan 2014 Çarşamba

JAVA Soket Programlama Türkçe Karakter Çözümü

Soket programlamada sıkıntılardan bir tanesi de iki makine arasında türkçe karakterlerin düzgün bir şekilde gönderilmesidir.



 Socket client;
 BufferedReader in = new BufferedReader(new client.getInputStream(), "UTF-8"));




ile çözülebilir.