Инструкция по настройке интернет-соединения через VPN с использованием удаленного сервера

Для создания интернет-соединения через VPN потребуется:

  1. Удаленный сервер с установленным VPN-сервером. Это может быть VPS, предоставляемый популярными хостинг-провайдерами (например, DigitalOcean, AWS, Hetzner и т. д.).
  2. VPN-клиент на вашем устройстве для подключения к серверу.
  3. Доступ к серверу через SSH для настройки VPN.

Шаг 1: Настройка VPN-сервера

  1. Подготовьте удаленный сервер:
    • Установите операционную систему (рекомендуется Ubuntu 20.04 или новее).
    • Обеспечьте доступ к серверу через SSH.
  2. Установите VPN-сервер: Для простоты настройки можно использовать WireGuard или OpenVPN.
    • WireGuard:
      1. Установите WireGuard: sudo apt update sudo apt install wireguard
      2. Настройте конфигурацию сервера:
        • Создайте ключи: umask 077 wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey
        • Настройте файл конфигурации /etc/wireguard/wg0.conf: [Interface] PrivateKey = <содержимое /etc/wireguard/privatekey> Address = 10.0.0.1/24 ListenPort = 51820 [Peer] PublicKey = <публичный ключ клиента> AllowedIPs = 10.0.0.2/32
        • Разрешите пересылку пакетов: echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf sudo sysctl -p
        • Запустите WireGuard: sudo systemctl start wg-quick@wg0 sudo systemctl enable wg-quick@wg0
    • OpenVPN:
      1. Установите OpenVPN: sudo apt update sudo apt install openvpn
      2. Используйте скрипт автоматической настройки, например Nyr’s OpenVPN install script: wget https://git.io/vpn -O openvpn-install.sh chmod +x openvpn-install.sh sudo ./openvpn-install.sh
      3. Следуйте инструкциям скрипта для настройки и получения клиентского конфигурационного файла.

Шаг 2: Настройка клиента

  1. На устройстве клиента установите соответствующий VPN-клиент:
    • Для WireGuard:
      • Установите клиент WireGuard (WireGuard клиент).
      • Импортируйте конфигурацию клиента.
    • Для OpenVPN:
      • Установите OpenVPN клиент (OpenVPN клиент).
      • Импортируйте файл конфигурации .ovpn, предоставленный сервером.
  2. Подключитесь к VPN:
    • В клиенте выберите импортированную конфигурацию и нажмите Connect.

Шаг 3: Проверка соединения

  1. Откройте веб-браузер и проверьте свой IP-адрес на сайте, таком как WhatIsMyIP. IP должен совпадать с IP вашего VPN-сервера.
  2. Убедитесь, что интернет работает через VPN.

Шаг 4: Дополнительные настройки (по желанию)

  1. Автозапуск VPN:
    • Для WireGuard: sudo systemctl enable wg-quick@wg0
    • Для OpenVPN: sudo systemctl enable openvpn-client@<имя конфигурационного файла>
  2. Шифрование DNS-трафика: Используйте публичные DNS-серверы, такие как Cloudflare (1.1.1.1) или Google (8.8.8.8), для повышения конфиденциальности.

Теперь ваше устройство подключено к интернету через удаленный сервер по VPN.

Добавление клиента для скрипта OpenVPN openvpn-install.sh (от Nyr)

Перейди в директорию, где находится скрипт:

cd ~

Запусти скрипт повторно:

sudo ./openvpn-install.sh

Скрипт предложит меню. Выбери пункт:

Select an option:
   1) Add a new user
   2) Revoke an existing user
   3) Remove OpenVPN
   4) Exit

Выбери 1) Add a new user.

Введи имя нового клиента (например, client2).

Скрипт автоматически сгенерирует конфигурационный файл:
/root/client2.ovpn (или аналогично, в зависимости от имени).

Скопируй .ovpn файл на клиентскую машину:

scp root@your_server_ip:/root/client2.ovpn ./client2.ovpn

Инструкция для настройки работы с GitHub по SSH

Шаг 1: Проверка наличия SSH-ключей

Сначала нужно проверить, есть ли уже сгенерированные SSH-ключи на вашем компьютере. Откройте терминал и выполните команду:

ls -al ~/.ssh

Шаг 2: Создание нового SSH-ключа (если необходимо)

Если SSH-ключи отсутствуют, их нужно создать. Выполните команду:

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

Замените «your_email@example.com» на свой адрес электронной почты, использованный для регистрации на GitHub. Нажмите Enter для подтверждения всех последующих вопросов, оставив путь по умолчанию.

Шаг 3: Запуск агента SSH и добавление ключа

Запустите агента SSH:

eval "$(ssh-agent -s)"

Добавьте SSH-ключ в агент:

ssh-add ~/.ssh/id_rsa

Шаг 4: Добавление SSH-ключа в GitHub

Скопируйте содержимое SSH-ключа в буфер обмена:

cat ~/.ssh/id_rsa.pub

Зайдите на страницу SSH и GPG-ключей на GitHub и нажмите «New SSH key». Вставьте скопированный ключ и нажмите «Add SSH key».

