Шаблон для выполнения работы
Для выполнения работы создайте новый файла в 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
HTTP/0.9 (1991 год) — самая первая версия протокола. Она поддерживала только один тип запроса —
GET
, и все ответы передавались в виде простого текста без заголовков.HTTP/1.0 (1996 год) — расширил возможности протокола, добавив поддержку заголовков и более сложных запросов. Также появилась возможность передачи файлов и других ресурсов, а не только текста.
HTTP/1.1 (1997 год) — эта версия стала основным стандартом на долгое время. В HTTP/1.1 были добавлены такие функции, как поддержка устойчивых соединений (keep-alive), что позволяло оставлять соединение открытым для передачи нескольких ресурсов подряд, и улучшенная поддержка кеширования.
HTTP/2 (2015 год) — версия, которая была разработана для повышения производительности передачи данных. HTTP/2 добавил поддержку мультиплексирования (передача нескольких запросов одновременно по одному соединению), сжатие заголовков и приоритет запросов. Это значительно улучшило скорость загрузки сайтов.
HTTP/3 (2020 год) — новейшая версия протокола, основанная на UDP вместо TCP, для улучшения задержек и производительности в современных сетях. Она использует транспортный протокол QUIC, который улучшает надежность передачи данных, особенно в условиях высокой задержки.
Основные методы HTTP
HTTP предоставляет набор методов для взаимодействия клиента с сервером. Каждый метод имеет свое назначение:
GET — запрашивает ресурс у сервера. Этот метод используется для получения данных (например, загрузки веб-страниц). Он не должен изменять состояние сервера.
- Пример использования: запрос страницы или API для получения информации.
curl -X GET http://example.com/resource
POST — отправляет данные на сервер для обработки (например, данные формы). Этот метод может изменять состояние сервера.
- Пример использования: отправка данных через форму на веб-странице или создание нового ресурса на сервере.
curl -X POST -d "name=John" http://example.com/resource
PUT — заменяет или обновляет существующий ресурс на сервере. Если ресурса нет, сервер может создать его.
- Пример использования: обновление существующего ресурса или загрузка файла на сервер.
curl -X PUT -d "name=JohnDoe" http://example.com/resource
DELETE — удаляет ресурс на сервере.
- Пример использования: удаление ресурса с сервера, например, удаление файла или записи.
curl -X DELETE http://example.com/resource
HEAD — идентичен методу
GET
, но без тела ответа. Он используется для получения только заголовков ответа, чтобы проверить наличие ресурса или метаданные, такие как размер или тип контента.- Пример использования: проверка наличия ресурса перед его загрузкой.
curl -I http://example.com/resource
PATCH — частично обновляет ресурс. В отличие от
PUT
, который заменяет весь ресурс,PATCH
обновляет только определенные части.- Пример использования: обновление части данных, например, изменение имени пользователя, не затрагивая другие данные.
curl -X PATCH -d "name=JohnDoe" http://example.com/resource
OPTIONS — возвращает список поддерживаемых сервером HTTP-методов для конкретного ресурса.
- Пример использования: проверка доступных методов на сервере.
curl -X OPTIONS http://example.com/resource
Протокол DNS
DNS (Domain Name System) — это система доменных имен, которая служит для преобразования доменных имен, понятных человеку (например, example.com
), в IP-адреса, которые используются для связи между устройствами в сети (например, 93.184.216.34
). DNS выполняет роль “телефонной книги” Интернета, где доменные имена ассоциируются с соответствующими IP-адресами.
Как происходит разрешение доменных имен
Когда пользователь вводит доменное имя в браузер, происходит следующее:
Запрос DNS отправляется на сервер, чтобы выяснить IP-адрес, соответствующий доменному имени.
Локальный DNS-кеш: Сначала браузер или операционная система проверяет, нет ли уже известного IP-адреса в локальном кеше. Если адрес найден, он используется без необходимости обращения к внешним DNS-серверам.
Рекурсивные DNS-серверы: Если доменное имя не найдено в локальном кеше, запрос направляется к рекурсивным DNS-серверам (обычно предоставляются интернет-провайдером). Они начинают поиск с корневых серверов DNS.
Корневые серверы DNS предоставляют информацию о том, какой DNS-сервер управляет зоной верхнего уровня (например,
.com
).TLD-серверы (серверы доменов верхнего уровня) (например,
.com
) направляют запрос дальше к DNS-серверам, которые отвечают за конкретный домен (например,example.com
).Авторитативные DNS-серверы для домена содержат точную информацию о том, какой IP-адрес соответствует конкретному доменному имени. Они возвращают IP-адрес, и этот адрес используется для установления соединения с сервером, обслуживающим сайт.
Возвращение IP-адреса: Полученный IP-адрес передается обратно пользователю через все предыдущие серверы, после чего браузер подключается к серверу с этим IP-адресом.
Зоны и поддомены
Зона DNS — это область ответственности DNS-сервера. Каждая зона обслуживается одним или несколькими DNS-серверами. Например, зона для домена
example.com
может содержать записи для поддоменов, таких какwww.example.com
илиmail.example.com
.Поддомен — это домен, который является частью большего домена. Например, в домене
mail.example.com
слово “mail” — это поддомен. Поддомены часто используются для структурирования веб-сайтов и сервисов.
Типы DNS-записей
DNS использует различные типы записей для хранения информации о доменах и IP-адресах. Вот основные из них:
A-запись (Address Record) — связывает доменное имя с IPv4-адресом. Это наиболее распространенная запись в DNS.
- Пример:
example.com. IN A 93.184.216.34
- Пример:
AAAA-запись — аналог A-записи, но связывает доменное имя с IPv6-адресом.
- Пример:
example.com. IN AAAA 2606:2800:220:1:248:1893:25c8:1946
- Пример:
CNAME-запись (Canonical Name Record) — устанавливает псевдоним для другого доменного имени. Это полезно для перенаправления запросов с одного домена на другой.
- Пример:
www.example.com. IN CNAME example.com.
- Пример:
MX-запись (Mail Exchange Record) — указывает почтовые серверы, которые обрабатывают электронную почту для домена. Эти записи содержат приоритеты, чтобы указать, какие серверы использовать в первую очередь.
- Пример:
example.com. IN MX 10 mail.example.com.
- Пример:
TXT-запись (Text Record) — позволяет хранить произвольную текстовую информацию, часто используется для подтверждения владения доменом или для хранения данных конфигурации, таких как SPF-записи (Sender Policy Framework), которые помогают защитить электронную почту от подделки.
- Пример:
example.com. IN TXT "v=spf1 ip4:93.184.216.34 -all"
- Пример:
Описание веб-сервера NGINX
NGINX — это высокопроизводительный веб-сервер с открытым исходным кодом, который также может выступать как обратный прокси-сервер, балансировщик нагрузки и HTTP-кэш. Он был разработан с целью обеспечения высокой производительности и низкого потребления ресурсов, что делает его популярным выбором для высоконагруженных сайтов и приложений.
Основные функции NGINX
Веб-сервер — основная функция NGINX. Он обрабатывает HTTP-запросы и возвращает пользователю веб-страницы или другой контент, такой как изображения, CSS, JavaScript.
Обратный прокси-сервер — NGINX может принимать запросы от клиентов и перенаправлять их на другие серверы (например, для микросервисов или распределенных систем).
Балансировщик нагрузки — NGINX распределяет входящий трафик между несколькими серверами, что улучшает масштабируемость и устойчивость приложения.
Кэширование — NGINX поддерживает HTTP-кэширование, что позволяет кэшировать ответы от веб-приложений и ускорять доступ к часто запрашиваемым ресурсам.
SSL/TLS терминатор — NGINX может обрабатывать SSL/TLS шифрование, принимая зашифрованные соединения от клиентов и расшифровывая их до передачи на внутренние серверы.
Статическая и динамическая обработка контента — NGINX очень эффективен в обслуживании статического контента (HTML, CSS, изображения), но может использоваться вместе с другими серверами приложений для обработки динамических запросов (например, через FastCGI, uWSGI, SCGI и другие протоколы).
Отличия NGINX от Apache
Apache — еще один популярный веб-сервер, который долгое время был стандартом в отрасли. Хотя оба сервера выполняют схожие функции, есть несколько ключевых отличий между ними:
Архитектура обработки запросов:
- NGINX использует асинхронную архитектуру, что позволяет ему обрабатывать большое количество одновременных подключений с минимальными ресурсными затратами. Он работает на основе событий и использует модель с несколькими рабочими процессами (workers).
- Apache использует потоковую или процессную модель, где каждый запрос обрабатывается в отдельном процессе или потоке, что может приводить к большему потреблению ресурсов при большом количестве одновременных соединений.
Производительность:
- NGINX обычно показывает лучшую производительность при обслуживании статического контента и при большом количестве одновременно подключенных клиентов благодаря своей асинхронной модели.
- Apache может быть более медленным в подобных сценариях, но за счет модульности может быть удобнее для обработки сложных динамических приложений (например, с использованием PHP через модуль mod_php).
Конфигурация и модульность:
- Apache обладает гибкой системой модулей, которые можно загружать или отключать по мере необходимости. Он поддерживает модульную архитектуру для различных языков программирования и технологий.
- NGINX менее модульный, и большая часть его функциональности включена по умолчанию. Однако это делает его более легким и быстрым в настройке.
Использование памяти:
- NGINX эффективнее использует память, что особенно важно для высоконагруженных систем.
- Apache при интенсивной работе с большим количеством соединений может потреблять больше оперативной памяти, особенно при использовании потоков или процессов для каждого соединения.
Обратный прокси и балансировка нагрузки:
- NGINX изначально проектировался как обратный прокси-сервер и балансировщик нагрузки, поэтому эта функциональность встроена и легко настраивается.
- Apache также может работать как прокси-сервер, но требует настройки через соответствующие модули (например, mod_proxy).
Конфигурационные файлы NGINX
Основные конфигурационные файлы NGINX располагаются в каталоге /etc/nginx/
(на Linux-системах). Главный конфигурационный файл — это nginx.conf
.
Структура конфигурационного файла nginx.conf
:
Глобальные настройки: Здесь определяются параметры, применяемые ко всему серверу, такие как количество рабочих процессов, логи, и настройки для управления соединениями:
worker_processes auto; events { worker_connections 1024; }
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; } } }
server-блок: Этот блок конфигурации определяет виртуальный хост. Внутри него настраиваются такие параметры, как домен, на котором будет работать сервер, и пути к файлам:
server { listen 80; server_name example.com; location / { root /var/www/html; index index.html index.htm; } }
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-файл для этого сервера, чтобы он запускался автоматически.
Создайте файл unit в директории
/etc/systemd/system/
:sudo nano /etc/systemd/system/python_server.service
Внутри файла добавьте следующее содержимое:
[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 и скрипту правильный.
- User: Замените
Примените изменения и запустите сервис:
sudo systemctl daemon-reload sudo systemctl start python_server sudo systemctl enable python_server
Проверьте, что сервер запущен:
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
.
Откройте файл конфигурации
dnsmasq
:sudo nano /etc/dnsmasq.conf
Добавьте следующие строки:
address=/python.ivanov.local/10.0.1.152 address=/static.ivanov.local/10.0.1.152
Перезапустите
dnsmasq
:sudo systemctl restart dnsmasq
Теперь python.ivanov.local
и static.ivanov.local
будут разрешаться в IP-адрес 10.0.1.152
.
2. Настройка NGINX
Установите и настройте NGINX на этой же машине.
Установите NGINX:
sudo apt install nginx
Создайте конфигурацию для доменов
python.ivanov.local
иstatic.ivanov.local
:sudo nano /etc/nginx/sites-available/ivanov.local
Добавьте следующее содержимое:
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
.
- Первая секция обрабатывает запросы к
Активируйте конфигурацию:
sudo ln -s /etc/nginx/sites-available/ivanov.local /etc/nginx/sites-enabled/
Создайте директорию для статической страницы и саму страницу:
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>
Перезапустите NGINX для применения изменений:
sudo systemctl reload nginx
3. Тестирование
1. Изменение DNS-сервера на машине с Python-сервером
Откройте файл конфигурации
/etc/resolv.conf
, где указываются DNS-серверы:sudo nano /etc/resolv.conf
Добавьте строку с IP-адресом машины, на которой настроен
dnsmasq
(в нашем случае это вторая машина с IP10.0.1.152
):nameserver 10.0.1.152
Сохраните файл и закройте его.
Обратите внимание, что изменения в файле
/etc/resolv.conf
могут быть временными, поскольку некоторые системы автоматически перезаписывают этот файл. Чтобы сделать изменения постоянными, можно внести их в файл/etc/netplan/*.yaml
или в настройках DHCP.
2. Проверка доступности доменных имен с помощью curl
Теперь, когда DNS настроен на использование dnsmasq
сервера, можно проверить доступность ресурсов через доменные имена.
Проверка доступа к 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>
Проверка доступа к статической странице на
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
.