---
# System prepended metadata

title: Ответ на тестовое задание для DevOps

---

# Ответ на тестовое задание для DevOps

## 1. Немного о себе

- Меня зовут Вахутинский Андрей
- Я работаю в компании "ИНТЕКО", которая является одним из девелоперов в Москве, Санкт-Петербурге и Ростове-на-Дону, заместителем начальника ИТ отдела. 
- Не смотря на название должности, в основном выполняю функции сетевого инженера, VoIP специалиста, немного - системного администратора Windows и Linux. И совсем немного административной работы.
- Какой стек технологий использую: 
    - в моём случае это больше стек TCP/IP :smiley: 
    - L2/L3 протоколы: Ethernet, ARP, IP, BGP, OSPF, VRRP, HSRP
    - коммутаторы/маршрутизаторы/WiFi фирм: Cisco, HP/3Com, Huawei, Mikrotik, Ubiquiti (в принципе настрою любое - не встречал ещё пока тех, которые невозможно было бы настроить)
    - серверы под ОС: Windows Server (2008, 2012, 2016), Linux (CentOS, Debian, Ubuntu)
    - сервисы: DNS, DHCP, TFTP, HTTP(S), FTP, SSH, SNMP, NTP, RADIUS, SIP, и т.д.
    - технологии: VPN, IPSEC, PPTP, L2TP, NAT, ACL, port-security, и т.д.
- Инструменты DevOps, которыми владею - немного сложно, ибо я только на несколько шагов приблизился к DevOps и не знаю как там оно у взрослых дядей, но из того что знаю должно использоваться и что использую в своей работе:
    - мониторинг - Zabbix (PRTG - windows)
    - Trello/Kanboard для работы с задачами в стиле Kanban
    - OTRS - бесплатный аналог JIRA для управления тикетами, если можно так выразиться ;)
    - Limesurvey - для сбора обратной связи от пользователей
    - могу подправить чужой скрипт на bash и потихоньку уже на python (если там нет чего-то серьёзного, связанного с классами и ООП)
- В каких областях DevOps вы разбираетесь лучше всего:
    - из всего этого - однозначно в сетевых
    - я как пользователь - в линуксе (хотя глядя на глубину знаний Романа, мне как-то стыдно говорить что я что-то знаю..)
- Какие темы из программы курса “DevOps-инженер” вы хотели бы рассказать в качестве лектора?
    - Опять же темы по сетям. При том, что Роман их рассказывает очень классно и я бы не сказал, что я хочу рассказать их лучше его - просто я мог бы это сделать, чтобы, например, разгрузить его, если необходимо.
- был ли у вас опыт выступлений или обучения кого-либо? если да, то какой именно?
    - Да, опыт есть. 
    - По выступлениям - работал в компании АйТи пресейлом, презентовал проекты по сетям для достаточно крупных компаний в энергетической сфере.
    - По обучению - практически везде где работал - делился знаниями. На текущем месте работы я уже 6 лет - при внедрении новой системы (например, тот же Limesurvey для опросов, OTRS для системы тикетов) - писал инструкции и проводил обучения по работе с этими системами.

## 2. Мини-лекция
https://yadi.sk/i/7QCyhp51JHYd8g

## 3. Код
Не очень понимаю, что именно можно прислать в виде кода по сетям. Долго думал по этому поводу.
Решил прислать мой код из ДЗ по поводу сетей - моё понимание того, что происходит, когда происходит запрос http://netology.ru
Честно скажу - я не всё это знал до занятий в Нетологии - что касается fd, например, узнал только здесь.



- Сначала происходит анализ конфигурационных файлов.

- Проверяется очерёдность БД для резолва.

`[pid 13168] 08:19:11 openat(AT_FDCWD, "/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC <unfinished ...>`

 - Содержимое файла:

```
root@vagrant:~# cat /etc/nsswitch.conf
hosts:          files dns
networks:       files
```

- Судя по всему - получаем приоритетность информации (локальная приоритетнее данных из DNS)

`[pid 13168] 08:19:11 openat(AT_FDCWD, "/etc/host.conf", O_RDONLY|O_CLOEXEC <unfinished ...>`

 - Содержимое файла:

```
root@vagrant:~# cat /etc/host.conf
order hosts,bind
```

- Обращение к файлу, содержащему IP-адреса DNS-серверов.

`[pid 13168] 08:19:11 openat(AT_FDCWD, "/etc/resolv.conf", O_RDONLY|O_CLOEXEC <unfinished ...>`

 - Содержимое файла:

```
root@vagrant:~# cat /etc/resolv.conf
nameserver 127.0.0.53
```

- Обращение к файлу с проверкой, нет ли этого хоста в локальном файле hosts

`[pid 13168] 08:19:11 openat(AT_FDCWD, "/etc/hosts", O_RDONLY|O_CLOEXEC <unfinished ...>`

 - Содержимое файла:

