Шаблон для выполнения работы

Для выполнения работы создайте новый файла в Obsidian, назовите его “Фамилия Имя Отчество Группа”, скопируйте и вставьте представленный ниже шаблон:

# Лабораторная работа №2

## Сервер 1

```bash
<Тут должен быть вывод команд, можно скриншотами>
$ cat /home/user/python_server.py
$ cat /etc/systemd/system/python_server.service
$ systemctl status python_server

```

## Сервер 2

```bash
<Тут должен быть вывод команд, можно скриншотами>
$ cat /etc/dnsmasq.conf # только последние строки, которые вы настраивали
$ systemctl status dnsmasq
$ cat /etc/nginx/sites-available/ivanov.local
$ systemctl status nginx 
$ cat /var/www/static/index.html

```

## Тестирование

Команды выполняются на втором сервере.

```bash
<Тут должен быть вывод команд, можно скриншотами>
$ cat /etc/resolv.conf
$ ping -c 4 python.ivanov.local
$ ping -c 4 static.ivanov.local
$ curl -X GET http://python.ivanov.local
$ curl -X GET http://static.ivanov.local
$ curl -X POST -d "name=John" python.ivanov.local
$ curl -X PUT -d "name=JohnDoe" python.ivanov.local
$ curl -X DELETE python.ivanov.local

```

## Вопросы для самопроверки
1. Какие методы HTTP существуют, и для чего они используются?
2. Как сервер отвечает на различные запросы?
3. Какой тип DNS-записи отвечает за привязку доменного имени к IP?
4. Что такое CNAME-запись?
5. Какой конфигурационный файл отвечает за настройки NGINX?
6. Какие основные блоки конфигурации используются для настройки сервера?

Теоретическая часть

Протокол HTTP

HTTP (HyperText Transfer Protocol) — это протокол прикладного уровня, который используется для передачи гипертекста (обычно веб-страниц) по сети, в основном в Интернете. Он лежит в основе взаимодействия между веб-браузерами (клиентами) и веб-серверами, позволяя передавать данные, такие как HTML-документы, изображения, видео и другие ресурсы.

Краткая история HTTP

  1. HTTP/0.9 (1991 год) — самая первая версия протокола. Она поддерживала только один тип запроса — GET, и все ответы передавались в виде простого текста без заголовков.

  2. HTTP/1.0 (1996 год) — расширил возможности протокола, добавив поддержку заголовков и более сложных запросов. Также появилась возможность передачи файлов и других ресурсов, а не только текста.

  3. HTTP/1.1 (1997 год) — эта версия стала основным стандартом на долгое время. В HTTP/1.1 были добавлены такие функции, как поддержка устойчивых соединений (keep-alive), что позволяло оставлять соединение открытым для передачи нескольких ресурсов подряд, и улучшенная поддержка кеширования.

  4. HTTP/2 (2015 год) — версия, которая была разработана для повышения производительности передачи данных. HTTP/2 добавил поддержку мультиплексирования (передача нескольких запросов одновременно по одному соединению), сжатие заголовков и приоритет запросов. Это значительно улучшило скорость загрузки сайтов.

  5. HTTP/3 (2020 год) — новейшая версия протокола, основанная на UDP вместо TCP, для улучшения задержек и производительности в современных сетях. Она использует транспортный протокол QUIC, который улучшает надежность передачи данных, особенно в условиях высокой задержки.

Основные методы HTTP