Шаг 5: Проверка соединения

Теперь можно проверить соединение с GitHub:

ssh -T git@github.com

Если все сделано правильно, вы увидите сообщение приветствия.

Установка MongoDB на Ubuntu. Подключение к MongoDB и создание базы данных с помощью Python.

1. Установка MongoDB на Ubuntu

MongoDB доступен в официальном репозитории Ubuntu, но рекомендуется установить его из официального репозитория MongoDB для получения последней версии.

Шаги по установке:

  1. Импорт ключа GPG:
    Это гарантирует, что пакеты из репозитория будут подлинными.
   wget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | sudo apt-key add -
  1. Добавьте репозиторий MongoDB:
    Создайте файл списка репозиториев для MongoDB.
   echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu $(lsb_release -cs)/mongodb-org/6.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list
  1. Обновите список пакетов:
   sudo apt update
  1. Установите MongoDB:
   sudo apt install -y mongodb-org
  1. Запустите MongoDB:
    После установки MongoDB можно запустить с помощью команды:
   sudo systemctl start mongod
  1. Проверьте статус MongoDB:
    Убедитесь, что MongoDB запущен:
   sudo systemctl status mongod
  1. Настройка автозапуска MongoDB при перезагрузке:
   sudo systemctl enable mongod

2. Подключение к MongoDB и создание базы данных с помощью Python

Для работы с MongoDB в Python используется библиотека pymongo.

Шаги по подключению и созданию базы данных:

  1. Установите библиотеку pymongo:
    Убедитесь, что у вас установлен Python и pip, затем установите библиотеку:
   pip install pymongo
  1. Подключение к MongoDB: Напишите Python-скрипт для подключения к MongoDB и создания базы данных.
   from pymongo import MongoClient

   # Подключение к локальному серверу MongoDB
   client = MongoClient("mongodb://localhost:27017/")

   # Создание базы данных
   db = client["mydatabase"]

   # Создание коллекции (эквивалент таблицы в реляционных базах данных)
   collection = db["mycollection"]

   # Добавление документа (эквивалент записи в реляционных базах данных)
   data = {"name": "Alice", "age": 25, "city": "New York"}
   collection.insert_one(data)

   print("База данных и коллекция созданы, документ добавлен!")

Этот код создаст базу данных с именем mydatabase, коллекцию с именем mycollection и вставит один документ.

3. Проверка результатов

Чтобы проверить, что база данных и коллекция были созданы, можно использовать командную строку MongoDB:

mongo

В интерактивной оболочке MongoDB введите:

show dbs;  // Показать все базы данных
use mydatabase;  // Переключиться на вашу базу данных
show collections;  // Показать коллекции в базе данных
db.mycollection.find();  // Показать документы в коллекции

Шпаргалка по mitmproxy

Библиотека mitmproxy — это мощный инструмент для перехвата и анализа HTTP/HTTPS трафика. Она предоставляет несколько интерфейсов: консольный (mitmproxy), командный (mitmdump) и веб-интерфейс (mitmweb). Вот основные шаги для начала работы с mitmproxy в Python:

Установка

Для установки mitmproxy используйте pip:

pip install mitmproxy

Основные функции

Запуск mitmproxy:

mitmproxy

Это запустит консольный интерфейс, где вы сможете видеть и управлять перехваченным трафиком.

Запуск mitmdump:

mitmdump -w outputfile

Этот режим позволяет сохранять трафик в файл для последующего анализа.

Запуск mitmweb:

mitmweb

Это запустит веб-интерфейс, доступный по умолчанию на порту 8081.

Пример использования в Python

Вы можете создавать собственные аддоны для автоматизации задач. Вот пример простого аддона, который добавляет заголовок к каждому HTTP-ответу:

from mitmproxy import http

def response(flow: http.HTTPFlow) -> None:
    flow.response.headers["X-Custom-Header"] = "MyValue"

Для запуска этого аддона используйте команду:

mitmdump -s path/to/your_addon.py

>>> Примеры аддонов.

Шпаргалка по основам работы сетей и протоколов

Основные принципы работы сетей и протоколов включают несколько ключевых аспектов, которые обеспечивают эффективное и надежное взаимодействие между устройствами в сети. Вот основные моменты:

1. Модель OSI и TCP/IP

2. Протоколы и их функции

3. Маршрутизация и управление трафиком

4. Безопасность сети

5. Примеры сетевых протоколов

Эти принципы и протоколы обеспечивают эффективное и безопасное взаимодействие устройств в сети, позволяя передавать данные, управлять трафиком и защищать информацию.

Установка PostgreSQL, создание пользователя и базы данных

Откройте терминал и выполните следующие команды:

  1. Обновите список пакетов:
   sudo apt update
  1. Установите PostgreSQL:
   sudo apt install postgresql postgresql-contrib
  1. Проверьте статус сервиса PostgreSQL:
   sudo systemctl status postgresql

Если сервис работает, вы увидите сообщение о том, что PostgreSQL активен.

2. Настройка PostgreSQL

