8. Python pro sítě

Letní škola sítí

Programování vlastních síťových nástrojů od úplných základů

Nebojte se Pythonu!

Dnes nepotřebujete být programátoři.

Ukážeme si, jak z Pythonu udělat náš síťový švýcarský nůž.

Co si dnes vyzkoušíme?

  1. Základní příkazy v Pythonu pro síťaře
  2. Co je to socket a jak spojit dva počítače
  3. Jak napsat vlastní Port Scanner
  4. Jak zjistit verze služeb (Banner Grabber)
  5. Jak vytvářet a odchytávat pakety v Scapy

Kategorie 1

Rychlé minimum z Pythonu pro síťaře

Proměnné: Uložení údajů

Proměnná je krabička s názvem, do které si uložíme IP nebo port:

ip_adresa = "192.168.1.1"
port = 80

print(ip_adresa)
print(port)

Text vs. Bajty (Strings vs Bytes)

Po síti nelze posílat obyčejný text, musíme ho převést na bajty!

Předpona b: Přidáme b před uvozovky:

text_bajty = b"Ahoj svete"

Převod textu: "Ahoj".encode()

Podmínka: Rozhodování v kódu

Kontrola, zda je port otevřený nebo zavřený:

stav = "otevreno"

if stav == "otevreno":
    print("Port je dostupný!")
else:
    print("Port je zavřený.")

Cyklus: Opakování činnosti

Když chceme zkontrolovat více portů za sebou:

porty = [22, 80, 443]

for p in porty:
    print("Testuji port:", p)

Kategorie 2

Co je to Socket a jak funguje spojení

Co je to Socket?

Socket je jako telefonní přístroj ve vašem počítači.

  • Zadáte IP adresu (telefonní číslo).
  • Zadáte port (klapku v budově).
  • Zvednete sluchátko a můžete si povídat!

Importujeme knihovnu socket

V Pythonu už je nástroj na sockety vestavěný:

import socket

# Nyní máme přístup k síťovým funkcím!

Krok 1: Vytvoření socketu

Řekneme počítači, že chceme standardní síťové spojení (IPv4 + TCP):

import socket

# Vytvoříme spojovací socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

AF_INET = IPv4 adresa | SOCK_STREAM = TCP protokol

Krok 2: Připojení k cíli

Zavoláme funkci connect() s dvojicí (IP, Port):

# Připojíme se na webový server na portu 80
s.connect(("example.com", 80))

print("Úspěšně připojeno!")

Krok 3: Odeslání zprávy

Pošleme jednoduchý HTTP požadavek (v bajtech!):

zprava = b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"

s.sendall(zprava)

Krok 4: Přijetí odpoví a zavření

Přečteme odpovídající data ze sítě a zavřeme spojení:

# Přečteme maximálně 1024 bajtů
odpoved = s.recv(1024)

print(odpoved.decode())

# Na závěr socket VŽDY zavřeme
s.close()

Shrnutí TCP Klienta

Všechno dohromady v 6 řádcích kódu:

import socket