HTTP предоставляет набор методов для взаимодействия клиента с сервером. Каждый метод имеет свое назначение:

  1. GET — запрашивает ресурс у сервера. Этот метод используется для получения данных (например, загрузки веб-страниц). Он не должен изменять состояние сервера.

    • Пример использования: запрос страницы или API для получения информации.
    curl -X GET http://example.com/resource
    
  2. POST — отправляет данные на сервер для обработки (например, данные формы). Этот метод может изменять состояние сервера.

    • Пример использования: отправка данных через форму на веб-странице или создание нового ресурса на сервере.
    curl -X POST -d "name=John" http://example.com/resource
    
  3. PUT — заменяет или обновляет существующий ресурс на сервере. Если ресурса нет, сервер может создать его.

    • Пример использования: обновление существующего ресурса или загрузка файла на сервер.
    curl -X PUT -d "name=JohnDoe" http://example.com/resource
    
  4. DELETE — удаляет ресурс на сервере.

    • Пример использования: удаление ресурса с сервера, например, удаление файла или записи.
    curl -X DELETE http://example.com/resource
    
  5. HEAD — идентичен методу GET, но без тела ответа. Он используется для получения только заголовков ответа, чтобы проверить наличие ресурса или метаданные, такие как размер или тип контента.

    • Пример использования: проверка наличия ресурса перед его загрузкой.
    curl -I http://example.com/resource
    
  6. PATCH — частично обновляет ресурс. В отличие от PUT, который заменяет весь ресурс, PATCH обновляет только определенные части.

    • Пример использования: обновление части данных, например, изменение имени пользователя, не затрагивая другие данные.
    curl -X PATCH -d "name=JohnDoe" http://example.com/resource
    
  7. OPTIONS — возвращает список поддерживаемых сервером HTTP-методов для конкретного ресурса.

    • Пример использования: проверка доступных методов на сервере.
    curl -X OPTIONS http://example.com/resource
    

Протокол DNS

DNS (Domain Name System) — это система доменных имен, которая служит для преобразования доменных имен, понятных человеку (например, example.com), в IP-адреса, которые используются для связи между устройствами в сети (например, 93.184.216.34). DNS выполняет роль “телефонной книги” Интернета, где доменные имена ассоциируются с соответствующими IP-адресами.

Как происходит разрешение доменных имен

Когда пользователь вводит доменное имя в браузер, происходит следующее:

  1. Запрос DNS отправляется на сервер, чтобы выяснить IP-адрес, соответствующий доменному имени.

  2. Локальный DNS-кеш: Сначала браузер или операционная система проверяет, нет ли уже известного IP-адреса в локальном кеше. Если адрес найден, он используется без необходимости обращения к внешним DNS-серверам.

  3. Рекурсивные DNS-серверы: Если доменное имя не найдено в локальном кеше, запрос направляется к рекурсивным DNS-серверам (обычно предоставляются интернет-провайдером). Они начинают поиск с корневых серверов DNS.

  4. Корневые серверы DNS предоставляют информацию о том, какой DNS-сервер управляет зоной верхнего уровня (например, .com).

  5. TLD-серверы (серверы доменов верхнего уровня) (например, .com) направляют запрос дальше к DNS-серверам, которые отвечают за конкретный домен (например, example.com).

  6. Авторитативные DNS-серверы для домена содержат точную информацию о том, какой IP-адрес соответствует конкретному доменному имени. Они возвращают IP-адрес, и этот адрес используется для установления соединения с сервером, обслуживающим сайт.

  7. Возвращение IP-адреса: Полученный IP-адрес передается обратно пользователю через все предыдущие серверы, после чего браузер подключается к серверу с этим IP-адресом.

Зоны и поддомены

  • Зона DNS — это область ответственности DNS-сервера. Каждая зона обслуживается одним или несколькими DNS-серверами. Например, зона для домена example.com может содержать записи для поддоменов, таких как www.example.com или mail.example.com.

  • Поддомен — это домен, который является частью большего домена. Например, в домене mail.example.com слово “mail” — это поддомен. Поддомены часто используются для структурирования веб-сайтов и сервисов.

Типы DNS-записей

DNS использует различные типы записей для хранения информации о доменах и IP-адресах. Вот основные из них:

  1. A-запись (Address Record) — связывает доменное имя с IPv4-адресом. Это наиболее распространенная запись в DNS.

    • Пример:
      example.com.    IN  A   93.184.216.34
      
  2. AAAA-запись — аналог A-записи, но связывает доменное имя с IPv6-адресом.

    • Пример:
      example.com.    IN  AAAA  2606:2800:220:1:248:1893:25c8:1946
      
  3. CNAME-запись (Canonical Name Record) — устанавливает псевдоним для другого доменного имени. Это полезно для перенаправления запросов с одного домена на другой.

    • Пример:
      www.example.com.  IN  CNAME   example.com.
      
  4. MX-запись (Mail Exchange Record) — указывает почтовые серверы, которые обрабатывают электронную почту для домена. Эти записи содержат приоритеты, чтобы указать, какие серверы использовать в первую очередь.

    • Пример:
      example.com.    IN  MX  10   mail.example.com.
      
  5. TXT-запись (Text Record) — позволяет хранить произвольную текстовую информацию, часто используется для подтверждения владения доменом или для хранения данных конфигурации, таких как SPF-записи (Sender Policy Framework), которые помогают защитить электронную почту от подделки.

    • Пример:
      example.com.    IN  TXT   "v=spf1 ip4:93.184.216.34 -all"
      

