TCP proxy'ler durum bilgisi tutan, bağlantı yönelimli veri akışlarını garantili teslim ve sıra ile yönetir; UDP proxy'ler ise bağlantısız datagramları iletir ve daha düşük gecikme ile daha az ek yük sunar, ancak taşıma katmanında doğal bir güvenilirlik, sıralama veya oturum yönetimi sağlamaz. Bu temel fark, uygulanış biçimlerini, performans özelliklerini ve uygun kullanım alanlarını belirler.
TCP ve UDP protokollerini anlamak
Transmission Control Protocol (TCP) ve User Datagram Protocol (UDP), IP yığınındaki iki temel taşıma katmanı protokolüdür. Birbirinden farklı özellikleri, bir proxy hizmetinin her birinin trafiğini işlemek için nasıl çalışması gerektiğini doğrudan etkiler.
TCP: bağlantı yönelimli ve güvenilir
TCP, herhangi bir veri aktarımı başlamadan önce istemci ile sunucu arasında kalıcı ve çift yönlü bir bağlantı kurar. Bu bağlantı yönelimli yapı şunları sağlar:
* Güvenilir veri aktarımı: veri segmentleri alıcı tarafından onaylanır. Onay alınmazsa gönderici veriyi yeniden iletir.
* Sıralı veri teslimi: segmentler hedefte doğru sırayla yeniden birleştirilir, sırasız gelseler bile.
* Akış kontrolü: hızlı bir göndericinin yavaş bir alıcıyı boğmasını engeller.
* Tıkanıklık kontrolü: tıkanıklık çöküşünü önlemek için ağ trafiğini yönetir.
Bu özellikler TCP'yi, veri bütünlüğü ve sırasının kritik olduğu uygulamalar için uygun kılar.
UDP: bağlantısız ve güvenilir olmayan
UDP daha basit, bağlantısız bir protokoldür. Önceden bağlantı kurmadan ve teslimi garanti etmeden datagram adı verilen bağımsız paketler gönderir. Özellikleri şunlardır:
* Bağlantı kurma/kapatma yok: ek yükü ve gecikmeyi azaltır.
* Güvenilir olmayan teslim: datagramlar kaybolabilir, çoğaltılabilir veya göndericiye bildirilmeden sırasız ulaşabilir.
* Akış veya tıkanıklık kontrolü yok: veri, uygulamanın hızında gönderilir.
UDP; hızın ve düşük gecikmenin garantili teslimden daha önemli olduğu ya da güvenilirliğin uygulama tarafından üst katmanda ele alındığı durumlarda tercih edilir.
TCP proxy'leme
Bir TCP proxy, biri istemciyle diğeri hedef sunucuyla olmak üzere iki ayrı TCP bağlantısı kurarak çalışır. Aracı görevi görür ve bu iki bağlantı arasında veriyi iletir.
İşleyiş
- İstemci-proxy bağlantısı: istemci, proxy'ye bir TCP bağlantısı başlatır.
- Proxy-sunucu bağlantısı: istemcinin bağlantı isteğini alan proxy, hedeflenen sunucuya kendi TCP bağlantısını kurar.
- Veri iletimi: her iki bağlantı kurulduktan sonra proxy, istemci bağlantısından veriyi okuyup sunucu bağlantısına yazar ve tersini yapar.
- Durum yönetimi: proxy, her istemci-sunucu oturumu için durum bilgisi tutar; ilişkili iki TCP bağlantısını ve bunların veri akışlarını izler. Bu durum bilgisi, doğru veri yönlendirmesi ve bağlantı yönetimi için kritiktir.
- Bağlantının kapatılması: istemci ya da sunucu bağlantısını kapattığında proxy, ilgili bağlantının ve sonunda kendi bağlantısının düzgün biçimde sonlandırılmasını yönetir.
Kullanım senaryoları
TCP proxy'ler, TCP üzerine kurulu her uygulama katmanı protokolü için kullanılır:
* HTTP/HTTPS proxy'leri: web'de gezinme, API çağrıları.
* SOCKS proxy'leri: çeşitli TCP uygulamaları için genel amaçlı proxy'leme (örneğin SSH, FTP, P2P).
* SMTP/POP3/IMAP proxy'leri: e-posta hizmetleri.
* Veritabanı proxy'leri: MySQL, PostgreSQL vb.
* SSH proxy'leri: güvenli kabuk bağlantıları.
Örnek: basit TCP proxy mantığı (kavramsal)
import socket
def tcp_proxy(listen_port, target_host, target_port):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('0.0.0.0', listen_port))
server_socket.listen(5)
print(f"Listening on port {listen_port} for TCP traffic...")
while True:
client_conn, client_addr = server_socket.accept()
print(f"Client {client_addr} connected.")
target_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
target_socket.connect((target_host, target_port))
print(f"Connected to target {target_host}:{target_port}.")
# Gerçek bir proxy'de çift yönlü iletim için thread/asenkron G-Ç gerekir
# Basitlik adına bu örnek yalnızca bağlantı kurulumunu gösterir.
# Veri iletim mantığı buraya gelirdi.
# Örnek: client_conn.recv(4096) -> target_socket.send()
# ve target_socket.recv(4096) -> client_conn.send()
except Exception as e:
print(f"Could not connect to target: {e}")
finally:
client_conn.close()
target_socket.close()
# Örnek kullanım (gerçek iletim için ayrı bir thread/süreçte çalıştırın)
# tcp_proxy(8080, 'www.example.com', 80)
UDP proxy'leme
Bir UDP proxy, bağlantısız datagramları iletir. UDP'de açık bağlantılar bulunmadığından, bir UDP proxy'nin temel zorluğu yanıt datagramlarını doğru şekilde kaynak istemciye geri yönlendirmektir.
İşleyiş
- İstemci-proxy datagramı: istemci, proxy'ye bir UDP datagramı gönderir.
- Proxy-sunucu datagramı: proxy datagramı alır ve hedeflenen sunucuya iletir.
- Yanıt işleme (durum bilgili eşleme): sunucunun yanıtını doğru istemciye yönlendirmek için proxy, istemcinin (kaynak IP, kaynak port) bilgisi ile datagramı sunucuya göndermek için kullandığı kendi (kaynak IP, kaynak port) bilgisi arasındaki eşlemeyi geçici olarak saklamalıdır.
- Yanıt iletimi: sunucu proxy'ye yanıt verdiğinde proxy, sakladığı eşlemeyi kullanarak yanıt datagramının hedef adres/portunu özgün istemcinin adres/portuna yeniden yazar ve ardından iletir.
- Oturum zaman aşımı: UDP'de açık bir bağlantı sonlandırma olmadığından bu eşlemeler genellikle kısa ömürlüdür ve belirli bir hareketsizlik süresinden sonra sona erer.
Zorluklar
- NAT traversal: UDP proxy'ler, tek bir genel IP arkasındaki birden çok istemciyi yönetmek için sık sık Network Address Translation (NAT) uygular.
- Asimetrik trafik: yanıtlar farklı bir yol izlerse veya trafiği sunucu başlatırsa, proxy ilgili tüm paketleri göremeyebilir; bu da durum yönetimini zorlaştırır.
- DDoS amplifikasyonu: uygun denetimler olmadan UDP proxy'ler, sahte kaynaklardan gelen istekleri yüksek bant genişlikli sunuculara ilettiklerinde DDoS amplifikasyon saldırılarında kötüye kullanılabilir.
Kullanım senaryoları
UDP proxy'ler, hızı önceleyen ya da güvenilirliği uygulamanın üstlendiği protokollerde kullanılır:
* DNS proxy'leri: alan adı çözümleme.
* NTP proxy'leri: zaman senkronizasyonu.
* VoIP/RTP proxy'leri: gerçek zamanlı ses ve video iletişimi.
* Oyun proxy'leri: çok oyunculu çevrimiçi oyunlar.
* SNMP proxy'leri: ağ yönetimi.
Örnek: basit UDP proxy mantığı (kavramsal)
import socket
import time
def udp_proxy(listen_port, target_host, target_port):
proxy_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
proxy_socket.bind(('0.0.0.0', listen_port))
print(f"Listening on port {listen_port} for UDP traffic...")
# (client_addr, client_port) -> (proxy_addr, proxy_port, timestamp) saklar
# yanıtları geri yönlendirmek için
client_map = {}
TIMEOUT = 60 # saniye
while True:
data, client_address = proxy_socket.recvfrom(4096)
# İstemci eşlemesini sakla
client_map[client_address] = (proxy_socket.getsockname()[0], proxy_socket.getsockname()[1], time.time())
# Hedefe ilet
proxy_socket.sendto(data, (target_host, target_port))
# Hedeften gelen yanıtları kontrol et (basitleştirilmiş; gerçek proxy select/poll kullanır)
proxy_socket.settimeout(0.1) # Yanıtları kontrol etmek için kısa zaman aşımı
try:
reply_data, server_address = proxy_socket.recvfrom(4096)
# Bu yanıta ait özgün istemciyi bul
# Gerçek bir senaryoda proxy, özgün isteği belirli bir geçici porttan
# gönderip eşlemesini yapardı. Bu örnek fazla basit.
# Daha sağlam bir çözüm, her istemci-sunucu çifti için yeni bir socket oluşturmayı
# ya da geçici port havuzunu yönetip eşlemeyi gerektirir.
# Bu basit örnekte yanıtın, trafik gönderen son istemciye ait olduğunu varsayıyoruz
# Üretimdeki bir UDP proxy BÖYLE çalışmaz.
# Basitleştirilmiş: yalnızca bilinen son istemciye geri gönder
if client_address in client_map:
proxy_socket.sendto(reply_data, client_address)
print(f"Forwarded reply from {server_address} to {client_address}")
except socket.timeout:
pass # Henüz yanıt yok
# Eski eşlemeleri temizle
current_time = time.time()
for addr, (p_ip, p_port, ts) in list(client_map.items()): # Kopya üzerinde dolaş
if current_time - ts > TIMEOUT:
del client_map[addr]
# Örnek kullanım (gerçek iletim için ayrı bir thread/süreçte çalıştırın)
# udp_proxy(53, '8.8.8.8', 53)
Karşılaştırma: TCP proxy vs. UDP proxy
| Özellik | TCP proxy | UDP proxy |
|---|---|---|
| Bağlantı | Bağlantı yönelimli (iki akış kurar) | Bağlantısız (datagram iletir) |
| Güvenilirlik | Garantili teslim, yeniden iletim | Garantili teslim yok, datagramlar kaybolabilir |
| Sıra | Garantili sıralı teslim | Garantili sıra yok, datagramlar sırasız gelebilir |
| Durum bilgisi | Yüksek düzeyde durum bilgili (bağlantı durumunu yönetir) | Orta düzeyde durum bilgili (yanıtlar için adres eşlemelerini yönetir) |
| Ek yük | Daha yüksek (handshake, onaylar) | Daha düşük (minimum başlık, handshake yok) |
| Gecikme | Daha yüksek (güvenilirlik mekanizmaları nedeniyle) | Daha düşük (gönder ve unut) |
| Karmaşıklık | Bağlantı yaşam döngüsünü, akış kontrolünü yönetir | Geçici eşlemeleri, NAT traversal'ı yönetir |
| Yaygın protokoller | HTTP/S, FTP, SSH, SMTP, MySQL, PostgreSQL | DNS, NTP, RTP (VoIP), oyun, SNMP |
Proxy uygulamaları için pratik hususlar
Durum bilgisi ve kaynak kullanımı
- TCP proxy'ler: her etkin TCP bağlantısı kaynak tüketir (arabellekler için bellek, dosya tanıtıcıları). Yüksek sayıda eşzamanlı bağlantı, proxy kaynaklarını tüketebilir. Proxy, her istemci oturumu için iki bağlantının tüm yaşam döngüsünü yönetmelidir.
- UDP proxy'ler: "oturum" (istemci-sunucu çifti) başına kaynak kullanımı genellikle daha hafiftir; esas olarak geçici adres eşlemesini saklamak içindir. Ancak çok sayıda geçici eşlemeyi yönetmek ve olası zaman aşımlarını verimli biçimde ele almak dikkatli bir tasarım gerektirir.
Performans ve ölçeklenebilirlik
- TCP proxy'ler: performans, bağlantı kurma ve sürdürme ek yükünden etkilenebilir; özellikle kısa ömürlü bağlantılarda. Optimizasyonlar genellikle bağlantı havuzu veya çoğullama içerir.
- UDP proxy'ler: düşük ek yükü sayesinde paket kaybına toleranslı uygulamalar için daha yüksek verim sunar. Ölçeklenebilirlik genellikle trafiği yük dengeleyicilerle birden çok proxy örneğine dağıtarak sağlanır.
Güvenlik açısından etkileri
- TCP proxy'ler: trafiği uygulama katmanında inceleyip filtreleyebilir (örneğin içerik filtreleme için HTTP proxy'leri, WAF'lar). Şifreli trafiği incelemek için TLS bağlantılarını sonlandırabilir (HTTPS proxy).
- UDP proxy'ler: bağlantısız yapı ve çoğu zaman uygulamaya özgü protokoller nedeniyle paket incelemesi daha zordur. Yanlış yapılandırılmış UDP proxy'ler DDoS amplifikasyon saldırılarında kullanılabilir. Hız sınırlama ve kaynak doğrulama uygulamak kritiktir.
Hibrit proxy hizmetleri
SOCKS5 gibi bazı proxy çözümleri hem TCP hem de UDP proxy'lemeyi destekler. Bir istemci UDP ilişkilendirmesi talep ettiğinde, SOCKS5 sunucusu genellikle kendi tarafında bir UDP portu bağlar ve istemci ile hedef arasında UDP datagramlarını aktarır; yanıtlar için gerekli adres çevirisini de yapar. Bu sayede tek bir proxy hizmeti çok daha geniş bir ağ uygulaması yelpazesine hizmet edebilir.