PostgreSQL по умолчанию создает пользователя с именем postgres. Для взаимодействия с базой данных от имени этого пользователя выполните:

  1. Войдите под пользователем postgres:
   sudo -i -u postgres
  1. Откройте PostgreSQL shell:
   psql

Теперь вы находитесь в консоли PostgreSQL.

3. Создание базы данных

  1. Создайте новую базу данных:
   CREATE DATABASE имя_базы;
  1. Создайте нового пользователя и установите пароль:
   CREATE USER имя_пользователя WITH PASSWORD 'пароль';
  1. Предоставьте пользователю права на базу данных:
   GRANT ALL PRIVILEGES ON DATABASE имя_базы TO имя_пользователя;
  1. Выйдите из PostgreSQL shell:
   \q

4. Подключение к базе данных

Теперь вы можете подключиться к базе данных как пользователь, которого вы создали:

  1. Отключитесь от пользователя postgres:
   exit
  1. Подключитесь к базе данных:
   psql -U имя_пользователя -d имя_базы

Теперь вы подключены к вашей базе данных и можете начинать с ней работать.

Дополнительно

  • Чтобы проверить список баз данных:
  \l
  • Для выхода из psql:
  \q

Теперь PostgreSQL установлен, база данных создана, и вы можете взаимодействовать с ней.

Основные команды

Список основных команд для работы с базой данных в psql:

1. Подключение и выход

  • Подключение к базе данных:
  psql -U имя_пользователя -d имя_базы
  • Выход из psql:
  \q

2. Работа с базами данных

  • Создание базы данных:
  CREATE DATABASE имя_базы;
  • Удаление базы данных:
  DROP DATABASE имя_базы;
  • Просмотр списка баз данных:
  \l

3. Работа с пользователями

  • Создание пользователя:
  CREATE USER имя_пользователя WITH PASSWORD 'пароль';
  • Удаление пользователя:
  DROP USER имя_пользователя;
  • Изменение пароля пользователя:
  ALTER USER имя_пользователя WITH PASSWORD 'новый_пароль';
  • Предоставление прав на базу данных:
  GRANT ALL PRIVILEGES ON DATABASE имя_базы TO имя_пользователя;

4. Работа с таблицами

  • Создание таблицы:
  CREATE TABLE имя_таблицы (
    id SERIAL PRIMARY KEY,
    имя_поля тип_данных,
    ...
  );
  • Просмотр структуры таблицы:
  \d имя_таблицы
  • Просмотр всех таблиц в базе данных:
  \dt
  • Удаление таблицы:
  DROP TABLE имя_таблицы;

5. Вставка данных

  • Вставка данных в таблицу:
  INSERT INTO имя_таблицы (имя_поля1, имя_поля2, ...) VALUES (значение1, значение2, ...);

6. Чтение данных

  • Выбор всех данных из таблицы:
  SELECT * FROM имя_таблицы;
  • Выбор данных с условием:
  SELECT * FROM имя_таблицы WHERE имя_поля = 'значение';

7. Обновление данных

  • Обновление данных в таблице:
  UPDATE имя_таблицы SET имя_поля = 'новое_значение' WHERE имя_поля = 'значение';

8. Удаление данных

  • Удаление строки из таблицы:
  DELETE FROM имя_таблицы WHERE имя_поля = 'значение';

9. Управление транзакциями

  • Начало транзакции:
  BEGIN;
  • Завершение транзакции (подтверждение изменений):
  COMMIT;
  • Откат транзакции (отмена изменений):
  ROLLBACK;

10. Дополнительные команды

  • Просмотр версии PostgreSQL:
  SELECT version();
  • Смена базы данных:
  \c имя_базы

Транзакции

Транзакции в PostgreSQL (и в других СУБД) — это логическая единица работы, которая состоит из одного или нескольких SQL-запросов, выполняемых последовательно. Транзакция гарантирует, что все изменения в базе данных, которые происходят в рамках этой транзакции, будут выполнены полностью или не будут выполнены вовсе. Это помогает обеспечить целостность данных.

Основные свойства транзакций

Транзакции обладают четырьмя важными свойствами, известными как ACID:

  1. Atomicity (Атомарность): Транзакция выполняется как единое целое. Либо все операции внутри транзакции завершаются успешно, либо ни одна не завершается.
  2. Consistency (Согласованность): Транзакция переводит базу данных из одного согласованного состояния в другое. В случае неудачи база данных должна вернуться к исходному состоянию.
  3. Isolation (Изолированность): Каждая транзакция изолирована от других. Текущие изменения транзакции не видны другим транзакциям до тех пор, пока транзакция не завершится (не произойдет фиксация).
  4. Durability (Долговечность): После завершения транзакции (фиксации) ее изменения сохраняются и не теряются даже в случае сбоя системы.

Как работают транзакции в PostgreSQL