Описание веб-сервера NGINX

NGINX — это высокопроизводительный веб-сервер с открытым исходным кодом, который также может выступать как обратный прокси-сервер, балансировщик нагрузки и HTTP-кэш. Он был разработан с целью обеспечения высокой производительности и низкого потребления ресурсов, что делает его популярным выбором для высоконагруженных сайтов и приложений.

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

  1. Веб-сервер — основная функция NGINX. Он обрабатывает HTTP-запросы и возвращает пользователю веб-страницы или другой контент, такой как изображения, CSS, JavaScript.

  2. Обратный прокси-сервер — NGINX может принимать запросы от клиентов и перенаправлять их на другие серверы (например, для микросервисов или распределенных систем).

  3. Балансировщик нагрузки — NGINX распределяет входящий трафик между несколькими серверами, что улучшает масштабируемость и устойчивость приложения.

  4. Кэширование — NGINX поддерживает HTTP-кэширование, что позволяет кэшировать ответы от веб-приложений и ускорять доступ к часто запрашиваемым ресурсам.

  5. SSL/TLS терминатор — NGINX может обрабатывать SSL/TLS шифрование, принимая зашифрованные соединения от клиентов и расшифровывая их до передачи на внутренние серверы.

  6. Статическая и динамическая обработка контента — NGINX очень эффективен в обслуживании статического контента (HTML, CSS, изображения), но может использоваться вместе с другими серверами приложений для обработки динамических запросов (например, через FastCGI, uWSGI, SCGI и другие протоколы).

Отличия NGINX от Apache

Apache — еще один популярный веб-сервер, который долгое время был стандартом в отрасли. Хотя оба сервера выполняют схожие функции, есть несколько ключевых отличий между ними:

  1. Архитектура обработки запросов:

    • NGINX использует асинхронную архитектуру, что позволяет ему обрабатывать большое количество одновременных подключений с минимальными ресурсными затратами. Он работает на основе событий и использует модель с несколькими рабочими процессами (workers).
    • Apache использует потоковую или процессную модель, где каждый запрос обрабатывается в отдельном процессе или потоке, что может приводить к большему потреблению ресурсов при большом количестве одновременных соединений.
  2. Производительность:

    • NGINX обычно показывает лучшую производительность при обслуживании статического контента и при большом количестве одновременно подключенных клиентов благодаря своей асинхронной модели.
    • Apache может быть более медленным в подобных сценариях, но за счет модульности может быть удобнее для обработки сложных динамических приложений (например, с использованием PHP через модуль mod_php).
  3. Конфигурация и модульность:

    • Apache обладает гибкой системой модулей, которые можно загружать или отключать по мере необходимости. Он поддерживает модульную архитектуру для различных языков программирования и технологий.
    • NGINX менее модульный, и большая часть его функциональности включена по умолчанию. Однако это делает его более легким и быстрым в настройке.
  4. Использование памяти:

    • NGINX эффективнее использует память, что особенно важно для высоконагруженных систем.
    • Apache при интенсивной работе с большим количеством соединений может потреблять больше оперативной памяти, особенно при использовании потоков или процессов для каждого соединения.
  5. Обратный прокси и балансировка нагрузки:

    • NGINX изначально проектировался как обратный прокси-сервер и балансировщик нагрузки, поэтому эта функциональность встроена и легко настраивается.
    • Apache также может работать как прокси-сервер, но требует настройки через соответствующие модули (например, mod_proxy).

Конфигурационные файлы NGINX

Основные конфигурационные файлы NGINX располагаются в каталоге /etc/nginx/ (на Linux-системах). Главный конфигурационный файл — это nginx.conf.

