Работа с сетевыми соединениями в Python

Цели и задачи

Цель данного занятия — ознакомить студентов с основами работы с сетевыми соединениями в Python, а также научить их анализировать сетевой трафик с помощью Wireshark. В рамках занятия студенты изучат:

Подготовительный этап

Работу следует выполнять в среде Visual Studio Code, используя установленное расширение для Python. Перед началом необходимо:

  1. Создать и активировать виртуальное окружение с помощью venv или conda.
  2. Установить библиотеку requests для работы с HTTP-запросами.
  3. Инициализировать Git-репозиторий, добавить .gitignore и README.md.
  4. Закоммитить изменения. Не выполнять push.

Создание простых программ для клиент-серверного взаимодействия и анализ сетевого трафика в Wireshark

Необходимо реализовать две программы: сервер и клиент. Они должны обмениваться данными по протоколам TCP и UDP. В первом случае клиент отправляет строку, а сервер её модифицирует и возвращает обратно.

Пример TCP-сервера:

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("0.0.0.0", 10000))
server.listen(1)
print("TCP сервер запущен")

while True:

    conn, addr = server.accept()
    print(f"Подключение от {addr}")

    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data.upper())

    conn.close()

    if data.upper() == b'EXIT':
        break

Пример TCP-клиента:

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 10000))
client.sendall(b'hello server')
data = client.recv(1024)
print(f"Ответ от сервера: {data.decode()}")
client.close()

Wireshark — это инструмент для анализа сетевого трафика, который позволяет просматривать отправленные и полученные пакеты. Важным аспектом работы с TCP является трёхстороннее рукопожатие (three-way handshake):

Задание:

  1. Запустите Wireshark и начните захват трафика. Вам очень поможет фитльр tcp.port==10000 || udp.port==10001.
  2. Запустите сервер и клиент, зафиксируйте обмен пакетами.
  3. Остановите захват и найдите последовательность SYN, SYN-ACK, ACK.
  4. Обратите внимание на Sequence Number, Sequence Number (raw), Acknowledgment Number, Acknowledgment Number (raw), Flags. Эти параметры определяют порядок передачи данных и подтверждения приёма.
  5. Зафиксируйте последовательность завершения соединения (FIN), которая включает обмен FIN- и ACK-пакетами.
  6. Измените TCP-клиент так, чтобы TCP-сервер завершил работу.

Пример UDP-сервера:

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(('0.0.0.0', 10001))
print("UDP сервер запущен")

while True:
    data, addr = server.recvfrom(1024)
    print(f"Сообщение от {addr}: {data.decode()}")
    server.sendto(data.upper(), addr)

Пример UDP-клиента:

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client.sendto(b'hello server', ('127.0.0.1', 10001))
data, _ = client.recvfrom(1024)
print(f"Ответ от сервера: {data.decode()}")
client.close()

Задание:

  1. Запустите Wireshark и начните захват трафика.
  2. Запустите сервер и клиент, зафиксируйте обмен пакетами.
  3. Проанализируйте разницу в передаче данных между TCP и UDP, сравнив структуру пакетов в Wireshark.
  4. Модифицируйте серверную программу, чтобы изменять входящие данные перед отправкой клиенту. Измените порты для сервера и клиента.

Подключение к веб-серверу и работа с HTTP-запросами

Создайте TCP-клиент, который устанавливает соединение с vyatsu.ru по порту 80 и отправляет HTTP-запрос:

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('vyatsu.ru', 80))
request = "GET / HTTP/1.1\r\nHost: vyatsu.ru\r\n\r\n"
client.sendall(request.encode())
response = client.recv(4096)
print(response.decode())
client.close()

Задание:

  1. Запустите Wireshark, выполните запрос и проанализируйте трафик (фильтр tcp.port==80 оставит интересующие нас пакеты видимыми). Определите используемые протоколы. Поясните ответ от сервера.
  2. Повторите запрос с использованием requests:
import requests

response = requests.get("http://vyatsu.ru")
print(response.text[:500])
  1. Сравните полученные данные с анализом Wireshark и измените код первого примера так, чтобы он выглядел как захваченный трафик при использовании requests.

Работа с API Gitea

Задание:

  1. Сгенерируйте API-токен в Gitea (https://git.vyatsu.ru/user/settings/applications) с правами только на чтение.
  2. Важно! Токен не должен попадать в коммиты. Добавьте его в .gitignore и используйте переменные окружения.
  3. Выполните запрос к API Gitea:
import requests

TOKEN = "ВАШ_ТОКЕН"
headers = {"Authorization": f"token {TOKEN}"}
response = requests.get("https://git.vyatsu.ru/api/v1/user", headers=headers)
print(response.json())
  1. Выпустите новый токен с правами на запись и, например, создайте репозиторий, issue или комментарий. У каждого студента должно быть свой вариант.
  2. Закоммитьте весь написанный код и выполните git push из среды Visual Studio Code.

Критерии успешного выполнения