s = socket.socket()
s.connect(("example.com", 80))
s.sendall(b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")
print(s.recv(1024).decode())
s.close()

A co TCP Server?

Server nedvolá ven, ale **čeká na příchozí hovor**.

  1. bind() – Obsadí port na našem počítači.
  2. listen() – Zapne přijímač.
  3. accept() – Počká, až se někdo připojí.

Ukázka jednoduchého serveru

import socket

server = socket.socket()
server.bind(("0.0.0.0", 9999)) # Port 9999
server.listen(1)
print("Server čeká na připojení...")

klient, adresa = server.accept()
print("Připojil se klient z:", adresa)

klient.sendall(b"Vitej na mem serveru!\n")
klient.close()
server.close()

Kategorie 3

Stavíme vlastní Port Scanner a Banner Grabber

Co dělá Port Scanner?

Zkouší postupně porty na cíl a zjišťuje, kde běží služby.

Funguje to tak, že zkusí navázat spojení.

Kouzelná funkce: connect_ex()

Běžný connect() spadne s chybou, pokud je port zavřený.

connect_ex() vrátí číslo 0, pokud je port OTEVŘENÝ.

Vrátí jiné číslo, pokud je port zavřený.

Test jednoho portu

import socket

s = socket.socket()
vysledek = s.connect_ex(("127.0.0.1", 80))

if vysledek == 0:
    print("Port 80 je OTEVŘENÝ!")
else:
    print("Port 80 je zavřený.")

s.close()

Pozor na zamrznutí! (Timeout)

Pokud počítač neodpovídá, skript by mohl čekat do nekonečna.

Nastavíme časový limit 1 sekundu:

s = socket.socket()
s.settimeout(1.0) # Čekat max 1 sekundu

Port Scanner pro více portů

Spojíme cyklus for a testování portů:

import socket

cil = "127.0.0.1"
porty = [21, 22, 80, 443, 8080]

for port in porty:
    s = socket.socket()
    s.settimeout(0.5)
    if s.connect_ex((cil, port)) == 0:
        print(f"[+] Port {port} je OTEVŘENÝ")
    s.close()

Nástroj 2: Banner Grabber

Chceme vědět, jaký program na otevřeném portu běží!

Služby jako SSH nebo FTP po připojení samy napíší svou verzi (tzv. Banner).

Kód pro Banner Grabber

import socket

s = socket.socket()
s.connect(("127.0.0.1", 22))

# Přečteme prvních 100 znaků od serveru
banner = s.recv(100)
print("Na portu 22 běží:", banner.decode())

s.close()

Kategorie 4

Hrajeme si s pakety v knihovně Scapy

Co je to Scapy?

Scapy je jako LEGO stavebnice pro síťové pakety.

  • Běžné sockety vám nedovolí měnit IP hlavičku.
  • Scapy vám dovolí vyrobit jakýkoliv paket ručně.

Skládání paketů v Scapy

Různé vrstvy spojujeme pomocí lomítka /:

from scapy.all import IP, ICMP

# Vytvoříme IP paket mířící na 8.8.8.8
ip_vrstva = IP(dst="8.8.8.8")

# Přidáme ICMP vrstvu (Ping)
paket = ip_vrstva / ICMP()

Jak paket odeslat a počkat na odpověď?

Použijeme funkci sr1() (Send & Receive 1):

from scapy.all import IP, ICMP, sr1

# Pošleme paket a počkáme na odpověď
odpoved = sr1(IP(dst="8.8.8.8")/ICMP(), timeout=2)

if odpoved:
    print("Cíl odpovídá! Doba života TTL:", odpoved.ttl)
else:
    print("Cíl neodpovídá.")

Jak najít sousedy v síti? (ARP Scanner)

Zeptejte se všech počítačů v síti: „Kdo má tuto IP?“

from scapy.all import ARP, Ether, srp

# ARP dotaz na celou lokální síť
dotaz = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst="192.168.1.0/24")

odpovedi, _ = srp(dotaz, timeout=2)

for odeslano, prijato in odpovedi:
    print(prijato.psrc, "->", prijato.hwsrc)

Odchytávání paketů (Sniffer)

Chcete vidět, co létá po síti? Použijeme sniff():

from scapy.all import sniff

def ukaz_paket(pkt):
    print("Odchycen paket:", pkt.summary())

# Odchytí 5 paketů
sniff(count=5, prn=ukaz_paket)

Kategorie 5

Práva v Linuxu, bezpečnost a cvičení

Důležité: Práva root (Sudo)

Proč musíme u Scapy psát sudo?

Operační systém chrání síťovou kartu. Nízkoúrovňový přístup k paketům smí dělat jen správce (root).

sudo python3 muj_skript.py

Zlatá pravidla síťového vývoje

1. Pouze vlastní síť: Skenujeme a testujeme jen na localhost (127.0.0.1) nebo ve vlastní síti.

2. Žádné cizí cíle: Skenování cizích serverů bez povolení je nelegální!

Dnešní praktický úkol

  1. Otevřete si textový editor a vytvořte soubor scanner.py.
  2. Napište skript, který zkontroluje porty 22 a 80 na adrese 127.0.0.1.
  3. Pokud je port otevřený, vytiskněte zeleně nebo přehledně text do terminálu.
  4. Výzva pro rychlíky: Zkuste u portu 22 stáhnout jeho Banner!

Co si z dneška odnést

  • socket slouží ke spojení dvou počítačů přes IP a Port.
  • connect_ex() == 0 znamená otevřený port.
  • Scapy staví pakety jako LEGO s operátorem /.
  • Python je nejlepší přítel síťového administrátora!