Структура конфигурационного файла nginx.conf:

  1. Глобальные настройки: Здесь определяются параметры, применяемые ко всему серверу, такие как количество рабочих процессов, логи, и настройки для управления соединениями:

    worker_processes  auto;
    events {
        worker_connections  1024;
    }
    
  2. http-блок: В этом блоке задаются параметры для обработки HTTP-запросов:

    http {
        include       mime.types;
        default_type  application/octet-stream;
    
        # Логи
        access_log  /var/log/nginx/access.log;
        error_log   /var/log/nginx/error.log;
    
        # Настройки сжатия
        gzip on;
        gzip_types text/plain application/json;
    
        # Серверные блоки
        server {
            listen       80;
            server_name  example.com;
    
            location / {
                root   /var/www/html;
                index  index.html index.htm;
            }
    
            location /images/ {
                root /data;
            }
        }
    }
    
  3. server-блок: Этот блок конфигурации определяет виртуальный хост. Внутри него настраиваются такие параметры, как домен, на котором будет работать сервер, и пути к файлам:

    server {
        listen       80;
        server_name  example.com;
    
        location / {
            root   /var/www/html;
            index  index.html index.htm;
        }
    }
    
  4. location-блоки: Внутри server можно указать location для маршрутизации запросов. Например, можно отдельно обрабатывать запросы для определенных URL:

    location /images/ {
        root /data;
    }
    

Основные команды управления NGINX:

  • Запуск сервера:

    sudo systemctl start nginx
    
  • Перезапуск сервера после изменения конфигурации:

    sudo systemctl reload nginx
    
  • Проверка конфигурации на ошибки:

    sudo nginx -t
    

Практическая часть

Ниже по тексту будет встречаться использование транслита фамилии “Иванов” в качестве примера. Вы должны заменить её на свою.

Настройка Systemd Unit для Python-сервера

На первой машине, где будет запускаться Python-сервер, нужно создать systemd unit, который будет автоматически запускать сервер при загрузке системы.

1. Python-сервер

