Uzak sunucularla çalışırken, özellikle de bir GUI’ye ihtiyacınız olduğunda, SSH bazen yetersiz kalır. Ekran paylaşımlı bir ortam kurmak için RDP gibi ticari çözümlere para vermek istemediğimiz veya TeamViewer gibi kapalı kaynak yazılımlara güvenmediğimiz durumlar oluyor. İşte tam da bu noktada, yıllardır beni birçok sıkıntıdan kurtarmış olan VNC devreye giriyor. “Yeni başlayanlar için Python ile VNC server yapımı” derken, aslında Python’ı bir VNC sunucusunu kurmak, yapılandırmak ve yönetmek için nasıl bir araç olarak kullanabileceğimizden bahsedeceğim. Sıfırdan bir VNC protokolü yazmak değil amacım; bu, yeni başlayanlar için değil, doktora tezi konusu olur.
Kendi kariyerimde, özellikle hızlıca bir test ortamı kurmam gerektiğinde veya bir geliştiricinin GUI tabanlı bir araca erişmesi gerektiğinde, VNC benim için her zaman pratik bir çözüm olmuştur. Ancak, VNC’nin kendi başına getirdiği güvenlik ve yönetim zorlukları da cabası. İşte bu yüzden, Python’ın esnekliğini kullanarak bu süreci nasıl otomatize edip daha güvenli hale getirebileceğinizi göstereceğim.
VNC Nedir ve Perde Arkasında Neler Döner?
VNC (Virtual Network Computing), temel olarak bir uzak bilgisayarın grafiksel masaüstünü başka bir bilgisayara aktaran bir sistemdir. Bunu yaparken, Remote Framebuffer (RFB) protokolünü kullanır. RFB, aslında çok basit bir mantıkla çalışır: Sunucu tarafındaki ekranın piksel verilerini alır, sıkıştırır ve istemciye gönderir. İstemci de bu pikselleri kendi ekranında gösterir. İstemciden gelen fare ve klavye hareketleri de sunucuya geri gönderilir.
Peki, bu işin Python ile ne alakası var? Ben genelde Python’ı, mevcut VNC sunucu yazılımlarını (x11vnc, TigerVNC, TightVNC gibi) başlatmak, durdurmak, konfigüre etmek ve hatta durumlarını izlemek için bir orkestrasyon aracı olarak kullanıyorum. RFB protokolünün kendisi de basit bir yapıya sahip olsa da, sıfırdan bir implementasyon yazmak çok zaman alır. Benim gibi pratik düşünen bir IT Uzmanı, tekerleği yeniden icat etmek yerine, zaten çalışan bir çözümü kendi ihtiyaçlarına göre şekillendirmeyi tercih eder.
VNC, genellikle 5900’den başlayan portları kullanır. Örneğin, ilk VNC oturumu 5901 (display :1), ikincisi 5902 (display :2) şeklinde devam eder. Bu display numaraları, VNC sunucusunun arka planda hangi X sunucusu oturumunu yöneteceğini belirler. Sunucu tarafında, bir VNC oturumu başlatıldığında, aslında bir sanal X sunucusu (Xvfb gibi) veya mevcut bir X sunucusu (x11vnc durumunda) bir portta dinlemeye başlar ve ekran güncellemelerini bekler.
Dezavantajları ve Benim Eleştirilerim: VNC’nin en büyük sorunu, RFB protokolünün kendisinin varsayılan olarak şifreleme sunmamasıdır. Yani, VNC trafiğini doğrudan internete açmak, resmen intihardır. Kaç kez loglarda Çin’den, Rusya’dan gelen binlerce brute-force denemesi gördüğümü hatırlamıyorum bile. Bant genişliği tüketimi de ayrı bir dert. Yüksek çözünürlüklü bir ekranı VNC üzerinden paylaştığınızda, ağınızın canına okuyabilirsiniz. Modern RDP veya Spice gibi protokoller, bu konularda VNC’ye göre fersah fersah öndedir. VNC’yi hala kullanıyorsam, bu genellikle eski bir sistemle uğraştığım ya da çok basit bir GUI erişimine ihtiyacım olduğu içindir; yoksa RDP varken kim uğraşır?
Uygulama: Python ile Basit Bir VNC Sunucusu Kurulumu
Şimdi gelelim işin pratiğine. Ben burada x11vnc kullanacağım çünkü mevcut bir X oturumunu paylaşmak için oldukça esnek ve hafif bir araç. Amaç, Python ile bu kurulumu ve yönetimi otomatize etmek.
1. Gerekli Paketlerin Kurulumu
Öncelikle, bir Linux sunucusu (benim favorim Ubuntu Server) üzerinde çalıştığımızı varsayalım. SSH ile sunucunuza bağlanın ve aşağıdaki komutları çalıştırın:
sudo apt update # Paket listelerini günceller
sudo apt install -y x11vnc xvfb xserver-xorg-core xfonts-base xterm openbox # Gerekli VNC ve X bileşenlerini kurar
sudo apt install -y python3-pip # Python pip paket yöneticisini kurar (eğer yüklü değilse)
pip install psutil # Python'da süreç yönetimi için kullanacağımız kütüphane
x11vnc, mevcut bir X sunucusunu paylaşır. Eğer bir masaüstü ortamı yüklü değilse, xvfb (X Virtual Framebuffer) ile sanal bir X sunucusu oluşturup onun üzerinden VNC sağlayabiliriz. Ben genellikle sanal bir ortam tercih ederim çünkü gerçek masaüstü ortamını paylaşmak her zaman iyi bir fikir değildir.
2. VNC Şifresi Belirleme
VNC, şifresiz başlamanıza izin verse de, bu ölümcül bir hata olur. Ben her zaman öncelikle bir şifre belirlerim:
x11vnc -storepasswd # VNC bağlantısı için bir şifre belirler ve kaydeder
# Bu komut sizden bir şifre girmenizi isteyecektir. Güçlü bir şifre kullanın.
Bu komut, genellikle kullanıcının ev dizininde .vnc/passwd dosyasına şifreyi kaydeder.
3. Python ile VNC Sunucusunu Yönetme
Şimdi, VNC sunucusunu başlatmak ve durdurmak için basit bir Python scripti yazalım. Bu script, x11vnc‘yi bir xvfb oturumu üzerinde başlatacak ve belirli bir portta dinleyecek.
# vnc_manager.py
import subprocess
import os
import time
import psutil # Süreçleri yönetmek için kullanacağız
# --- Yapılandırma ---
VNC_DISPLAY = ":1" # VNC oturumunun display numarası
VNC_PORT = 5901 # VNC istemcilerinin bağlanacağı port (5900 + display numarası)
VNC_GEOMETRY = "1280x800" # Sanal ekranın çözünürlüğü
VNC_PASSWORD_FILE = os.path.expanduser("~/.vnc/passwd") # VNC şifre dosyasının yolu
VNC_LOG_FILE = os.path.expanduser("~/vncserver.log") # VNC sunucusunun log dosyası
XTERM_CMD = "xterm -geometry 80x24+10+10 -fg white -bg black" # Başlatılacak terminal uygulaması
def is_vnc_running():
"""Belirtilen VNC portunda bir sürecin çalışıp çalışmadığını kontrol eder."""
for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
try:
cmdline = " ".join(proc.cmdline())
if "x11vnc" in cmdline and VNC_DISPLAY in cmdline:
print(f"VNC sunucusu zaten çalışıyor (PID: {proc.pid}).")
return True
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
return False
def start_vnc_server():
"""VNC sunucusunu başlatır."""
if is_vnc_running():
return
print(f"VNC sunucusunu başlatılıyor (Display: {VNC_DISPLAY}, Port: {VNC_PORT})...")
# Sanal X sunucusunu (Xvfb) başlat
xvfb_command = [
"Xvfb", VNC_DISPLAY,
"-screen", "0", f"{VNC_GEOMETRY}x24", # 24 bit renk derinliği
"-ac", # Erişim kontrolünü devre dışı bırak (güvenlik için dikkatli olun)
"-listen", "tcp" # TCP bağlantılarına izin ver
]
# xvfb_process = subprocess.Popen(xvfb_command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) # Arka planda çalıştır
# Ben genelde logları görmek için bir süre ekrana basarım, sonra DEVNULL yaparım.
xvfb_process = subprocess.Popen(xvfb_command, stdout=open(VNC_LOG_FILE, "a"), stderr=subprocess.STDOUT)
time.sleep(2) # Xvfb'nin başlaması için biraz bekle
# x11vnc sunucusunu başlat
vnc_command = [
"x11vnc",
"-display", VNC_DISPLAY, # Hangi X display'ini paylaşacağını belirtir
"-rfbport", str(VNC_PORT), # Hangi portta dinleyeceğini belirtir
"-passwdfile", VNC_PASSWORD_FILE, # Şifre dosyasını belirtir
"-forever", # Sunucu kapanana kadar çalış
"-usepw", # Şifre kullanmaya zorla
"-loop", # Bağlantı kesilirse yeniden başlatmaya çalış
"-noxdamage", # Performans için XDamage uzantısını kapat
"-logfile", VNC_LOG_FILE, # Log dosyasını belirtir
"-bg" # Arka planda çalıştır
]
# x11vnc'yi başlat ve hemen ardından bir terminal aç
# Ben genelde VNC oturumu açıldığında bir terminalin otomatik açılmasını isterim.
# Bu, oturumun çalıştığını görmenin en kolay yoludur.
x11vnc_process = subprocess.Popen(vnc_command + ["-create", "-env", f"DISPLAY={VNC_DISPLAY}", XTERM_CMD])
# x11vnc_process = subprocess.Popen(vnc_command, stdout=open(VNC_LOG_FILE, "a"), stderr=subprocess.STDOUT)
print(f"VNC sunucusu başlatıldı. Loglar: {VNC_LOG_FILE}")
print(f"Bağlanmak için: vncviewer localhost:{VNC_PORT} (SSH tüneli ile!)")
def stop_vnc_server():
"""VNC sunucusunu durdurur."""
print("VNC sunucusunu durduruluyor...")
found_processes = False
for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
try:
cmdline = " ".join(proc.cmdline())
if "x11vnc" in cmdline and VNC_DISPLAY in cmdline:
print(f"x11vnc süreci bulunup sonlandırılıyor (PID: {proc.pid})...")
proc.terminate()
found_processes = True
elif "Xvfb" in cmdline and VNC_DISPLAY in cmdline:
print(f"Xvfb süreci bulunup sonlandırılıyor (PID: {proc.pid})...")
proc.terminate()
found_processes = True
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
if not found_processes:
print("Çalışan VNC sunucusu bulunamadı.")
else:
print("VNC sunucusu durduruldu.")
if __name__ == "__main__":
import sys
if len(sys.argv) > 1:
if sys.argv[1] == "start":
start_vnc_server()
elif sys.argv[1] == "stop":
stop_vnc_server()
else:
print("Kullanım: python3 vnc_manager.py [start|stop]")
else:
print("Kullanım: python3 vnc_manager.py [start|stop]")
Bu scripti vnc_manager.py olarak kaydedin. Ardından, aşağıdaki komutlarla kullanabilirsiniz:
python3 vnc_manager.py start # VNC sunucusunu başlatır
python3 vnc_manager.py stop # VNC sunucusunu durdurur
Bu script, Xvfb ile sanal bir X sunucusu oluşturur ve x11vnc‘yi bu sanal sunucu üzerinden başlatır. Ayrıca, VNC oturumu başladığında otomatik olarak bir xterm penceresi açar, bu da bana sunucunun gerçekten çalıştığını gösteren iyi bir işarettir.
4. VNC İstemcisi ile Bağlanma (ÇOK ÖNEMLİ!)
Yukarıda da bahsettiğim gibi, VNC trafiğini doğrudan internete açmak çok tehlikelidir. Ben projelerimde her zaman SSH tünelleme kullanırım. Bu, VNC trafiğinizin şifreli bir SSH bağlantısı üzerinden geçmesini sağlar.
Yerel bilgisayarınızda (VNC istemcisini çalıştıracağınız yerde) aşağıdaki komutu çalıştırın:
ssh -L 5901:localhost:5901 kullaniciadi@sunucu_ipadresi # Yerel 5901 portunu sunucunun 5901 portuna tüneller
Bu komutu çalıştırdıktan sonra, yerel makinenizdeki herhangi bir VNC istemcisi (TigerVNC Viewer, RealVNC Viewer gibi) ile localhost:5901 adresine bağlanabilirsiniz. Bu sayede, VNC trafiğiniz SSH tüneli üzerinden güvenli bir şekilde aktarılmış olur.
“Best Practices” ve Klasik Hatalar
VNC kurarken sıkça yapılan bazı hataları ve benim bu konudaki önerilerimi paylaşmak isterim:
- VNC’yi Doğrudan İnternete Açmak: Daha önce de söyledim, bu intihardır. VNC’nin şifrelemesi zayıftır veya yoktur. Eğer SSH tünelleme yapamıyorsanız, en azından bir VPN arkasında çalıştırın. Güvenlik duvarınızda sadece SSH (22) portunu açık bırakın.
- Zayıf Şifre Kullanmak veya Şifresiz Bırakmak: Bu da ayrı bir rezalettir. Birçok kişi “nasıl olsa içeride kullanıyorum” diyerek şifre koymuyor. Ama network’ünüzdeki herhangi bir zafiyet, bu oturuma kolayca erişime yol açar. Her zaman güçlü, karmaşık şifreler kullanın.
- Aynı VNC Oturumunu Birden Fazla Kullanıcıya Paylaştırmak: Her kullanıcıya kendi display’ini (örneğin :1, :2) atayın. Aksi takdirde, bir kullanıcının yaptığı diğerini etkiler ve işler karışır. Benim scriptimde tek bir display kullanıyoruz ama bunu çoğaltmak çok zor değil.
- Performans Ayarlarını Göz Ardı Etmek: VNC varsayılan olarak bazen çok fazla bant genişliği tüketebilir.
x11vncgibi araçlar-compresslevelve-qualitygibi parametreler sunar. Ben genelde test ortamlarında en düşük kaliteyle başlar, eğer görsel kalite gerçekten gerekliyse yavaş yavaş yükseltirim. “Her pikselin önemi yoksa, neden yavaş çalışalım ki?” derim. - VNC Servisinin Otomatik Başlamaması veya Ölünce Ayağa Kalkmaması: Yukarıdaki Python scripti manuel çalışır. Gerçek bir üretim ortamında veya sürekli kullanacağınız bir sunucuda, bu scripti bir
systemdservisi olarak yapılandırmalısınız. Bu sayede sunucu yeniden başladığında VNC oturumu da otomatik olarak başlar ve beklenmedik bir hata durumunda yeniden başlatılmaya çalışılır. Benim projelerimde her zaman bir.servicedosyası yazarım, aksi takdirde unutulur ve sunucu restart olunca “VNC neden çalışmıyor?” diye soran bir geliştiriciyle uğraşmak zorunda kalırım.
Sonuç
VNC, her ne kadar modern uzak masaüstü çözümlerinin gerisinde kalsa da, basit ve hızlı bir uzak masaüstü erişimi için hala iş görebilir bir araçtır. Özellikle Python gibi bir otomasyon diliyle birleştirildiğinde, benim gibi tembel IT Uzmanları için kurulum ve yönetim süreçlerini oldukça kolaylaştırabilir. Ancak unutmayın, güvenlik her zaman önceliklidir ve SSH tünelleme gibi basit adımlarla bile VNC deneyiminizi çok daha güvenli hale getirebilirsiniz. Bir sonraki projenizde, GUI’ye ihtiyaç duyduğunuzda, VNC’ye bir şans verin ama her zaman temkinli olun.