```
root@vagrant:~# cat /etc/hosts
127.0.0.1       localhost
127.0.1.1       vagrant.vm      vagrant
```

- Открываем сокет, присваеваем ему fd = 7

```
[pid 13168] 08:19:11 socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP = 7
[pid 13168] 08:19:11 setsockopt(7, SOL_IP, IP_RECVERR, [1], 4  = 0
```

- Устанавливаем соединение с этим сокетом

```
[pid 13168] 08:19:11 connect(7, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, 16 <unfinished ...>
[pid 13168] 08:19:11 <... sendmmsg resumed>[{msg_hdr={msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\263{\1\0\0\1\0\0\0\0\0\1\7netology\2ru\0\0\1\0\1\0\0)\4"..., iov_len=39}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, msg_len=39}, {msg_hdr={msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\0y\1\0\0\1\0\0\0\0\0\1\7netology\2ru\0\0\34\0\1\0\0)\4"..., iov_len=39}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, msg_len=39}], 2, MSG_NOSIGNAL) = 2
[pid 13168] 08:19:11 <... recvfrom resumed>"\0y\201\200\0\1\0\0\0\0\0\1\7netology\2ru\0\0\34\0\1\0\0)\377"..., 2048, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, [28->16]) = 39
[pid 13168] 08:19:11 <... recvfrom resumed>"\263{\201\200\0\1\0\1\0\0\0\1\7netology\2ru\0\0\1\0\1\300\f\0\1"..., 65536, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, [28->16]) = 55
```

- За счёт того, что 127.0.0.53 слушает наш же компьютер (без подсказке в чате я бы не понял как это посмотреть мне кажется)

```
vagrant@vagrant:~$ sudo lsof -ni @127.0.0.53:53
COMMAND   PID            USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
systemd-r 608 systemd-resolve   12u  IPv4  22556      0t0  UDP 127.0.0.53:domain
systemd-r 608 systemd-resolve   13u  IPv4  22557      0t0  TCP 127.0.0.53:domain (LISTEN)
```

 - Вот конфигурация самого systemd-resolve

```
root@vagrant:~# systemd-resolve --status`
Link 2 (eth0)
      Current Scopes: DNS
DefaultRoute setting: yes
       LLMNR setting: yes
MulticastDNS setting: no
  DNSOverTLS setting: no
      DNSSEC setting: no
    DNSSEC supported: no
  Current DNS Server: 10.0.2.3
         DNS Servers: 10.0.2.3