В PostgreSQL транзакции начинаются с команды BEGIN и завершаются с помощью команд COMMIT или ROLLBACK.

  1. BEGIN: Начало транзакции. Все SQL-операции, которые будут выполнены после этой команды, будут частью транзакции.
   BEGIN;
  1. COMMIT: Завершает транзакцию и подтверждает все изменения, сделанные в базе данных. После этого изменения становятся видимыми для всех пользователей и других транзакций.
   COMMIT;
  1. ROLLBACK: Откатывает все изменения, сделанные в рамках транзакции, возвращая базу данных к состоянию, которое было до начала транзакции.
   ROLLBACK;

Пример использования транзакции:

Предположим, у нас есть таблица accounts, и мы хотим перевести средства с одного счета на другой:

BEGIN;

UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;

COMMIT;

В этом примере два обновления (дебет одного счета и кредит другого) объединены в одну транзакцию. Если одно из обновлений не удастся (например, баланс станет отрицательным), можно отменить всю транзакцию с помощью ROLLBACK.

Зачем нужны транзакции

  1. Целостность данных: Если в процессе выполнения произошла ошибка, можно откатить все изменения и вернуть базу данных к исходному состоянию.
  2. Изолированность операций: Пока транзакция не завершена, её изменения не видны другим пользователям, что предотвращает возможные конфликты.
  3. Логическая группировка операций: Позволяет сгруппировать несколько операций, чтобы они были выполнены как единое целое.

Транзакции — это важный механизм для обеспечения надежности и согласованности данных в базе данных.

Шпаргалка по SQL

Основные команды SQL, чтобы вспомнить базу.

Создание базы данных и таблиц

CREATE DATABASE database_name;
CREATE TABLE table_name (
    column1 datatype,
    column2 datatype,
    ...
);

Вставка данных

INSERT INTO table_name (column1, column2, ...)
VALUES (value1, value2, ...);

Обновление данных

UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;

Удаление данных

DELETE FROM table_name
WHERE condition;

Запросы данных

Выбор данных

SELECT column1, column2, ...
FROM table_name
WHERE condition;

Сортировка данных

SELECT column1, column2, ...
FROM table_name
ORDER BY column1 [ASC|DESC];

Группировка данных

SELECT column1, COUNT(*)
FROM table_name
GROUP BY column1;

Соединения (Joins)

Внутреннее соединение (INNER JOIN)

SELECT columns
FROM table1
INNER JOIN table2
ON table1.common_column = table2.common_column;

Левое соединение (LEFT JOIN)

SELECT columns
FROM table1
LEFT JOIN table2
ON table1.common_column = table2.common_column;

Правое соединение (RIGHT JOIN)

SELECT columns
FROM table1
RIGHT JOIN table2
ON table1.common_column = table2.common_column;

Типы данных

Числовые типы

  • INT — целое число
  • FLOAT — число с плавающей точкой
  • DECIMAL — число с фиксированной точкой

Текстовые типы

  • CHAR — строка фиксированной длины
  • VARCHAR — строка переменной длины
  • TEXT — длинный текст

Типы даты и времени

  • DATE — дата (YYYY-MM-DD)
  • DATETIME — дата и время (YYYY-MM-DD HH:MM:SS)
  • TIMESTAMP — временная метка

Основные типы связей

В реляционных базах данных связи между таблицами играют ключевую роль в организации и управлении данными. Вот основные типы связей:

1. Один-к-одному (One-to-One)

Каждая запись в одной таблице соответствует одной записи в другой таблице.

  • Пример: Таблица Пользователи и таблица Профили, где каждый пользователь имеет один профиль.
CREATE TABLE Users (
    user_id INT PRIMARY KEY,
    username VARCHAR(50)
);

CREATE TABLE Profiles (
    profile_id INT PRIMARY KEY,
    user_id INT,
    bio TEXT,
    FOREIGN KEY (user_id) REFERENCES Users(user_id)
);


2. Один-ко-многим (One-to-Many)

Одна запись в одной таблице может соответствовать нескольким записям в другой таблице.

  • Пример: Таблица Категории и таблица Продукты, где каждая категория может содержать несколько продуктов.
CREATE TABLE Categories (
    category_id INT PRIMARY KEY,
    category_name VARCHAR(50)
);

CREATE TABLE Products (
    product_id INT PRIMARY KEY,
    product_name VARCHAR(50),
    category_id INT,
    FOREIGN KEY (category_id) REFERENCES Categories(category_id)
);


3. Многие-ко-многим (Many-to-Many)

Каждая запись в одной таблице может соответствовать нескольким записям в другой таблице и наоборот. Для реализации такой связи обычно используется промежуточная таблица.

  • Пример: Таблица Студенты и таблица Курсы, где каждый студент может записаться на несколько курсов, а каждый курс может включать нескольких студентов.
CREATE TABLE Students (
    student_id INT PRIMARY KEY,
    student_name VARCHAR(50)
);

CREATE TABLE Courses (
    course_id INT PRIMARY KEY,
    course_name VARCHAR(50)
);

CREATE TABLE Enrollments (
    student_id INT,
    course_id INT,
    PRIMARY KEY (student_id, course_id),
    FOREIGN KEY (student_id) REFERENCES Students(student_id),
    FOREIGN KEY (course_id) REFERENCES Courses(course_id)
);


