Her yerde bulunan kablosuz ağlara bağlanırken donanım seviyesinde bir güvenlik katmanı oluşturmak için yapılan bir akademik çalışma neticesinde bu yazı ortaya çıktı. Eylül 2018’de Saraybosna’da UBMK’da sunulan çalışmaya şuradan ulaşabilirsiniz: https://ieeexplore.ieee.org/abstract/document/8566439/
Sistemin özeti şöyle:
Bilgisayarın doğrudan kablosuz ağa bağlanması yerine öncelikle Raspberry Pi (RPi) kablosuz ağa bağlanacak ve bilgisayar da RPi üzerinden internet bağlantısı sağlayacak. RPi üzerinde çalışan Snort ve arkadaşları da, ağın güvenli olmasını sağlayacaklar.
Kullanılan Sistem Bileşenleri
- Donanım: Raspberry Pi (Model B Rev 2)
- İşletim sistemi: Raspbian GNU/Linux 9.4 (stretch), çekirdek: 4.14.42+
- IPS: Snort 2.9.11.1 GRE (Build 268). Kütüphane olarak libcap 1.8.1, PCRE 8.39, ZLIB 1.2.8,
libnetfilter-queue 1.0.2-2 - Güvenlik duvarı: Iptables v1.6.0, netfilter
- LOG işleme: Barnyard 2.1.14 (Build 337)
- WEB arayüzü: Bristle
Aşağıda sistemin genel görüntüsü verilmiştir. Normalde cihaz üzerinde ekrana ihtiyaç bulunmuyor. Sistemi kurarken faydalanmak üzere bir 7 inçlik HDMI ekran kullandım. Bir de fantezi olsun diye RPi uyumlu Nokia ekran kulandım. Nokia ekran, çok ucuz Çin malı bir ekran. Bu ekranda, cihazın IP adresini yazdırdım ki SSH ile bağlanırken IP aramayayım diye.
Kurulum
RPi işletim sisteminin nasıl kurulacağına girmiyorum burada. Standart işlemler zaten her yerde yazıyor. Özellikle kurulum sırasında problem çıkarabilecek olan birkaç kritik noktaya değineceğim.
Temel Raspbian İşlemleri
Raspbian imajı ilk açıldığında raspi-config uygulaması üzerinden bazı işlemleri yaptım, kısaca burada açıklayayım:
- ssh bağlantısını enable ettim. GUI olmayacağı için, SSH üzerinden bağlanacağız RPi’ye.
- Timezone ayarlarını düzenledim. Sistem log’larının sağlam olabilmesi için bu kısım elzem.
- GUI boot olayını devre dışı bıraktım. Boşu boşuna kaynak tüketmesin, zaten kullanmayacağız. Doğrudan konsolda (CLI boot) açılacak RPi.
Sistem güncellemesini yapalım (ve bunu ara sıra mutlaka tekrarlayalım):
1 |
sudo rpi-update |
Nokia ekran
Adafruit kütüphanesini kullandım. İlgili Python kodunu aşağıda verdim. Ekranda doğrudan IP adreslerini yazıyor. Önemli bir aşama değil ama işe yarıyor. Ancak kaynak kullanımı çok fazla. %30 civarında işlemci tüketiyor kod bellekte çalışırken. Bu nedenle sürekli güncel bilgi yazdırmak için bellekte tutmak tehlikeli. Ben IP adreslerini yazdırınca kendim sonlandırıyorum uygulamayı.
Betikte psutil modülü import edildiğinden önce onu kuralım ki, arıza yapmasın:
1 |
pip install psutil |
Nokia ekrana IP adresini yazan Python betiği:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
#!/usr/bin/python # Copyright (c) 2014 Adafruit Industries # Author: Tony DiCola # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # For float division operations: from __future__ import division # For cpu, network utilization: import psutil import time import Adafruit_Nokia_LCD as LCD import Adafruit_GPIO.SPI as SPI from PIL import Image from PIL import ImageDraw #from PIL import ImageFont # Software SPI usage (defaults to bit-bang SPI interface): SCLK = 17 DIN = 18 DC = 27 RST = 23 CS = 22 disp = LCD.PCD8544(DC, RST, SCLK, DIN, CS) # *** IP address *** def ip_address(interface): return (psutil.net_if_addrs()[interface][0].address) # *** Network utilization *** # https://stackoverflow.com/questions/276052/how-to-get-current-cpu-and-ram-usage-in-python def NET(): net = psutil.net_io_counters(pernic=True) s=net['eth0'].bytes_sent/(1024*1024) r=net['eth0'].bytes_recv/(1024*1024) return(str("%.1f" % s)+'M,'+str("%.1f" % r)+'M') # *** CPU usage *** def CPU(): return(str(psutil.cpu_percent())) # *** RAM usage *** def RAM(): return(str(psutil.virtual_memory().percent)) # Initialize library. disp.begin(contrast=60) #disp.clear() disp.display() image = Image.new('1', (LCD.LCDWIDTH, LCD.LCDHEIGHT)) draw = ImageDraw.Draw(image) print('Press Ctrl-C to quit.') while True: draw.rectangle((0,0,LCD.LCDWIDTH,LCD.LCDHEIGHT), outline=255, fill=255) draw.line((1,23,84,23), fill=0) draw.text((1,1), ip_address('eth0')) draw.text((1,13), ip_address('wlan0')) draw.text((1,25), 'CPU: %'+CPU()) #draw.text((1,25), 'RAM: %'+RAM()) draw.text((1,35), 's,r: '+NET()) time.sleep(1.0) # Display image. disp.image(image) disp.display() |
Konsoldan kablosuz ağa bağlanma
Bununla ilgili birçok araç var. En kolay kullanılanı bana göre wicd-curses . Bir satır ile kurulumu yapılabiliyor:
1 |
sudo apt install wicd-curses |
Ekran görüntüsü şöyle birşey:
İstenirse, nmcli diye bir araç ta var, onun da ekran görüntüsü şöyle:
Snort Kurulumu
Bu uygulamada önemli bir kısım, belleğin düşük (512MB) olması nedeniyle, Snort’un varsayılan ayarlarda çalışmaması oluyor. Bunun için SWAP bellek alanı (takas bellek) yapılandırmak gerekiyor. Şu şekilde swap ayarı yaptım:
1 2 3 4 5 6 |
sudo su apt-get install dphys-swapfile echo "CONF_SWAPSIZE=512" > /etc/dphys-swapfile dphys-swapfile setup dphys-swapfile swapon exit |
Snort kurulumu:
1 |
sudo apt install snort |
Kurulum sırasında local_net değerine bir şey girmeye gerek yok. Denemek için 10.0.0.0/24 girdim ama hiçbir alert üretmedi. Bu değer boş kalınca alert üretiyor.
Snort farklı türde log dosyaları kullanabiliyor. Varsayılan olarak /var/log/snort/ klasörüne yazıyor log’ları. Buradaki dosyanın türüne göre farklı şekilde dosya incelemesi yapılabiliyor. Log dosyasının türünü öğrenmek için şu komut verilebilir:
1 |
file var/log/snort.log |
Üstteki komutun çıktısı, “data” veya “tcpdump capture file” olabilir. Data biçimindeki dosyaları u2spewfoo <dosya> şeklinde okuyabiliriz. Tcpdump biçiminde ise, tcpdump -r <dosya> şeklinde okunabilir.
Log dosyası okumayı becerdikten sonra, birkaç tane alert etkinleştirilip log düşüp düşmediğine bakılabilir.
ÖNEMLİ: Bu aşamada Snort IDS modunda çalışıyor. Yani sadece log tutuyor. Trafiğe müdahale etmiyor. IPS moduna geçirme konusu aşağıda.
MySQL kurulumu
Kurulum basit, şöyle:
1 |
sudo apt install mysql-server |
Raspbian’ın güncel kurulumunda MySQL yapılandırması eskisi gibi olmuyor. root kullanıcısını parola yerine plugin ile yetkilendirmeye çalışıyor. Eğer eskisi gibi olsun istenirse, aşağıdaki işlemlerin yapılması gerekiyor. Kaynak: https://stackoverflow.com/questions/30815971/mariadb-installed-without-password-prompt
1 2 3 4 5 6 |
sudo mysql -u root [mysql] use mysql; [mysql] update user set plugin='' where User='root'; [mysql] flush privileges; [mysql] exit |
Barnyard kurulumu
Snort log’Larını bir veritabanına kaydetmek istersek, bu tarz bir araç gerekiyor. Çünkü Snort normalde dosyaya yazıyor. ok yoğun trafik altında Snort’un log işi ile uğraşmaması, en kolay şekilde halletmesi gerekiyor. Ancak bizim de bu log’ları sorgulamamız ve hatta arayüzden incelememiz gerekiyor. İşte bu iki isteğin bir arada olmasını sağlayan araç, Barnyard. Kurulumu şöyle:
ÖNEMLİ: Aşağıdaki kurulum aşamaları kopyala-yapıştır yapılırsa çalışmayabilir. Çünkü yeni sürümlerde ufak tefek farklılıklar olmaktadır. Lütfen adımları inceleyerek kendi sisteminize göre uyarlayınız.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
sudo apt-get install automake autoconf libtool git clone https://github.com/firnsy/barnyard2.git barnyard2 cd barnyard2 ./autogen.sh sudo apt install mysql-server libmysql++-dev sudo ln -s /usr/lib/arm-linux-gnueabihf/libmysqlclient.so /usr/lib/ ./configure --with-mysql sudo apt install libdaq-dev libdnet-dev libdnet sudo ln -s /usr/include/dumbnet.h /usr/include/dnet.h sudo ldconfig make sudo make install sudo ln -s /usr/local/etc/barnyard2.conf /etc/snort2/barnyard.conf sudo ln -s /usr/local/bin/barnyard2 /usr/bin/ sudo mkdir /var/log/snort/archived_logs/ sudo /usr/share/oinkmaster/create-sidmap.pl /etc/snort/rules/ > /etc/snort/sid-msg.map sudo barnyard2 -c /etc/snort/barnyard2.conf -d /var/log/snort -f snort.log -w /var/log/snort/barnyard2.waldo -g snort -u snort |
Barnyard’ı başlangıçta otomatik çalışacak hale getirmek için betik oluşturma konusunda şuradaki doküman işe yarayacaktır: http://computer-outlines.over-blog.com/article-nids-8-snort-boot-time-autorun-123375481.html
Eğer buradaki kurulum komutlarında sorun yaşanırsa, şuradaki doküman da işle yarayacaktır: http://sublimerobots.com/2017/01/snort-2-9-9-x-ubuntu-installing-barnyard2/
Barnyard’ı güzel bir şekilde başlatmak için gerekli satır şöyle:
1 |
sudo barnyard2 -c /etc/snort/barnyard2.conf -d /var/log/snort -f snort.log -w /var/log/snort/barnyard2.waldo -g snort -u snort -D -a /var/log/snort/archived_logs |
Bristle kurulumu
Bristle, Snort log’larını veritabanından çekerek web üzerinden sunan bir araç. Ekran görüntüsü şöyle birşey:
Bristle, https://github.com/Ejdamm/bristle adresinden indirilip kurulabilir. Barnyard kurulumu sırasında oluşturulan veritabanı yapısı ile tam uyumlu. Çok detaylı web kullanımı yok ama hiç yoktan iyidir.
Snort’u IPS moduna (Inline) getirme
Burada bridge/routing şeklinde farklı seçenekler bulunmaktadır. Detaya giremeyeceğim, çok uzayacak yoksa. Ben NFQ kullanarak routing modda inline yaptım.Şu kaynağı takip ettim: http://sublimerobots.com/2017/06/snort-ips-with-nfq-routing-on-ubuntu/
İşlemleri aşağıda yazdım. Önce hazırlık:
- /etc/sysctl.conf dosyasında forwarding enable et.
- Interface ayarlarını yap.
Depoda gelen Snort içinde NFQ desteği gelmediğinden, kaynaktan derlemek durumundayız (malesef). Snort’u tar.gz biçiminde indirip, açıp ilgili klasöre girdikten sonra:
1 2 3 4 5 6 |
sudo apt-get install -y build-essential libpcap-dev libpcre3-dev libdumbnet-dev bison flex zlib1g-dev liblzma-dev openssl libssl-dev libnghttp2-dev libtool-bin sudo apt-get install libnetfilter-queue-dev ./configure --enable-sourcefire make make install sudo ldconfig |
snort.conf dosyasında bir satır hatalı geldi, onu düzeltmek gerekti. /usr/lib/snort_dynamicpreprocessor/ kısmını bulup /usr/local/lib/snort_dynamicpreprocessor/ olacak şekilde değiştirdim.
Test et (-Q parametresi inline mod için kullanılıyor):
1 2 |
snort --daq-list sudo snort -T -c /etc/snort/snort.conf -Q |
Bu kısım için şurası güzel bir kaynak olabilir: http://sublimerobots.com/2017/06/snort-ips-with-nfq-routing-on-ubuntu/
Snort’u gerçekçi olarak (tets için değil) başlatmak için ilgili satır şöyle:
1 |
sudo /usr/local/bin/snort -m 027 -d -D -l /var/log/snort -u snort -g snort -c /etc/snort/snort.conf -S HOME_NET=[any] -Q |
Trafiği iptables ile inline Snort’a gönderme
Snort’u tek başına inline yapmak yetmiyor, iptables üzerinden de trafiğin Snort’a yönlendirilmesi gerekiyor. Aşağıda benim yaptığım ayarlarda iptables-save komutunun çıktısı görülmektedir. Wifi tarafındaki (wlan0) ip adresi sürekli değişeceği için, MASQUERADE yapmak gerekiyor.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
pi@raspberrypi:~ $ sudo iptables-save # Generated by iptables-save v1.6.0 on Thu Jul 19 11:04:49 2018 *filter :INPUT ACCEPT [838:75325] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [399:69815] -A FORWARD -i wlan0 -o eth0 -m state --state RELATED,ESTABLISHED -j NFQUEUE --queue-num 4 -A FORWARD -i eth0 -o wlan0 -j NFQUEUE --queue-num 4 COMMIT # Completed on Thu Jul 19 11:04:49 2018 # Generated by iptables-save v1.6.0 on Thu Jul 19 11:04:49 2018 *nat :PREROUTING ACCEPT [4035:358855] :INPUT ACCEPT [83:9560] :OUTPUT ACCEPT [4:295] :POSTROUTING ACCEPT [0:0] -A POSTROUTING -o wlan0 -j MASQUERADE -A POSTROUTING -o wlan0 -j MASQUERADE -A POSTROUTING -o wlan0 -j MASQUERADE -A POSTROUTING -o wlan0 -j MASQUERADE COMMIT # Completed on Thu Jul 19 11:04:49 2018 |
Benim uygulamada eth0 bacağına statik IP verdim 192.168.0.2/24 şeklinde. Bunun üzerinden bağlanacak cihazlara da aynı ağdan bir IP verip, ağ geçidi olarak 192.168.0.2 verince doğrudan çalışıyor. İstenirse eth0 tarafına IP dağıtmak için dhcp server yapılandırılabilir. Ben yapmadım bunu.
Kablosuz ağa bağlanmak
Eğer bir betik içinden veya herhangi bir nedenle bir ağa otomatik bağlanma ihtiyacı olursa, şu şekilde bir komut ile bu sağlanabilir. Tabii wpa_supplicant kullanılıyorsa. Mesela eduroam bağkantısı için ilgili ayarları wpa_supplicant.conf içinde yazarak, otomatik olarak bağlantı yapabiliyorum.
1 |
sudo wpa_supplicant -iwlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf & sudo dhcpcd wlan0 |
Son Söz
Yukarıda da dediğim gibi, kodlarda mutlaka farklılık olacaktır. Bu işlerle az ilgilenenler zaten kopyala-yapıştır ile yapılamayacağını bilir. Yazıyı okuyup mantığı anladıktan sonra, ufak tüyolara da dikkat ederek, verilen kaynakları da mutlaka inceleyerek kendi sisteminize özel kurulum yapabilirsiniz.