30.01.2021

Bir RaspberryPI projesi

Evde boş duran bir raspberry pi 2 vardı. Sebebi bu yazının konusundan bağımsız bir düşünceden dolayı evdeki kablosuz ağımızda bilinen ve/veya bilinmeyen ne gibi cihazlar var; davetsiz misafirlerimiz var mı diye meraklandığım bir anda bu raspberry pi için bir amaç buldum. Bir şekilde yerel ağımızdaki cihazlar için periyodik ARP taraması yapacak, MAC adreslerini listeyecekti. Ben de sonra bu sonuçlara bakarak hangisi tanıdık, hangisi istenmeyen bilebilecektim.

Bu amaçla önce raspberry pi'ya bir ARM tabanlı Ubuntu türevi olan Raspbery PI OS işletim sistemini yükledim. Eskiden Raspbian vardı, adı artık değişti. ARP taramasını önce nmap ile yapmak aklımdan geçti. Ama daha sonra arpscan diye bir aracın varlığını öğrendim. Kullanımı basit.

$ sudo arp-scan -l

yazınca yerel ağdaki cihazların listesini, 2 satır header ve 2 satır footer arasında sekmelerle ayrılmış olarak veriyor, aşağıdaki gibi:

Interface: eth0, datalink type: EN10MB (Ethernet)
Starting arp-scan 1.9.5 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.xx.xx    xx:xx:xx:xx:xx:xx    (Unknown)
192.168.xx.xx    xx:xx:xx:xx:xx:xx    (Unknown)
192.168.xx.xx    xx:xx:xx:xx:xx:xx    (Unknown)

3 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.9.5: 256 hosts scanned in 4.335 seconds (59.05 hosts/sec). 3 responded

Bu tamam. Bunu bir bash script'ine koydum (scan.sh):

#!/bin/bash
_now=$(date +"%Y-%m-%dH%H-%M")
_file="/home/pi/arpscan/log_$_now.log"
sudo arp-scan -l > "$_file"

Bu script, çalıştığında ARP taramasının sonuçlarını log_2021-01-29H21-15.log gibi bir dosyaya kaydedecek. Peki nasıl çalışacak?

# sudo crontab -e

ile bir cronjob oluşturdum, aşağıdaki gibi

0,15,30,45 * * * * sh  /home/pi/arpscan/scan.sh

Yani, her 15 dakikada bir çalışıp ağdaki her cihazın MAC adresini, o anın tarih ve saatini içeren  isme sahip bir log dosyasına kaydedecek. Buraya kadar güzel. Ama bu dosyaları oturup incelemek uzun iş. Onun için önce evdeki cihazların bir envanterini çıkardım. MAC adreslerini belirledim. Sonra da bir python script'i oluşturarak, bu envanterin dışında kalan MAC adreslerini bulmasını sağladım (read.py):

#!/usr/bin/python3.7
import glob

def get_mac(line):
    line_ = line.split('\t')
    if (len(line_)>2):
        mac = line_[1]
        if (mac.count(':')==5) or (mac.count('-')==5):
            return mac.upper()
    return ''

def mac_in_list(mac):
    mac_list = {"xx:xx:xx:xx:xx:xx",... }
    for item in mac_list:
        if mac==item:
            return True
        else:
            continue
    return False

logPath = "/home/pi/arpscan/log*.log"
outPath = '/home/pi/arpscan/all_macs_py.txt'

loglist  = glob.glob(logPath,recursive=False)

for item in loglist:
    oLogFiles = open(item,'r')
    content_ = oLogFiles.read()
    content = content_.split('\n')
    for line in content:
        mac = get_mac(line)
        if (len(mac)>0):
            if not mac_in_list(mac):
                print(mac,"is new!",item)
    oLogFiles.close()

 

Gün içinde her 15 dakikada bir yapılacak ARP taramasının sonuçları bir klasörde birikecek, günün bir saatinde de bu dosya çalışacak, yabancı MAC adresi taraması yapacak, eski logları sıkıştırıp arşivleyecek ve gereksiz dosyaları temizleyecek (temizle.sh):