4. Самоссылающиеся связи (Self-Referencing)

Таблица может ссылаться сама на себя, что полезно для представления иерархий.

  • Пример: Таблица Сотрудники, где каждый сотрудник может иметь менеджера, который также является сотрудником.
CREATE TABLE Employees (
    employee_id INT PRIMARY KEY,
    employee_name VARCHAR(50),
    manager_id INT,
    FOREIGN KEY (manager_id) REFERENCES Employees(employee_id)
);


Ключи и индексы

Первичный ключ (Primary Key)

Первичный ключ — это уникальный идентификатор каждой записи в таблице. Он гарантирует, что каждая строка в таблице уникальна и может быть однозначно идентифицирована. Основные функции первичного ключа:

  1. Уникальность: Обеспечивает уникальность каждой записи в таблице.
  2. Идентификация: Позволяет однозначно идентифицировать каждую запись.
  3. Целостность данных: Предотвращает дублирование записей.
  4. Связи: Используется для создания связей между таблицами через внешние ключи.

Пример создания первичного ключа:

CREATE TABLE Users (
    user_id INT PRIMARY KEY,
    username VARCHAR(50)
);

Внешний ключ (Foreign Key)

Внешний ключ — это поле или набор полей в одной таблице, которое ссылается на первичный ключ другой таблицы. Основные функции внешнего ключа:

  1. Связи между таблицами: Обеспечивает связь между таблицами, поддерживая целостность данных.
  2. Целостность ссылок: Гарантирует, что значения внешнего ключа соответствуют значениям первичного ключа в связанной таблице.
  3. Каскадные операции: Позволяет выполнять каскадные обновления и удаления.

Пример создания внешнего ключа:

CREATE TABLE Orders (
    order_id INT PRIMARY KEY,
    user_id INT,
    order_date DATE,
    FOREIGN KEY (user_id) REFERENCES Users(user_id)
);

Уникальный ключ (Unique Key)

Уникальный ключ — это ограничение, которое обеспечивает уникальность значений в одном или нескольких столбцах таблицы. В отличие от первичного ключа, уникальный ключ может принимать значение NULL.

Пример создания уникального ключа:

CREATE TABLE Products (
    product_id INT PRIMARY KEY,
    product_name VARCHAR(50) UNIQUE
);

Индексы (Indexes)

Индексы — это структуры данных, которые улучшают скорость выполнения запросов к базе данных. Индексы создаются на одном или нескольких столбцах таблицы и позволяют быстро находить записи.

Пример создания индекса:

CREATE INDEX idx_product_name
ON Products (product_name);

Эти ключи и индексы помогают поддерживать целостность данных, оптимизировать запросы и обеспечивать эффективное управление базой данных.

Kafka. Быстрый старт.

Apache Kafka — распределённый программный брокер сообщений с открытым исходным кодом, разрабатываемый в рамках фонда Apache на языках Java и Scala. Цель проекта — создание горизонтально масштабируемой платформы для обработки потоковых данных в реальном времени с высокой пропускной способностью и низкой задержкой.

Тип: Распределённая платформа потоковой передачи событий (Distributed Event Streaming Platform).

Архитектура: Использует архитектуру топиков (topics), где сообщения сохраняются в логах для длительного хранения, и потребители могут читать данные в своём темпе. Kafka ориентирован на высокопроизводительные, распределённые системы.

Использование: Подходит для работы с большими объемами данных и обработки событий в реальном времени (например, логирование, аналитика, события IoT). Используется для долгосрочного хранения данных и их обработки.

Плюсы:

  • Поддержка горизонтального масштабирования.
  • Высокая производительность для обработки большого количества данных.
  • Долговременное хранение сообщений.
  • Консистентность данных и возможности реиграции событий.

Минусы:

  • Сложность конфигурации и управления.
  • Не подходит для краткосрочных или транзакционных сообщений.

Далее будет рассмотрен пример использования системы для организации общения между микросервисами через Kafka на Python.

Чтобы запустить Kafka и создать топик my_topic, следуйте инструкциям ниже. Мы будем использовать Apache Kafka и ZooKeeper (ZooKeeper — это сервер координации, который требуется для работы Kafka).

Шаги:

1. Скачать и установить Kafka

Скачать Kafka:

  • Перейдите на страницу загрузки Kafka и выберите нужную версию (например, Kafka 3.0).
  • Или воспользуйтесь командой для загрузки последней версии Kafka:
wget https://dlcdn.apache.org/kafka/3.0.0/kafka_2.13-3.0.0.tgz

Распаковать Kafka:

tar -xzf kafka_2.13-3.0.0.tgz
cd kafka_2.13-3.0.0

2. Запуск ZooKeeper и Kafka

Kafka использует ZooKeeper для координации, поэтому сначала нужно запустить ZooKeeper, а затем сам Kafka.

Запустить ZooKeeper:

Kafka поставляется с встроенным ZooKeeper. Запустите его с помощью следующей команды:

bin/zookeeper-server-start.sh config/zookeeper.properties

