Pardus ETAP Yöneticileri İçin Ağ Üzerinden Toplu Şifre Değiştirme Python Uygulaması
Okullardaki Bilişim Teknolojileri Rehber Öğretmenleri ve sistem yöneticileri için en büyük zaman kaybı, basit bir işlem için onlarca sınıfı tek tek dolaşmaktır. Özellikle 30-40 adet Etkileşimli Tahtanın (ET) bulunduğu bir okulda, "ogretmen" veya "ogrenci" kullanıcısının şifresini değiştirmek için her sınıfa klavye taşımanız gerekmez.
Eğer okulunuzdaki tahtalar (ETAP 23.4 vb.) ile sizin bilgisayarınız aynı yerel ağdaysa (Örneğin: 10.46.xxx.xxx bloğu), bu işlemi oturduğunuz yerden, çayınızı yudumlarken saniyeler içinde halledebilirsiniz.
Sadece bir script kullanmaktansa (https://www.nuritiras.com.tr/2025/12/pardus-etap-yoneticileri-icin-rehber-ag.html), görsel bir arayüze (GUI) sahip bir araç, hem sizin hem de bu aracı paylaşacağınız diğer öğretmenlerin işini çok kolaylaştırır.
Bunun için Python ve PyQt6 (Modern arayüzler için) kütüphanelerini kullanacağız. Ayrıca SSH bağlantılarını yönetmek için profesyonel bir kütüphane olan Paramiko'yu kullanacağız. Bu, sshpass gibi harici araçlara olan bağımlılığı ortadan kaldırır.
İşte "Pardus Toplu Şifre Değiştirici" uygulamanızın kaynak kodları ve çalışma mantığı.
Bu özellik uygulamayı tam bir "İsviçre Çakısı"na dönüştürür. IP adreslerini tek tek elle girmek yerine, tek tuşla ağdaki aktif tahtaları bulmak kullanıcı deneyimini zirveye taşır.
Bunun için uygulamamıza şu özellikleri ekleyeceğiz:
Nmap Entegrasyonu: Arka planda
nmapkomutunu çalıştıracak bir yapı.IP Aralığı Kutusu: Hangi ağı tarayacağını belirtmek için (Örn:
10.46.197.0/24).Otomatik Kayıt: Bulunan IP'leri hem ekrana yazacak hem de
tahtalar.txtdosyasına kaydedecek.
Hazırlık Aşaması (Etap 23 Tahtalar İçin)
Adım 1: SSH Sunucusunun Yüklü Olduğundan Emin Olun
Pardus ETAP sürümlerinde güvenlik nedeniyle SSH sunucusu (openssh-server) varsayılan olarak yüklü gelmeyebilir veya yüklü olsa bile başlatılmamış olabilir.
Tahtada uçbirimi (terminal) açın ve şu komutu girin:
sudo apt update
sudo apt install openssh-server -yAdım 2: Servisi Başlatın ve Aktif Edin
SSH yüklü olsa bile servis "stop" durumundaysa bağlantı reddedilir. Servisi başlatmak ve her açılışta otomatik çalışmasını sağlamak için şu komutu girin:
sudo systemctl enable --now ssh(Bu komuttaki --now parametresi servisi hem hemen başlatır hem de başlangıca ekler.)
Hazırlık Aşaması (Yönetici Pardus PC)
1. Hazırlık: Gerekli Kütüphanelerin Kurulumu
Terminali açıp şu komutu çalıştırarak gerekli Python paketlerini yükleyin:
sudo apt install python3-pip nmap -y
pip3 install PyQt6 paramiko
2. Uygulama Kodu (pardus_yonetici.py)
İşte güncellenmiş, "Ağı Tara" butonlu uygulamanızın tam kodu:
2. Güncel Uygulama Kodu (pardus_yonetici.py)
import sys
import socket
import paramiko
import subprocess
import re
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
QHBoxLayout, QLabel, QLineEdit, QPushButton,
QTextEdit, QProgressBar, QMessageBox, QGroupBox, QFormLayout)
from PyQt6.QtCore import QRunnable, QThreadPool, pyqtSignal, QObject, Qt
# --- SİNYALLER ---
class WorkerSignals(QObject):
log = pyqtSignal(str)
progress = pyqtSignal()
finished = pyqtSignal()
result_ips = pyqtSignal(list) # Tarama sonucu bulunan IP listesini taşır
# --- SSH İŞÇİSİ (Şifre Değiştirme) ---
class SSHWorker(QRunnable):
def __init__(self, ip, admin_user, admin_pass, target_user, target_pass):
super().__init__()
self.ip = ip
self.admin_user = admin_user
self.admin_pass = admin_pass
self.target_user = target_user
self.target_pass = target_pass
self.signals = WorkerSignals()
def check_port_22(self):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2)
result = sock.connect_ex((self.ip, 22))
sock.close()
return result == 0
except:
return False
def run(self):
if not self.check_port_22():
self.signals.log.emit(f"⚠️ {self.ip}: Erişim yok veya kapalı. (Atlandı)")
self.signals.finished.emit()
return
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
self.signals.log.emit(f"🔄 {self.ip}: Bağlanılıyor...")
client.connect(self.ip, username=self.admin_user, password=self.admin_pass, timeout=5)
command = f"echo '{self.admin_pass}' | sudo -S sh -c 'echo \"{self.target_user}:{self.target_pass}\" | chpasswd'"
stdin, stdout, stderr = client.exec_command(command)
exit_status = stdout.channel.recv_exit_status()
if exit_status == 0:
self.signals.log.emit(f"✅ {self.ip}: Şifre başarıyla değiştirildi.")
else:
hata = stderr.read().decode().strip()
self.signals.log.emit(f"❌ {self.ip}: Hata! ({hata})")
except Exception as e:
self.signals.log.emit(f"❌ {self.ip}: Bağlantı hatası: {str(e)}")
finally:
client.close()
self.signals.progress.emit()
self.signals.finished.emit()
# --- YENİ: NMAP TARAMA İŞÇİSİ ---
class ScanWorker(QRunnable):
def __init__(self, network_range):
super().__init__()
self.network_range = network_range
self.signals = WorkerSignals()
def run(self):
self.signals.log.emit(f"🔍 Ağ taranıyor: {self.network_range} (Lütfen bekleyin...)")
found_ips = []
try:
# nmap komutu: -sn (port tarama yapma, sadece ping), -n (DNS çözme, hız için)
cmd = ["nmap", "-sn", "-n", self.network_range]
# Subprocess ile komutu çalıştır
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
stdout, stderr = process.communicate()
if process.returncode != 0:
self.signals.log.emit(f"❌ Tarama Hatası: nmap bulunamadı veya yetki yok.\n{stderr}")
return
# Çıktıyı analiz et (Regex ile IP yakala)
# Çıktı formatı: "Nmap scan report for 10.46.197.2"
lines = stdout.splitlines()
for line in lines:
if "Nmap scan report for" in line:
# Satırın sonundaki IP'yi al
parts = line.split()
ip = parts[-1]
# Parantez varsa temizle (bazen (192.168...) şeklinde döner)
ip = ip.replace("(", "").replace(")", "")
found_ips.append(ip)
self.signals.result_ips.emit(found_ips)
self.signals.log.emit(f"✅ Tarama bitti. {len(found_ips)} cihaz bulundu.")
except FileNotFoundError:
self.signals.log.emit("❌ Hata: 'nmap' yüklü değil. Lütfen 'sudo apt install nmap' yapın.")
except Exception as e:
self.signals.log.emit(f"❌ Beklenmedik hata: {str(e)}")
# --- ANA ARAYÜZ ---
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Pardus ETAP Yönetici Asistanı v2.0")
self.resize(650, 750)
self.threadpool = QThreadPool()
self.init_ui()
def init_ui(self):
central_widget = QWidget()
self.setCentralWidget(central_widget)
main_layout = QVBoxLayout()
# 1. Admin Bilgileri
group_admin = QGroupBox("1. Yönetici Bilgileri")
layout_admin = QFormLayout()
self.input_admin_user = QLineEdit("etapadmin")
self.input_admin_pass = QLineEdit()
self.input_admin_pass.setEchoMode(QLineEdit.EchoMode.Password)
layout_admin.addRow("Yönetici Kullanıcı:", self.input_admin_user)
layout_admin.addRow("Yönetici Şifresi:", self.input_admin_pass)
group_admin.setLayout(layout_admin)
main_layout.addWidget(group_admin)
# 2. Hedef Bilgileri
group_target = QGroupBox("2. Hedef Kullanıcı Bilgileri")
layout_target = QFormLayout()
self.input_target_user = QLineEdit("ogretmen")
self.input_target_pass = QLineEdit()
self.input_target_pass.setPlaceholderText("Yeni Şifreyi Buraya Yazın")
layout_target.addRow("Kullanıcı Adı:", self.input_target_user)
layout_target.addRow("YENİ Şifre:", self.input_target_pass)
group_target.setLayout(layout_target)
main_layout.addWidget(group_target)
# 3. Ağ Tarama ve IP Listesi (GÜNCELLENEN KISIM)
group_ips = QGroupBox("3. Hedef Tahtalar")
layout_ips_main = QVBoxLayout()
# Tarama Alanı
layout_scan = QHBoxLayout()
self.input_network = QLineEdit("10.46.197.0/24") # Varsayılan ağ
self.input_network.setPlaceholderText("Örn: 192.168.1.0/24")
self.btn_scan = QPushButton("🔍 Ağı Tara ve Listeyi Doldur")
self.btn_scan.setStyleSheet("background-color: #3498db; color: white; font-weight: bold;")
self.btn_scan.clicked.connect(self.start_scan)
layout_scan.addWidget(QLabel("Ağ Aralığı:"))
layout_scan.addWidget(self.input_network)
layout_scan.addWidget(self.btn_scan)
layout_ips_main.addLayout(layout_scan)
# Liste Alanı
self.text_ips = QTextEdit()
self.text_ips.setPlaceholderText("IP adresleri buraya gelecek...\nveya elle yazabilirsiniz.")
layout_ips_main.addWidget(self.text_ips)
group_ips.setLayout(layout_ips_main)
main_layout.addWidget(group_ips)
# 4. İşlem Butonu ve İlerleme
self.btn_start = QPushButton("🚀 Şifre Değiştirme İşlemini Başlat")
self.btn_start.setStyleSheet("background-color: #2ecc71; color: white; font-weight: bold; padding: 12px; font-size: 14px;")
self.btn_start.clicked.connect(self.start_change_process)
main_layout.addWidget(self.btn_start)
self.progress_bar = QProgressBar()
main_layout.addWidget(self.progress_bar)
# 5. Log Ekranı
self.text_log = QTextEdit()
self.text_log.setReadOnly(True)
self.text_log.setStyleSheet("background-color: #2c3e50; color: #ecf0f1; font-family: monospace; font-size: 11px;")
main_layout.addWidget(self.text_log)
central_widget.setLayout(main_layout)
def log_message(self, msg):
self.text_log.append(msg)
# Scroll en alta insin
sb = self.text_log.verticalScrollBar()
sb.setValue(sb.maximum())
# --- TARAMA FONKSİYONLARI ---
def start_scan(self):
network = self.input_network.text().strip()
if not network:
QMessageBox.warning(self, "Hata", "Lütfen bir ağ aralığı girin (Örn: 192.168.1.0/24)")
return
self.btn_scan.setEnabled(False) # Butonu kilitle
self.text_ips.clear()
worker = ScanWorker(network)
worker.signals.log.connect(self.log_message)
worker.signals.result_ips.connect(self.handle_scan_result)
self.threadpool.start(worker)
def handle_scan_result(self, ip_list):
self.btn_scan.setEnabled(True) # Butonu aç
if not ip_list:
QMessageBox.information(self, "Bilgi", "Bu ağ aralığında açık cihaz bulunamadı.")
return
# Listeyi ekrana yaz
ips_text = "\n".join(ip_list)
self.text_ips.setText(ips_text)
# Dosyaya kaydet
try:
with open("tahtalar.txt", "w") as f:
f.write(ips_text)
self.log_message(f"💾 Liste 'tahtalar.txt' olarak kaydedildi.")
QMessageBox.information(self, "Başarılı", f"{len(ip_list)} adet cihaz bulundu ve listeye eklendi.")
except Exception as e:
self.log_message(f"❌ Dosya kaydetme hatası: {e}")
# --- ŞİFRE DEĞİŞTİRME FONKSİYONLARI ---
def update_progress(self):
self.progress_bar.setValue(self.progress_bar.value() + 1)
def start_change_process(self):
admin_u = self.input_admin_user.text().strip()
admin_p = self.input_admin_pass.text().strip()
target_u = self.input_target_user.text().strip()
target_p = self.input_target_pass.text().strip()
raw_ips = self.text_ips.toPlainText().strip().split('\n')
ip_list = [ip.strip() for ip in raw_ips if ip.strip()]
if not ip_list:
QMessageBox.warning(self, "Hata", "IP listesi boş.")
return
if not admin_p or not target_p:
QMessageBox.warning(self, "Hata", "Şifre alanları boş olamaz.")
return
self.progress_bar.setMaximum(len(ip_list))
self.progress_bar.setValue(0)
self.btn_start.setEnabled(False)
self.active_workers = len(ip_list)
self.log_message(f"🚀 {len(ip_list)} tahta için işlem başlatılıyor...")
for ip in ip_list:
worker = SSHWorker(ip, admin_u, admin_p, target_u, target_p)
worker.signals.log.connect(self.log_message)
worker.signals.progress.connect(self.update_progress)
worker.signals.finished.connect(self.check_finished)
self.threadpool.start(worker)
def check_finished(self):
self.active_workers -= 1
if self.active_workers == 0:
self.btn_start.setEnabled(True)
self.log_message("🏁 Tüm işlemler tamamlandı.")
QMessageBox.information(self, "Bitti", "Tüm işlemler tamamlandı.")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())"Pardus için Python ile Sistem Yönetim Aracı Geliştirme" başlığı altında paylaşabilirsiniz. Kodlar tamamen açık kaynak ve geliştirmeye müsaittir!
Kaynak Kod: https://github.com/nuritiras/PardusEtapSifreDegistirme
3. Nasıl Çalıştırılır?
Dosyayı kaydettiğiniz klasörde terminali açın.
sudo python3 pardus_yonetici.pykomutunu yazın.Karşınıza gelen ekranda:
Yönetici Bilgileri: Tahtalara bağlanırken kullandığınız admin hesabını (örn:
etapadmin) ve şifresini girin.Hedef Bilgileri: Şifresini değiştirmek istediğiniz kullanıcıyı (örn:
ogretmen) ve yeni şifreyi yazın.IP Listesi:
tahtalar.txtdosyanızdaki veyanmapçıktısındaki IP adreslerini kopyalayıp buraya yapıştırın.
İşlemi Başlat butonuna basın.
Kodun Çalışma Mantığı
Thread Kullanımı: Hem ağ tarama (
ScanWorker) hem de şifre değiştirme (SSHWorker) işlemleri ana arayüzden ayrı iş parçacıklarında çalışır. Bu sayede tarama yaparken "Uygulama Yanıt Vermiyor" hatası almazsınız.Nmap Komutu:
nmap -sn -n 10.46.197.0/24komutunu kullanır.-sn: Port taraması yapma, sadece "orada mı?" diye bak (Ping Scan). Çok daha hızlıdır.-n: DNS çözümlemesi yapma (İsimleri çözmeye çalışmak çok vakit kaybettirir, bize sadece IP lazım).
Otomatik Kayıt: Tarama bittiğinde bulunan temiz IP listesini otomatik olarak
tahtalar.txtdosyasına yazar.Esneklik: "Ağ Aralığı" kutusu varsayılan olarak sizin IP bloğunuzla gelir ama değiştirilebilir.
Uygulamayı çalıştırıp "Ağı Tara" dediğinizde, 10-15 saniye içinde tüm açık tahtalar listeye dökülecektir.
Yorumlar
Yorum Gönder