#!/bin/bash

cd /home/pi/arpscan
./read3.py > all_macs_py.txt
_today=$(date +"%F")
_file="/home/pi/arpscan/log_$_today.7z"
_move_target="/home/pi/arpscan/all_macs_$_today.txt"
7z a $_file /home/pi/arpscan/log_*.log
rm /home/pi/arpscan/log_*.log -f
mv /home/pi/arpscan/all_macs_py.txt $_move_target -f
sudo cp $_move_target /var/www/html/arp.lan/

Bunu da benzer bir şekilde günün bir saatinde çalışmak üzere bir cronjob'a atadım. En son satırdaki dosyanın /var/www/html/arp.lan/ klasörüne kopyalanması bu yazının son bölümünde anlatacağım adımdan sonra netlik kazanacak.

Sonra bu cihazın herkesin erişimine açık olmaması için öncelikle güvenlik duvarını etkinleştirdim:

$ sudo ufw enable

$ sudo ufw allow ssh 

Sonra da fail2ban paketini kurdum. Bu paketi özellikle çok sevdim. Aslında Windows alışkanlığı olarak account lockout diye arattım, ama bu daha da güzel. Belli bir sayıda giriş başarısız olursa kaynak IP adresini güvenlik duvarı üzerinde engelliyor.

$ sudo apt install fail2ban

Sonrasında şu adreste yazdığı gibi yapılandırmaya başladım. Öncelikle /etc/fail2ban/jail.conf dosyasının bir kopyasını alıp jail.local olarak kaydettim:

$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

sonra bu dosyasının ortalarına denk gelen bir bölümde [sshd] başlığı altındaki bölüme şu satırları ekledim (siyah : var olan, kırmızı : yeni eklenen)

[sshd]
port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
maxretry= 3
bantime = -1
findtime=6h

Bu şekilde varsayılan ssh portu üzerinden 6 saatlik zaman diliminde (findtime=6h) 3 kez yanlış şifre girilmesi durumunda (maxretry=3) IP adresini süresiz (bantime=-1) engelliyor. Bunların logunu da /var/log/auth.log dosyasında tutuyor.

Kurulduktan sonra fail2ban hizmetini etkinleştirip çalıştırdım:

$ sudo systemctl enable fail2ban.service

$ sudo systemctl start fail2ban.service

Sistemin çalıştığından emin olmak istedim. 5 kez yanlış şifre sonunda IP adresim engellendi. IP adresimi değiştirerek tekrar giriş yapmam mümkün oldu. Girdikten sonra da

$ sudo fail2ban-client unban 192.168.xx.xx

ile engellemeyi kaldırdım. Herhangi bir anda engellenen IP var mı diye bakmak için

$ sudo fail2ban-client status sshd

komutunu kullanabilirim.

Aklımda başka bir fikir daha vardı. Modemimin loglarını saklamak için rsyslog'u ayarladım. Artık sadece ARP tarama sonuçlarını değil, modemimin loglarını da raspberry pi'ın üzerinde saklıyorum. Bunu yapabilmek için Raspberry PI OS ile gelen rsyslog'un yapılandırma dosyası olan /etc/rsyslog.conf'u açtım. 514 numaralı port üzerinden TCP ve UDP'den gelecek syslog kayıtlarını etkinleştirmek için aşağıdaki satırların başındaki hash karakterini sildim.

module(load="imudp")
input(type="imudp" port="514")

module(load="imtcp")
input(type="imtcp" port="514")

Bu portları güvenlik duvarı üzerinde açmayı da unutmayalım:

$ sudo ufw allow 514

Ardından cihazımdan gelecek logların saklanacağı dosyayı belirledim

$template PerHostLog,"/var/log/rsyslog/netmaster.log"
if $fromhost-ip startswith '192.168.0' then -?PerHostLog
& STOP