Это запустит ZooKeeper на порту 2181 (по умолчанию).

Запустить Kafka:

В другом терминале запустите Kafka-брокер:

bin/kafka-server-start.sh config/server.properties

Это запустит Kafka на порту 9092 (по умолчанию).

3. Создать топик my_topic

После запуска ZooKeeper и Kafka можно создать топик с именем my_topic. Используйте следующую команду для создания топика:

bin/kafka-topics.sh --create --topic my_topic --bootstrap-server localhost:9092 --partitions 1 --replication-factor 1

Здесь:

  • --bootstrap-server localhost:9092: Адрес брокера Kafka.
  • --partitions 1: Количество разделов для топика.
  • --replication-factor 1: Число реплик (можно установить в 1 для локального запуска).

Убедитесь, что топик создан:

bin/kafka-topics.sh --list --bootstrap-server localhost:9092

В списке должен появиться my_topic.

4. Тестирование

Запустить producer для отправки сообщений:

  • В другом терминале выполните команду, чтобы отправлять сообщения в my_topic:
bin/kafka-console-producer.sh --topic my_topic --bootstrap-server localhost:9092

Введите несколько сообщений вручную и нажмите Enter.

Запустить consumer для получения сообщений:

  • В другом терминале выполните команду для чтения сообщений:
bin/kafka-console-consumer.sh --topic my_topic --from-beginning --bootstrap-server localhost:9092

Вы увидите сообщения, отправленные продюсером.

5. Запуск Python-кода

Теперь, когда Kafka запущен и топик создан, можно использовать игрушечный пример кода на Python, который будет чуть ниже, чтобы продемонстрировать отправку и получение сообщений через Kafka.

6. Остановка Kafka и ZooKeeper

После тестирования можно остановить Kafka и ZooKeeper:

  • Остановите Kafka:
bin/kafka-server-stop.sh
  • Остановите ZooKeeper:
bin/zookeeper-server-stop.sh

Таким образом, вы настроите и запустите Kafka локально, создадите топик и сможете тестировать общение микросервисов через Python и Kafka.

Демонстрация общения микросервисов с помощью Kafka

Для организации общения между микросервисами через Kafka на Python, можно использовать библиотеку confluent-kafka, которая обеспечивает удобный интерфейс для взаимодействия с Apache Kafka.

Шаги:

  1. Установить Kafka и библиотеку confluent-kafka
pip install confluent-kafka

2. Настроить брокер Kafka (локально или в Docker), если он еще не запущен.

3. Написать два простых микросервиса: один будет производителем (producer), а другой — потребителем (consumer).

Пример кода:

1. Producer (отправка сообщений)

from confluent_kafka import Producer

# Конфигурация для подключения к Kafka
producer_config = {
    'bootstrap.servers': 'localhost:9092'  # Адрес брокера Kafka
}

# Создаем объект продюсера
producer = Producer(producer_config)

# Функция, вызываемая при подтверждении отправки
def delivery_report(err, msg):
    if err:
        print(f'Ошибка отправки сообщения: {err}')
    else:
        print(f'Сообщение отправлено в {msg.topic()} [{msg.partition()}]')

# Отправляем несколько сообщений
for i in range(10):
    message = f'Сообщение номер {i}'
    producer.produce('my_topic', message.encode('utf-8'), callback=delivery_report)

# Ожидаем завершения всех сообщений
producer.flush()

2. Consumer (получение сообщений)

from confluent_kafka import Consumer, KafkaError

# Конфигурация для подключения к Kafka
consumer_config = {
    'bootstrap.servers': 'localhost:9092',  # Адрес брокера Kafka
    'group.id': 'my_group',                # Группа потребителей
    'auto.offset.reset': 'earliest'         # Начинать чтение с самого начала, если нет сохраненного смещения
}

# Создаем объект консюмера
consumer = Consumer(consumer_config)

# Подписываемся на топик
consumer.subscribe(['my_topic'])

# Чтение сообщений
try:
    while True:
        msg = consumer.poll(timeout=1.0)  # Ожидаем получения сообщения
        if msg is None:
            continue
        if msg.error():
            if msg.error().code() == KafkaError._PARTITION_EOF:
                continue
            else:
                print(f'Ошибка: {msg.error()}')
                break

        print(f'Получено сообщение: {msg.value().decode("utf-8")}')

except KeyboardInterrupt:
    pass
finally:
    # Закрываем консюмер
    consumer.close()

Пояснение:

  1. Producer:
    • Отправляет сообщения в топик my_topic.
    • Использует метод produce для отправки сообщений с асинхронной обработкой.
    • После отправки всех сообщений, вызывается flush, чтобы дождаться завершения всех запросов.
  2. Consumer:
    • Подписывается на топик my_topic и прослушивает его.
    • Читает сообщения в бесконечном цикле, используя метод poll.
    • Сообщения выводятся на экран.

Запуск:

  1. Убедитесь, что Kafka запущен, и топик my_topic создан.
  2. Запустите producer для отправки сообщений.
  3. Запустите consumer для получения сообщений.

