Gereksinimler ve Ön Hazırlık
Projemize başlamadan önce Python 3.12 veya daha güncel bir sürümün yüklü olduğundan emin olmalısınız. Ağ tarama işlemleri için Python'un standart kütüphaneleri olan socket, threading ve queue modüllerini kullanacağız. Harici bir bağımlılığa ihtiyaç duymadan, sistemin kendi kütüphaneleriyle yüksek performanslı bir araç geliştireceğiz.
Geliştirme ortamınızda şu komutla Python sürümünüzü kontrol edebilirsiniz:
python --version
Ağ tarama işlemleri sırasında işletim sisteminizin güvenlik duvarı (firewall) veya antivirüs yazılımları, gönderdiğiniz paketleri "şüpheli" olarak işaretleyebilir. Bu nedenle, kendi yerel ağınızda veya yetkili olduğunuz ortamlarda test yapmanız önerilir.
Temel Soket Programlama Mantığı
Bir ağ tarayıcısının kalbi "soket" yapısıdır. Soket, iki cihaz arasındaki veri alışverişini sağlayan uç noktadır. Python'da bir portun açık olup olmadığını anlamak için o porta bir bağlantı isteği göndeririz. Eğer bağlantı kabul edilirse port açıktır, reddedilirse kapalıdır.
Aşağıdaki örnek, tek bir IP ve port için basit bir bağlantı denemesini gösterir:
import socket
def port_kontrol(ip, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(1)
sonuc = s.connect_ex((ip, port))
s.close()
return sonuc == 0
# Örnek kullanım: 192.168.1.1 IP'sinin 80. portunu kontrol et
print(f"Port açık mı: {port_kontrol('192.168.1.1', 80)}")
Burada connect_ex metodu, bağlantı başarılıysa 0 değerini döndürür. settimeout(1) kullanımı, yanıt vermeyen portlarda programın sonsuza kadar beklemesini engeller.
Çok İş Parçacıklı (Multi-Threading) Yapının Kurulması
Tek bir işlemle 1000 portu taramak dakikalar sürebilir. threading modülü ile bu işlemi paralel hale getirerek süreyi saniyelere indirebiliriz. İş parçacıkları, aynı bellek alanını paylaşarak CPU'nun boşta kalan zamanlarını değerlendirir.
İş parçacıklarını yönetmek için queue (kuyruk) yapısını kullanmak en güvenli yöntemdir. Bu sayede her bir iş parçacığı, kuyruktaki bir sonraki portu alıp işlemeye başlar.
import threading
from queue import Queue
kuyruk = Queue()
def tarayici():
while not kuyruk.empty():
port = kuyruk.get()
if port_kontrol("127.0.0.1", port):
print(f"Port {port} açık!")
kuyruk.task_done()
# Kuyruğu doldur
for i in range(1, 1025):
kuyruk.put(i)
# İş parçacıklarını başlat
for _ in range(100):
thread = threading.Thread(target=tarayici)
thread.start()
Bu kod bloğunda 100 farklı iş parçacığı aynı anda 1024 portu tarar. kuyruk.task_done() metodu, iş parçacığının görevi bitirdiğini sisteme bildirir.
Performans ve Yöntem Karşılaştırması
Ağ tarama işlemlerinde farklı yöntemler farklı ihtiyaçlara hitap eder. Aşağıdaki tablo, Python ile geliştirilen tarama yaklaşımlarını karşılaştırmaktadır.
| Yöntem | Hız | Karmaşıklık | Kullanım Alanı |
|---|---|---|---|
| Sıralı (Single-thread) | Çok Düşük | Düşük | Hata ayıklama |
| Çok İş Parçacıklı (Threading) | Yüksek | Orta | Yerel ağ/Sunucu tarama |
| Asenkron (Asyncio) | Çok Yüksek | Yüksek | Geniş ölçekli ağlar |
Güvenlik ve Etik Kullanım
Kritik Uyarı: Ağ tarama araçları, izinsiz kullanıldığında saldırı girişimi olarak algılanabilir. Yalnızca sahibi olduğunuz veya üzerinde yazılı izninizin bulunduğu ağlarda test yapın. Yasal sorumluluk tamamen kullanıcıya aittir.
Tarama yaparken ağ trafiğini aşırı yüklememek için "sleep" (bekleme) süreleri eklemek veya iş parçacığı sayısını ağın kapasitesine göre sınırlamak iyi bir pratiktir. Çok yüksek iş parçacığı sayısı, hedef cihazın servis dışı kalmasına (DoS) neden olabilir.
Gelişmiş Tarama: IP Aralığı ve Port Listesi
Şimdi kodumuzu daha modüler hale getirelim. Kullanıcıdan IP aralığı alan ve bu aralıktaki tüm cihazları tarayan bir yapı kuralım.
def ip_tarama(ip_listesi, portlar):
for ip in ip_listesi:
print(f"Hedef taranıyor: {ip}")
for port in portlar:
kuyruk.put((ip, port))
# İş parçacıklarını başlatma mantığı buraya gelecek
Bu yapıda, kuyruk içerisinde artık sadece port değil, (ip, port) demeti (tuple) tutulmaktadır. Bu yöntem, geniş ağ yapılarında cihaz envanteri çıkarmak için oldukça etkilidir.
Sıkça Sorulan Sorular
Neden threading yerine multiprocessing kullanmıyoruz?
threading, I/O (Giriş/Çıkış) ağırlıklı işlemler için idealdir. Ağ tarama işlemi ağ soketlerine dayalı bir I/O işlemi olduğu için threading yeterlidir ve daha az bellek tüketir.
Programım neden bazı portları kaçırıyor?
Bunun nedeni genellikle ağ tıkanıklığıdır. Çok fazla iş parçacığı aynı anda ağa yüklendiğinde paket kayıpları oluşabilir. İş parçacığı sayısını azaltmayı deneyin.
Tarama hızını nasıl artırabilirim?
İş parçacığı sayısını artırabilirsiniz ancak bu, ağ cihazınızın (router/switch) limitlerine takılabilir. Daha hızlı bir tarama için asyncio kütüphanesini araştırmanızı öneririm.
Bu araçla hangi protokolleri tarayabilirim?
Bu temel kod TCP protokolünü tarar. UDP taraması yapmak isterseniz socket.SOCK_DGRAM kullanmanız gerekir, ancak UDP'nin doğası gereği yanıt almak daha zordur.
Sistem kaynaklarını nasıl korurum?
Tarama sırasında time.sleep(0.01) gibi kısa beklemeler ekleyerek işlemci üzerindeki yükü dengeleyebilirsiniz.
Tarama Sonuçlarını SQLite Veritabanında Saklama
Ağ tarayıcınızdan gelen verileri anlık olarak ekrana yazdırmak yerine, kalıcı bir veritabanında saklamak, ağınızdaki değişimleri zaman içinde izlemenize olanak tanır. Python'un yerleşik sqlite3 kütüphanesi, bu tür hafif ölçekli verileri yönetmek için idealdir. Aşağıdaki örnek, tarama sonuçlarını bir tabloya nasıl kaydedeceğinizi göstermektedir.
import sqlite3
def veritabani_kaydet(ip, port, durum):
conn = sqlite3.connect('ag_tarama_sonuclari.db')
cursor = conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS sonuclar
(ip TEXT, port INTEGER, durum TEXT, zaman TIMESTAMP)''')
cursor.execute("INSERT INTO sonuclar VALUES (?, ?, ?, CURRENT_TIMESTAMP)", (ip, port, durum))
conn.commit()
conn.close()
# Tarama fonksiyonunuz içinde kullanımı:
# if port_acik:
# veritabani_kaydet(hedef_ip, port, "AÇIK")
Scapy ile Paket Analizi ve İleri Seviye Tarama
Standart socket kütüphanesi TCP bağlantısı kurarak "Connect Scan" yapar. Ancak, daha gizli ve hızlı bir tarama yöntemi olan "SYN Scan" (yarı açık tarama) gerçekleştirmek isterseniz, scapy kütüphanesini kullanmanız gerekir. scapy, ağ paketlerini düşük seviyede oluşturmanıza ve manipüle etmenize olanak tanır.
Dikkat: Scapy kullanımı için işletim sistemi düzeyinde yönetici (root/administrator) yetkilerine sahip olmanız gerekir.
from scapy.all import sr1, IP, TCP
def syn_tarama(hedef_ip, port):
# SYN paketi oluştur
paket = IP(dst=hedef_ip)/TCP(dport=port, flags="S")
# Paketi gönder ve yanıtı bekle
yanit = sr1(paket, timeout=1, verbose=0)
if yanit is None:
return "Filtrelenmiş veya Kapalı"
elif yanit.haslayer(TCP):
if yanit.getlayer(TCP).flags == 0x12: # SYN-ACK
return "Açık"
elif yanit.getlayer(TCP).flags == 0x14: # RST-ACK
return "Kapalı"
return "Bilinmiyor"
Performans Analizi ve İyileştirme Tablosu
Farklı tarama yöntemlerinin sistem üzerindeki etkilerini ve hızlarını aşağıdaki tabloda inceleyebilirsiniz:
| Yöntem | Hız | Gizlilik | Gereksinim |
|---|---|---|---|
| Socket (TCP Connect) | Orta | Düşük | Standart Kullanıcı |
| Scapy (SYN Scan) | Yüksek | Yüksek | Root/Admin |
| Scapy (UDP Scan) | Düşük | Orta | Root/Admin |
Dağıtık Tarama İçin İleri İpuçları
Büyük bir ağ altyapısını tararken, tek bir makine üzerindeki threading yapısı bir noktadan sonra darboğaz oluşturabilir. Bu durumda şu stratejileri izleyebilirsiniz:
- İşlemci Bağlılığı (CPU Affinity): Çok çekirdekli sistemlerde iş parçacıklarını belirli çekirdeklere atayarak bağlam değiştirme (context switching) maliyetini azaltın.
- Ağ Arayüzü Yönetimi: Eğer sisteminizde birden fazla ağ kartı varsa, tarama trafiğini bu kartlar arasında bölüştürerek bant genişliği limitlerini aşın.
- Hata Yönetimi:
socket.erroristisnalarını yakalarken, "Too many open files" hatasına karşıulimitdeğerlerinizi kontrol edin ve her tarama sonrası soketleris.close()ile mutlaka kapatın.
Bu ileri seviye yaklaşımlar, basit bir port tarayıcısını kurumsal düzeyde bir ağ keşif aracına dönüştürmenize yardımcı olacaktır. Kodunuzu yazarken her zaman modüler bir yapı kurmaya ve fonksiyonlarınızı test edilebilir parçalara bölmeye özen gösterin.
Sonuç
Python ile çok iş parçacıklı bir ağ tarayıcısı geliştirmek, ağ programlama dünyasına giriş yapmak için mükemmel bir projedir. Bu makalede soketlerin nasıl çalıştığını, iş parçacıklarıyla performansı nasıl artıracağınızı ve kuyruk yapısını nasıl yöneteceğinizi öğrendiniz. Bir sonraki adım olarak, tarama sonuçlarını bir veritabanına (örneğin SQLite) kaydeden veya sonuçları görselleştiren bir arayüz ekleyerek projenizi daha profesyonel hale getirebilirsiniz.
Kod güvenliği sorumluluk reddi: Bu rehberdeki kodlar eğitim amaçlıdır. Üretim ortamlarında kullanmadan önce girdi doğrulama, hata yönetimi (try-except blokları) ve ağ trafiği limitlerini içeren profesyonel güvenlik katmanlarını eklediğinizden emin olun.

Yorumlar (0)
Yorum Yaz