# ДЗ к занятию "Nginx - Описание, Настройка, Безопасность" ::: success Для выполнения задания необходимо использовать настроенные приложения и виртуальные машины из прошлого урока. ::: :::info Практика требует наличия: 1. Хотя бы одной виртуальной машины Linux 2. Установленный Vagrant 3. Установленный Ansible ::: Результат выполнения дз можно выкладывать на свой github, либо загружать архив с проектом в lms. ## Задача №1 ## Vagrant Для простого поднятия виртуальных машин можно воспользоваться вот таким конфигом: ```ruby= Vagrant.configure("2") do |config| config.vm.base_mac = nil config.ssh.username = "labs" config.ssh.private_key_path = "labs_private" config.ssh.forward_agent = true # config.vm.synced_folder ".", "/vagrant", disabled: true config.vm.provider "virtualbox" do |vb| vb.gui = false vb.memory = "1024" vb.cpus = 1 # vb.linked_clone = true end N = 3 (1..N).each do |machine_id| config.vm.define "nginx-#{machine_id}" do |n| #n.vm.hostname = "nginx-#{machine_id}" n.vm.network "private_network", ip: "192.168.56.#{20+machine_id}" n.vm.network "forwarded_port", guest: 80, host: "#{8080+machine_id}" n.vm.network "forwarded_port", guest: 443, host: "#{8442+machine_id}" n.vm.box = "ubuntuServer" end end end ``` Команда vagrant up будет стартовать последовательно 3 машины. Если этого не происходит - пользователю внутри системы нехватает привилегий для настройки системы. Нужно прописать его учетку в sudoers без пароля. ## Простая установка # Simple nginx setup role ::: warning Нужно поставить приложение на 2 сервера. Перед приложениями настроить балансировщик, который будет распределять доступ и проводить авторизацию с использованием сертификатов пользователей. ::: ::: danger Все ip адреса заполнять нужно по конфигурации вашей сети ::: ### Поднимаем приложение 1. Создать файл index.html, содержимое файла должно говорить на котором сервере мы оказались. Для этого лучше сделать отдельную task. 2. Создать простой конфиг для nginx. Документацию можно найти [тут](https://docs.nginx.com/nginx/admin-guide/). Содержимое конфига помещаем в переменную `nginx_configs`. Переменная может храниться в `myproject/host_vars/nginx-(1,2).yml`. Дальше роль nginx будет создавать файл конфигурации `mywebsite.conf` по пути в директории `/etc/nginx/conf.d`: ```yaml nginx_configs: - name: mywebsite.conf value: | server { listen 80; location / { access_log off; root /var/www/mywebsite; } } ``` Данный конфиг нужно располагать на 2х серверах с приложением `nginx-2` и `nginx-3`. 3. Создаем конфиг для балансировщика. Возможный путь - `myproject/host_vars/nginx-1.yml` ```yaml nginx_configs: - name: mywebsite.conf value: | upstream backend { server 192.168.56.22:80; server 192.168.56.23:80; } server { listen 80; server_name nginx-1.local; location / { proxy_pass http://backend; } } ``` 4. Запускаем тестовый запрос ```curl 127.0.0.1:8081``` несколько раз правильная настройка выдаст нам ответы от всех серверов по очереди. ## Задача №2 ### Цель - написать 2 роли, которые будут выполнять следующие операции: 1. Создать сертификаты для сервера и клиента, добавить их для работы сервера 2. Создать сертификаты для клиентов. В результате настройки сервер балансировки должен открывать страницу только по предоставленному сертификату. Набор полезных команд, которые могут понадобиться для описание роли. - Создание сертификатов УЦ ```bash openssl genrsa -out ca.key 2048 openssl req -new -x509 -days 3650 -key ca.key -out ca.crt ``` - Создание сертификата сервера. Для этого нужно создать конфиг server.cnf ```bash cat >server.cnf <<EOF [req] prompt = no distinguished_name = dn req_extensions = ext [dn] CN = nginx-1.local emailAddress = my.email@example.com O = Private person OU = Alter ego dept L = Korolyov C = RU [ext] subjectAltName = DNS:nginx-1.local,IP:127.0.0.1 EOF ``` - Создание запроса на сертификат для сервера: ```bash openssl req -new -utf8 -nameopt multiline,utf8 -config server.cnf -newkey rsa:2048 -keyout server.key -nodes -out server.csr ``` - Создание сертификата по запросу ```bash openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt -extfile server.cnf -extensions ext ``` - Создание сертификата клиента (Обязательно указываем уникальные Organization Name, Organizational Unit Name, Common Name для каждого клиента и они не должны совпадать с указанными для сервера или корневого УЦ) ```bash openssl req -new -utf8 -nameopt multiline,utf8 -newkey rsa:2048 -nodes -keyout client.key -out client.csr openssl x509 -req -days 3650 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt ``` В результате вы должны получить следующий набор файлов: - Корневые сертификат и ключ (ca.crt, ca.key) - Сертификат, ключ и запрос для клиента (client.crt, client.csr, client.key) - Сертификат, ключ и запрос для сервера (server.key, server.crt, server.csr) - Конфиг для генерирования сертификатов (server.cnf) - Созданные файлы можно так же хранить в переменных: ```yaml nginx_ssl_certs: - name: ca.crt value: | -----BEGIN CERTIFICATE----- .... -----END CERTIFICATE----- - name: server.crt value: | -----BEGIN CERTIFICATE----- .... -----END CERTIFICATE----- - name: server.key value: | -----BEGIN PRIVATE KEY----- .... -----END PRIVATE KEY----- ``` - подготовка конфига с настройкой `https`: ```yaml nginx_configs: - name: mywebsite.conf value: | upstream backend { server 192.168.56.22:80; server 192.168.56.23:80; } server { listen 80; server_name nginx-1.local; return 301 https://$host:8443$request_uri; } server { listen 443 ssl http2; server_name nginx-1.local; access_log /var/log/nginx/nginx-1.local.access.log main; error_log /var/log/nginx/nginx-1.local.error.log debug; ssl_certificate ssl/server.crt; ssl_certificate_key ssl/server.key; ssl_client_certificate ssl/ca.crt; ssl_verify_client on; location / { proxy_pass http://backend; } } ``` - после предоставления данных на балансировщик, можно проверить результат: ```curl -Lk 127.0.0.1:8081```. где -L - follow redirect (http->https), k - игнорировать что сертификат не доверенный - прверка доступа к ресурсу: ```bash curl --cacert ssl/ca.crt --cert ssl/client.crt --key ssl/client.key -L 127.0.0.1:8081 ``` - ограничения только для выбранных сертификатов. nginx умеет работать с серийным номером, поэтому можно использовать следующие команды: ```bash cert=filename.crt serial=$(openssl x509 -in ${cert} -text -noout | grep -A1 Serial | grep -v Serial | tr -d ' ') && \ echo classic serial: $serial && \ echo \$ssl_client_serial: $(echo $serial | tr -d ":" | tr '[:lower:]' '[:upper:]') ``` - вид конфига при добавлении серийника: - ```text map $ssl_client_serial $reject { default 1; ..........C5CE16 0; #client1 ..........635A2D60 0; # client2 } server { ... location / { if ($reject) { return 403; } proxy_pass http://backend; } .... ``` ### Полезные проекты для проверки безопасности конфига - https://github.com/stark0de/nginxpwner - https://github.com/yandex/gixy