Таким образом, микросервисы могут общаться через Kafka, отправляя и получая сообщения в различных топиках.

Чем TCP отличается от UDP?

TCP и UDP — это два основных транспортных протокола в стекe интернет-протоколов. Оба служат для передачи данных между устройствами в сети, но они существенно различаются по своим характеристикам и назначению.

1. TCP (Transmission Control Protocol)

TCP — это ориентированный на соединение протокол, который гарантирует надёжную доставку данных.

Характеристики TCP:

  • Надёжность: TCP обеспечивает, чтобы данные были доставлены точно в том порядке, в котором они отправлены. Для этого используется механизм подтверждения (acknowledgment), таймауты и повторная отправка данных, если подтверждение не получено.
  • Установка соединения: TCP требует предварительной установки соединения между отправителем и получателем через так называемое трёхстороннее рукопожатие (three-way handshake). Только после этого начинается передача данных.
  • Контроль потока: TCP регулирует скорость передачи данных, чтобы не перегружать получателя (flow control).
  • Контроль перегрузки: TCP снижает скорость передачи, если обнаруживается перегрузка сети, чтобы предотвратить потерю пакетов (congestion control).
  • Гарантированная доставка: TCP проверяет целостность данных и гарантирует, что все пакеты будут доставлены, а в случае потери — автоматически пересылает их.
  • Ориентация на поток: Передача данных происходит в виде непрерывного потока байтов.

Примеры использования TCP:

  • Веб-серфинг (HTTP/HTTPS).
  • Передача файлов (FTP).
  • Электронная почта (SMTP).
  • Удалённый доступ (SSH).

Плюсы:

  • Надёжная доставка и контроль целостности.
  • Данные всегда приходят в правильном порядке.

Минусы:

  • Более медленный из-за необходимости подтверждений, установки соединения и контроля потока.
  • Большая задержка из-за дополнительных проверок и пересылок.

2. UDP (User Datagram Protocol)

UDP — это протокол без установления соединения, который фокусируется на быстрой передаче данных, жертвуя надёжностью.

Характеристики UDP:

  • Без установления соединения: UDP не требует предварительного установления соединения между устройствами. Пакеты отправляются сразу.
  • Отсутствие подтверждений: UDP не проверяет доставку пакетов. Пакеты могут потеряться, дублироваться или приходить в неправильном порядке.
  • Меньшая задержка: За счёт отсутствия подтверждений и установления соединений UDP обеспечивает минимальные задержки.
  • Нет контроля потока и перегрузки: UDP не регулирует поток данных и не адаптируется к сетевой перегрузке.
  • Ориентация на датаграммы: Данные передаются в виде независимых сообщений (датаграмм), каждое из которых может быть доставлено отдельно.

Примеры использования UDP:

  • Потоковое видео и аудио (VoIP, видеоконференции).
  • Онлайн-игры.
  • DNS-запросы.
  • Вещание данных (broadcast).

Плюсы:

  • Высокая скорость передачи.
  • Низкая задержка, что критично для времени отклика (например, в онлайн-играх или видеоконференциях).

Минусы:

  • Нет гарантии доставки данных.
  • Пакеты могут теряться или приходить не по порядку.
  • Нет встроенного механизма контроля перегрузки.

Ключевые отличия:

ХарактеристикаTCPUDP
Тип протоколаОриентированный на соединениеБез соединения
НадёжностьГарантирует доставкуНе гарантирует доставку
Порядок сообщенийПакеты приходят по порядкуПорядок не гарантирован
Скорость передачиМедленнее из-за подтвержденийБыстрее, без задержек
Контроль потокаЕстьНет
ИспользованиеПриложения, требующие надёжности (HTTP, FTP)Приложения, требующие скорости и низкой задержки (VoIP, DNS)

Таким образом, TCP выбирается, когда важна надёжность и целостность данных, а UDP — когда приоритетом являются скорость и низкие задержки.

Взламываем игры с помощью Python

В стародавние времена, когда по земле ходили мамонты, а я был в два раза моложе, среди игрового сообщества пользовалась популярностью компьютерная программа для «взлома» игр под названием ArtMoney. С помощью этой софтины можно было не только облегчить себе жизнь в прохождении хардкорного приключения, модифицировав значения ресурсов в игре, но и просто поразвлечься, изучив полюбившийся проект с разных сторон.

А на днях мне вдруг захотелось вспомнить молодость и поиграть в бумерский диаблойд под названием Titan Quest, выпущенный аж в 2006 году. Да вот только времени на беготню, прокачку, и вот это вот всё, у меня нет. И ArtMoney нет. Зато есть определенные знания программирования. Вот я и решил совместить приятное с полезным, написав аналог ArtMoney на Python, а заодно стать супербогатым, хотя бы в Titan Quest.

Для этого дела понадобились только Python и библиотека Pymem, с помощью которой можно взламывать процессы Windows и манипулировать памятью (читать и записывать).

Программа состоит из класса MemoryEditor, который отвечает за взаимодействие с процессом игры, поиск и замену значений в его памяти. И функции, которая выступает интерактивным меню для взаимодействия с юзером.