```

- Дальше идёт ARP-запрос от нашего компьютера в наш бродкастный домен с вопросом: кто такой 10.0.2.3 ? Идёт ARP запрос, т.к. IP находится в нашей подсети.

`08:00:27:81:2f:f8 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 10.0.2.3 tell 10.0.2.15, length 28`

- Дальше от 10.0.2.3 прилетает ответ с его MAC-адрресом.

`11:50:53.475218 52:54:00:12:35:03 > 08:00:27:81:2f:f8, ethertype ARP (0x0806), length 60: Reply 10.0.2.3 is-at 52:54:00:12:35:03, length 46`

- Собственно IP-пакет энкапсулируется в Ethernet-фрейм с полученным ранее MAC в dest, и отправляется по этому MAC-адресу.

 - Вот собственно наш запрос. По UDP запросили A и AAAA запись домена netology.ru 

```
08:19:11.648332 IP 10.0.2.15.45731 > 10.0.2.3.53: 29743+ [1au] A? netology.ru. (39)
08:19:11.648449 IP 10.0.2.15.44139 > 10.0.2.3.53: 12721+ [1au] AAAA? netology.ru. (39)
```

- Дальше приходит ответ от DNS сервера

```
08:19:11.667699 IP 10.0.2.3.53 > 10.0.2.15.44139: 12721 0/1/1 (101)
08:19:11.670141 IP 10.0.2.3.53 > 10.0.2.15.45731: 29743 1/0/1 A 172.67.75.22 (55)
```

- После чего открывается socket и ему присваевается fd = 5.

```
08:19:11 socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 5
08:19:11 setsockopt(5, SOL_TCP, TCP_NODELAY, [1], 4) = 0
08:19:11 setsockopt(5, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
08:19:11 setsockopt(5, SOL_TCP, TCP_KEEPIDLE, [60], 4) = 0
08:19:11 setsockopt(5, SOL_TCP, TCP_KEEPINTVL, [60], 4) = 0
08:19:11 connect(5, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("172.67.75.22")}, 16) = -1 EINPROGRESS (Operation now in progress)
```

- И устанавливается соединение с сокетом

```
08:19:11 getpeername(5, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("172.67.75.22")}, [128->16]) = 0
08:19:11 getsockname(5, {sa_family=AF_INET, sin_port=htons(50630), sin_addr=inet_addr("10.0.2.15")}, [128->16]) = 0
08:19:11 sendto(5, "HEAD / HTTP/1.1\r\nHost: netology.r"..., 75, MSG_NOSIGNAL, NULL, 0) = 75
```

- Дальше, т.к. указанный IP-адрес не находится в нашей локальной сети, необходимо отправить этот пакет на default gw.
Аналогично предыдущему разу - идёт запрос - какой MAC у 10.0.2.2 и приходит ответ.

```
08:00:27:81:2f:f8 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 10.0.2.2 tell 10.0.2.15, length 28
52:54:00:12:35:02 > 08:00:27:81:2f:f8, ethertype ARP (0x0806), length 60: Reply 10.0.2.2 is-at 52:54:00:12:35:02, length 46
```

- Это на 2 и 3-м уровнях.
- На 4-м уровне начинается установление TCP-сессии.

 - Наш хост отправляет пакет cо своим source ip и source портом из диапазона 1025-65535 на адрес 172.67.75.22 на порт 80 по протоколу TCP, с флагом SYN, номером последовательности 552696288 и размером окна 64240, mss 1460 и window scale = 7.

`length 74: 10.0.2.15.51872 > 172.67.75.22.80: Flags [S], seq 552696288, win 64240, options [mss 1460,sackOK,TS val 1977256836 ecr 0,nop,wscale 7], length 0`

 - В случае прохождения через маршрутизаторы, каждый раз в фреймах меняется как source mac, так и dest mac. При этом (кроме NAT) source ip и dest ip не меняются.

 - В нашем случае на нашем default gw настроен NAT, поэтому на следующем этапе прохождения пакета, source ip изменится на наш "реальный" адрес, и будет сделана запись в таблице NAT-трансляций, чтобы ответный пакет был перенаправлен на нужный "внутренний" адрес. 10.0.2.15.51872 -> REAL-IP:new-port

 - То есть до веб-сервера долетает пакет с source REAL-IP:new-port с тем же destination.

 - После этого хост 172.67.75.22 отвечает с порта 80 на REAL-IP:new-port, но долетев до нашего роутера, destination меняется на 10.0.2.15.51872 благодаря прошлой записи в таблице NAT-трансляций.

 - Отвечает пакетом с флагами SYN-ACK с новым SEQ 671552001 и ACK на 1 больше.

`length 60: 172.67.75.22.80 > 10.0.2.15.51872: Flags [S.], seq 671552001, ack 552696289, win 65535, options [mss 1460], length 0`

 - Наш компьютер подтверждает получение пакета флагом ACK.

`length 54: 10.0.2.15.51872 > 172.67.75.22.80: Flags [.], ack 1, win 64240, length 0`

 - После этого наш компьютер отправляет необходимые данные по протоколу http ( HEAD / HTTP/1.1 ) (флаг Push Data)

`length 130: 10.0.2.15.51872 > 172.67.75.22.80: Flags [P.], seq 1:77, ack 1, win 64240, length 76: HTTP: HEAD / HTTP/1.1`

 - Сервер подтверждает получение пакета ACK'ом.

`length 60: 172.67.75.22.80 > 10.0.2.15.51872: Flags [.], ack 77, win 65535, length 0`

 - После чего отвечает на запрос "HTTP/1.1 301 Moved Permanently"

`length 430: 172.67.75.22.80 > 10.0.2.15.51872: Flags [P.], seq 1:377, ack 77, win 65535, length 376: HTTP: HTTP/1.1 301 Moved Permanently`

- Система получает информацию

`08:19:11 recvfrom(5, "HTTP/1.1 301 Moved Permanently\r\n"..., 102400, 0, NULL, NULL) = 257`

- И затем выводит её пользователю на экран

`08:19:11 write(1, "HTTP/1.1 301 Moved Permanently\r\n"..., 257) = 257`

 - Наш компьютер подтверждает получение, следом отправляет FIN-ACK

```
length 54: 10.0.2.15.51872 > 172.67.75.22.80: Flags [.], ack 377, win 63864, length 0
length 54: 10.0.2.15.51872 > 172.67.75.22.80: Flags [F.], seq 77, ack 377, win 63864, length 0
```

 - Сервер подтверждает получение ACK'ом, затем отправляет FIN-ACK.

```
length 60: 172.67.75.22.80 > 10.0.2.15.51872: Flags [.], ack 78, win 65535, length 0
length 60: 172.67.75.22.80 > 10.0.2.15.51872: Flags [F.], seq 377, ack 78, win 65535, length 0
```

 - Наш компьютер отправляет последний ACK. TCP сессия закончена.

`length 54: 10.0.2.15.51872 > 172.67.75.22.80: Flags [.], ack 378, win 63864, length 0`

- После этого система закрывает ранее открытый fd=5 и сокет.

`08:19:11 close(5)                       = 0`