from http.server import BaseHTTPRequestHandler, HTTPServer

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):

    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(b"<html><body><h1>GET request received</h1></body></html>")

    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_length)
        self.send_response(201)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        response = f"<html><body><h1>POST request received with data: {post_data.decode('utf-8')}</h1></body></html>"
        self.wfile.write(response.encode('utf-8'))

    def do_PUT(self):
        content_length = int(self.headers['Content-Length'])
        put_data = self.rfile.read(content_length)
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        response = f"<html><body><h1>PUT request received with data: {put_data.decode('utf-8')}</h1></body></html>"
        self.wfile.write(response.encode('utf-8'))

    def do_DELETE(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(b"<html><body><h1>DELETE request received</h1></body></html>")

def run(server_class=HTTPServer, handler_class=SimpleHTTPRequestHandler, port=8080):
    server_address = ('', port)
    httpd = server_class(server_address, handler_class)
    print(f"Starting server on port {port}")
    httpd.serve_forever()

if __name__ == '__main__':
    run()

Сохраните этот код в файл, например, /home/user/python_server.py.

2. Systemd Unit для Python-сервера

Создайте systemd unit-файл для этого сервера, чтобы он запускался автоматически.

  1. Создайте файл unit в директории /etc/systemd/system/:

    sudo nano /etc/systemd/system/python_server.service
    
  2. Внутри файла добавьте следующее содержимое:

    [Unit]
    Description=Python HTTP Server
    After=network.target
    
    [Service]
    User=user
    WorkingDirectory=/home/user
    ExecStart=/usr/bin/python3 /home/user/python_server.py
    Restart=always
    
    [Install]
    WantedBy=multi-user.target
    
    • User: Замените user на ваше имя пользователя.
    • ExecStart: Убедитесь, что путь к Python и скрипту правильный.
  3. Примените изменения и запустите сервис:

    sudo systemctl daemon-reload
    sudo systemctl start python_server
    sudo systemctl enable python_server
    
  4. Проверьте, что сервер запущен:

    sudo systemctl status python_server
    

Теперь Python-сервер будет запускаться автоматически при загрузке и работать на порту 8080.

Настройка dnsmasq и NGINX на второй машине

На второй машине нужно настроить dnsmasq для работы с доменными именами и настроить NGINX для обработки этих имен.

1. Настройка dnsmasq

Установите dnsmasq на вторую машину (если он еще не установлен):

sudo apt update
sudo apt install dnsmasq

Настройте dnsmasq для резолвинга доменных имен python.ivanov.local и static.ivanov.local на IP-адрес 10.0.1.152.

  1. Откройте файл конфигурации dnsmasq:

    sudo nano /etc/dnsmasq.conf
    
  2. Добавьте следующие строки:

    address=/python.ivanov.local/10.0.1.152
    address=/static.ivanov.local/10.0.1.152
    
  3. Перезапустите dnsmasq:

    sudo systemctl restart dnsmasq
    

Теперь python.ivanov.local и static.ivanov.local будут разрешаться в IP-адрес 10.0.1.152.

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

Установите и настройте NGINX на этой же машине.

  1. Установите NGINX:

    sudo apt install nginx
    
  2. Создайте конфигурацию для доменов python.ivanov.local и static.ivanov.local:

    sudo nano /etc/nginx/sites-available/ivanov.local
    
  3. Добавьте следующее содержимое:

    server {
        listen 80;
        server_name python.ivanov.local;
    
        location / {
            proxy_pass http://10.0.1.151:8080;  # IP первой машины с Python-сервером
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
    
    server {
        listen 80;
        server_name static.ivanov.local;
    
        location / {
            root /var/www/static;
            index index.html;
        }
    }
    
    • Первая секция обрабатывает запросы к python.ivanov.local и проксирует их на первую машину с Python-сервером (предполагается, что её IP — 10.0.1.151).
    • Вторая секция обслуживает запросы к static.ivanov.local и выдает статическую HTML-страницу из директории /var/www/static.
  4. Активируйте конфигурацию:

    sudo ln -s /etc/nginx/sites-available/ivanov.local /etc/nginx/sites-enabled/
    
  5. Создайте директорию для статической страницы и саму страницу:

    sudo mkdir -p /var/www/static
    sudo nano /var/www/static/index.html
    

    В файл index.html добавьте следующий пример простой HTML-страницы:

    <html>
    <head>
        <title>Static Page</title>
    </head>
    <body>
        <h1>Welcome to static.ivanov.local!</h1>
        <p>This is a simple static page served by NGINX.</p>
    </body>
    </html>
    
  6. Перезапустите NGINX для применения изменений:

    sudo systemctl reload nginx
    

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

1. Изменение DNS-сервера на машине с Python-сервером

  1. Откройте файл конфигурации /etc/resolv.conf, где указываются DNS-серверы:

    sudo nano /etc/resolv.conf
    
  2. Добавьте строку с IP-адресом машины, на которой настроен dnsmasq (в нашем случае это вторая машина с IP 10.0.1.152):

    nameserver 10.0.1.152
    
  3. Сохраните файл и закройте его.

Обратите внимание, что изменения в файле /etc/resolv.conf могут быть временными, поскольку некоторые системы автоматически перезаписывают этот файл. Чтобы сделать изменения постоянными, можно внести их в файл /etc/netplan/*.yaml или в настройках DHCP.

2. Проверка доступности доменных имен с помощью curl

Теперь, когда DNS настроен на использование dnsmasq сервера, можно проверить доступность ресурсов через доменные имена.

  1. Проверка доступа к Python-серверу через NGINX на python.ivanov.local:

    Выполните команду curl, чтобы убедиться, что запросы через NGINX проксируются к Python-серверу, который работает на другой машине:

    curl http://python.ivanov.local
    

    Ожидаемый результат — это ответ от Python-сервера, который проксируется через NGINX. Например, если Python-сервер возвращает HTML-страницу с текстом “GET request received”, то вы увидите этот текст в выводе curl.

    Пример успешного ответа:

    <html><body><h1>GET request received</h1></body></html>
    
  2. Проверка доступа к статической странице на static.ivanov.local:

    Выполните команду curl, чтобы проверить доступность статической HTML-страницы:

    curl http://static.ivanov.local
    

    Ожидаемый результат — это содержимое статической страницы, которую вы настроили в NGINX.

    Пример успешного ответа:

    <html>
    <head>
        <title>Static Page</title>
    </head>
    <body>
        <h1>Welcome to static.ivanov.local!</h1>
        <p>This is a simple static page served by NGINX.</p>
    </body>
    </html>
    

3. Использование ping для проверки разрешения доменных имен

Также можно проверить, правильно ли доменные имена разрешаются в IP-адрес с помощью команды ping:

  • Для python.ivanov.local:

    ping python.ivanov.local
    
  • Для static.ivanov.local:

    ping static.ivanov.local
    

В обоих случаях ping должен показывать, что домены разрешаются в IP-адрес 10.0.1.152, который был настроен в dnsmasq.