Класс MemoryEditor

class MemoryEditor:
    def __init__(self, process_name: str) -> None:
        self.pm = pymem.Pymem(process_name)
        self.process_base = pymem.process.module_from_name(self.pm.process_handle, process_name).lpBaseOfDll

Конструктор класса принимает имя процесса (process_name), которое нужно открыть (например, process.exe).

  • pymem.Pymem(process_name) — открывает процесс и позволяет взаимодействовать с его памятью.
  • process_base — это базовый адрес основного модуля процесса (обычно самого .exe файла).

Метод search_value

def search_value(self, value: int) -> list:
        search_results = []
        memory_size = 0x7FFFFFFF  # Размер памяти для сканирования (большой диапазон)
        chunk_size = 0x1000  # Размер блока чтения
        search_bytes = ctypes.c_uint32(value).value.to_bytes(4, byteorder='little')
        
        offset = 0
        while offset < memory_size:
            current_address = self.process_base + offset
            
            if self.is_memory_readable(current_address):
                try:
                    buffer = self.pm.read_bytes(current_address, chunk_size)
                except pymem.exception.MemoryReadError:
                    offset += chunk_size
                    continue
                
                chunk_offset = 0
                while True:
                    chunk_offset = buffer.find(search_bytes, chunk_offset)
                    if chunk_offset == -1:
                        break

                    # Сохранение адреса найденного значения
                    address = current_address + chunk_offset
                    search_results.append(address)
                    
                    chunk_offset += len(search_bytes)
            
            offset += chunk_size

        return search_results

Эта функция выполняет поиск заданного значения (value) в памяти процесса.

  • memory_size определяет область памяти, в которой будет производиться поиск.
  • chunk_size определяет, какой объем данных будет считываться за раз (в данном случае 4KB).
  • search_bytes преобразует значение в байтовую строку для поиска в памяти.
  • Цикл while offset < memory_size: проходит по всей указанной области памяти, проверяя каждую часть на наличие нужного значения.
  • self.is_memory_readable(current_address) проверяет, доступна ли память для чтения.
  • Если значение найдено в текущем блоке памяти, его адрес сохраняется в search_results.

Метод is_memory_readable

def is_memory_readable(self, address) -> bool:
        mbi = pymem.memory.virtual_query(self.pm.process_handle, address)
        if mbi.Protect & 0xF != 0x0 and mbi.State == 0x1000 and mbi.Protect & 0x100 == 0:
            return True
        return False

Эта функция проверяет, доступна ли память по указанному адресу для чтения.

  • Использует функцию virtual_query из библиотеки pymem, которая возвращает информацию о состоянии и защите памяти.
  • Проверяет, что память доступна, не защищена и не имеет флага PAGE_GUARD.

Метод search_next_value

def search_next_value(self, addresses: list, next_value: int) -> list:
        search_results = []
        search_bytes = ctypes.c_uint32(next_value).value.to_bytes(4, byteorder='little')
        
        for address in addresses:
            if self.is_memory_readable(address):
                try:
                    buffer = self.pm.read_bytes(address, 4)
                except pymem.exception.MemoryReadError:
                    continue
                
                if buffer == search_bytes:
                    search_results.append(address)
        
        return search_results

Эта функция ищет новое значение (next_value) только среди адресов, найденных на предыдущем этапе поиска.

  • Функция принимает список адресов (addresses) и значение для поиска (next_value).
  • Если новое значение найдено по одному из адресов, этот адрес добавляется в список search_results.

И метод replace_value

def replace_value(self, addresses: list, new_value: int) -> None:
        replace_bytes = ctypes.c_uint32(new_value).value.to_bytes(4, byteorder='little')
        for address in addresses:
            self.pm.write_bytes(address, replace_bytes, 4)
            print(f"Замена значения по адресу: {hex(address)} на {new_value}")

Функция заменяет значения по указанным адресам (addresses) на новое значение (new_value).

  • replace_bytes — это новое значение в виде байтовой строки.
  • self.pm.write_bytes(address, replace_bytes, 4) записывает новое значение в память по указанному адресу.

Вот и всё. Теперь в основной части программы необходимо просто создать экземпляр написанного выше класса с названием процесса игры, и поочередно вызывать необходимые методы, для поиска нужных ячеек, и замены значений. Я не стал мудрить с интерфейсом, и написал простейшее меню в командной строке, с запросами нужной информации у пользователя. Выглядит это так:

В игре у моего персонажа было 12345 монет, это значение я и ввел. Однако программа нашла слишком много адресов с идентичными значениями, поэтому в игре я собрал еще немного голды, изменив количество монет у персонажа, и отфильтровал адреса уже по новым данным. Во второй раз адресов было значительно меньше и я решил дальше не фильтровать, а изменить значения во всех. В итоге мой персонаж стал почти миллионером (совсем уж наглеть не стал).

Что сказать, я доволен, и могу без всяких там читов чистить данжы, закупившись хилками на все деньги.

Кто желает воспользоваться программой или дополнить её: репозиторий PyMoney.

Благодарю за внимание!