Elbette modemimin üzerindeki ilgili sayfaya giderek logları syslog sunucuya göndermek için raspberry PI'ın IP adresini yazmam da gerekti.

Bu da yetmedi, bir süredi adını çok duyduğum PI-hole'u kurmayı denedim. Ev ağımızda reklamlardan kurtulmak için faydalı olduğunu okumuştum. Kurma işlemi gayet basit, sayfada anlatıldığı gibi. Kurduktan sonra yine (aynı zamanda DHCP sunucum olan) modemime gittim ve IP atamaları sırasında internet hizmet sağlayıcımın değil de PI-hole cihazım üzerinden IP sorgularını çözmesini sağladım. Bu şekilde reklam ve diğer istenmeyen IP adreslerinin kara listeye alınmasını sağladım. Ama önceden belirtmekte fayda var; youtube reklamları bu yöntemle engellenmiyor. Çoğu durumda uBlock yine vazgeçilmez.

PI-hole ile birlikte lighttpd web sunucusu geliyor ve çoklu sanal sunucuları destekliyor. Varsayılan olarak bir sanal sunucuda kendi portalını çalıştırıyor. İkinci bir sanal sunucu oluştursam da ARP taraması sonuçlarını ssh ile giriş yapmadan bir web arayüzünden görüntülesem diye düşündüm. Bu kısım beni biraz uğraştırdı. Lighttpd web sunucusuna ayrı bir yazı yazmak isterim ileride; çok yetenekli bir sunucu. Yapılandırmasını çözmem biraz zaman aldı. Apache ile ilgili tonlarca kaynak var, ama lighttpd ile ilgili bilgi daha az.

Önce şu videoda anlatıldığı gibi /etc/dnsmasq.d klasörünün altına 02-lan.conf dosyasını oluşturarak PI-hole üzerinde yerel DNS kayıtları oluşturmak istedim. Bu dosyanın içeriğini

addn-hosts=/etc/pihole/lan.list

olarak kaydettim. Sonra /etc/pihole/lan.list dosyasının içeriğini de 

192.168.xx.xx    arp.lan

olarak kaydettim. Telefonumdaki bir tarayıcıdan bile http://arp.lan ile bu siteye girebileceğim :)

Buraya kadarki kısım sadece yerel DNS kaydı oluşturmak içindi (ve güncellemelerde varsayılan doslaların üzerine yazılmasından kaçınmak için). Bundan sonra asıl sanal sunucuyu oluşturmak için /etc/lighttpd/external.conf dosyasına şu içeriği kaydettim:

$HTTP["host"] =~ "(^|.)arp.lan$" {
    server.document-root = "/var/www/html/arp.lan/"
    server.dir-listing = "enable"
}

Sonra da elbette /var/www/html/arp.lan klasörünü oluşturdum. Buradaki içeriğin de daha önce bahsettiğim ARP taramasında envanterimde olmayan cihazların MAC adreslerini içeren dosyaların kopyalanmasını (temizle.sh dosyasının son satırı) sağladım.

DNS sorguları ve web sitesi için sırasıyla 53 ve 80 numaralı portları da açmayı unutmayalım:

$ sudo ufw allow 53 # DNS için hem UDP hem TCP

$ sudo ufw allow 80/TCP # HTTP için sadece TCP

Başka ilave listeler de bulup PI-hole'a ekledim, malware ve daha fazla reklam engellemesi için. Şu anda yerel ağımızdaki DNS sorgularının %10'unun PI-hole tarafından engelleniyor. Bu trafiğin ve bağlantı için harcanan zamanın %10'u değil, sadece sayısal olarak yapılan DNS sorgularının oranı. Ölçmedim, ama büyük olasılıkla daha yüksek bir oranda trafik ve zaman kazancı sağlayacaktır.

Tam bitti derken reddit'te PI.Alert projesini okudum. Niye, ama niye?

Hiç yorum yok: