Python ile Networking | TCP ve UDP

Bu yazıda Python ile TCP ve UDP protokollerini kullanarak socket nesnesi aracılığıyla server-client arasında network üzerinden iletişim kurmayı göreceğiz.

Python içerisinde network’e bağlı server ve client’lar oluşturmak için çeşitli third-party araçlar programcılar tarafından kullanılmaktadır. Fakat bütün bu araçların çekirdek modülü socket adı verilen modüldür. Bu modül hızlı bir biçimde TCP ve UDP client ve serverları yazmak, ham soketleri kullanmak için gerekli bütün parçaları barındırır.  Böylece çabucak, basit client ve serverlar oluşturmak mümkün hale gelir.

Soket nedir ?

Soketler bir network bağlantısının soyutlanmasına yarayan programlama nesneleridir. Çift yönlü olarak iletişim kurmamıza olanak sağlarlar. Bir kere bağlantı sağlandığında, veri iletmeye hazır olduklarında, veri iletmek veya almak için kullanılabilirler. Soket TCP ve UDP protokollerini implemente ederek kolaylıkla yönetebileceğimiz bir arayüzdür.

Notlar :

  • Örneklerde kullandığımız 127.0.0.1 IP adresi bilgisayarın kendini işaret etmektedir. (localhost)
  • Kodların Python3 versiyonlarını aşağıda bulabilirsiniz:

Şimdi basit bir TCP istemcisi yazarak başlayalım.

TCP İstemcisi (TCP Client)

Bir sistem içerisinde bir TCP client’i oluşturmak ihtiyaç duyulabilecek gayet kullanışlı bir şeydir. Aşağıda basit bir TCP client’i görülmektedir :

import socket

target_host = "www.google.com"
target_port = 80

# create a socket object
➊ client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# connect the client
➋ client.connect((target_host,target_port))

# send some data
➌ client.send("GET / HTTP/1.1\r\nHost: google.com\r\n\r\n")

# receive some data
➍ response = client.recv(4096)
print response

Socket objesini AF_INET ve SOCK_STREAM  parametreleri ile oluşturuyoruz. ➊

  • AF_INET parametresi standart IPv4 adresi ya da hostname kullanacağımızı söylüyor.
  • SOCK_STREAM bunun bir TCP client’i olacağını belirtiyor.

Server’a bağlanıyoruz.➋

Örnek bir data gönderiyoruz.➌

Son adımda ise gelen cevabı (response) ekrana yazdırıyoruz.➍

TCP client’inin en basit biçimidir. Unutmamak gerekir ki yukarıdaki kod parçasında, socket’ler hakkında kesinlikle farkında olmak istediğiniz bazı varsayımlar yapıyoruz.

İlk varsayım, bağlantımızın her zaman başarılı olacağı varsayımıdır.

İkincisi ise sunucunun her zaman önce veri göndermemizi bekleyeceği varsayımıdır. (Aksine serverlar size önce veri yollayıp cevabınızı bekleyebilir.)

Üçüncü varsayımımız sunucunun her zaman bize zamanında veri göndereceğidir. Bu varsayımları büyük ölçüde basitlik adına yapıyoruz.

UDP İstemcisi (UDP Client)

Python UDP Client’da  TCP Client’a benzerdir. Birkaç değişiklik yaparak paketleri UDP formunda yollayacağız.

import socket

target_host = "127.0.0.1"
target_port = 80

# create a socket object
➊ client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# send some data
➋ client.sendto("AAABBBCCC",(target_host,target_port))

# receive some data
➌ data, addr = client.recvfrom(4096)

print data

Görebileceğiniz üzere soket türünü SOCK_DGRAM olarak değiştiriyoruz. ➊

sendto() ile veriyi göndermek sunucuya veriyi yolluyoruz. ➋

UDP bağlantısız protokol (connectionless) olduğundan, önceden connect () çağrısı yoktur. UDP karşıda bir cihaz olup olmaması ile ilgilenmez. Verinin cihaz tarafından alınacağı garanti değildir.

Son adım, recvfrom () fonksiyonu ile UDP datasını çağırmak. ➌

Dikkat edersek bu sefer hem datayı, hem de uzaktaki host ve portun bilgilerini döndürüyor.

Burada amacımız detaylı bir client tasarlamaktan ziyade günlük alıştırmaları yürütebilecek kadar hızlı, kolay ve güvenilir bir client’lar elde etmek. Şimdi server’lar ile devam edelim.

TCP Server

Python ile TCP Server oluşturmak da Client oluşturmak kadar kolaydır. Command shell yazarken veya proxy oluştururken kendi TCP serverımızı kullanmak isteyebiliriz. Standart multi-threaded bir TCP server ile başlayalım.

import socket
import threading

bind_ip = "0.0.0.0"
bind_port = 9999

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

➊ server.bind((bind_ip, bind_port))

➋ server.listen(5)

print "[*] Listening on %s:%d" % (bind_ip, bind_port)

➌ def handle_client(client_socket):
    
    # send something
    client_socket.send("Connected\r\n")
    
    # print out what the client sends
    request = client_socket.recv(1024)
    
    print "[*] Reveived: %s" % request
    
    # send back a packet
    client_socket.send("ACK!\r\n")
    
    client_socket.close()
    
while True:
    ➍ client, addr = server.accept()
    
    print "[*] Accepted connection from: %s:%d" % (addr[0], addr[1])
    
    # spin up our client thread to handle incoming data
    client_handler = threading.Thread(target=handle_client,args=(client,))
    ➎ client_handler.start()

Başlamak için önce sunucunun IP adresini ve dinlemek istediğimiz portunu belirtiyoruz. ➊

Daha sonra sunucuya dinlemeyi başlatmasını söylüyoruz. Parametresi (backlog – sıradaki maximum bağlantı sayısı) olarak 5 veriyoruz. ➋

Ardından alt kısma gelecek olursak (while True:) sunucuyu main döngüsü içerisine koyuyoruz. Bu döngü içerisinde gelecek bağlantıyı bekleyecek.

Bir istemci bağlantıyı gerçekleştirdiğinde, client soketini alıp client değişkenine aktarıyor ve yine uzak bağlantı detaylarını da addr değişkenine aktarıyoruz. ➍

Ardından handle_client fonksiyonumuzu işaret eden yeni bir thread nesnesi oluşturuyoruz ve client soket nesnesi’ni argüman olarak gönderiyoruz.

Sunucuya gelen Client bağlantısını işlemek için thread’i başlatıyoruz. ➎ Artık main server döngüsü gelecek olan başka bir bağlantıyla başa çıkmaya hazır.

handle_client fonksiyonu recv()‘i çağırarak istemcinin gönderdiği mesajı alıp. Ardından client’a basit bir mesaj gönderiliyor.

Daha önce yapmış olduğumuz TCP istemcisini kullanırsanız, sunucuya bazı test paketleri gönderebilirsiniz.

Aşağıdakine benzer bir çıktı görmelisiniz:

[*] Listening on 127.0.0.1:5000
[*] Accepted connection from: 127.0.0.1:41824
[*] Received: deneme

Bu yazıda oldukça basit, kullanışlı bir kod parçalarını ile TCP ve UDP kullanarak haberleşmeyi gördük. Umarım faydalı olmuştur. Bir sonraki yazıda görüşmek dileğiyle.

Kaynak:

Black Hat Python: Python Programming for Hackers and Pentesters

Etiketler:

“Python ile Networking | TCP ve UDP” hakkında 1 yorum

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir