Try   HackMD

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

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

  • Меня зовут Вахутинский Андрей
  • Я работаю в компании "ИНТЕКО", которая является одним из девелоперов в Москве, Санкт-Петербурге и Ростове-на-Дону, заместителем начальника ИТ отдела.
  • Не смотря на название должности, в основном выполняю функции сетевого инженера, VoIP специалиста, немного - системного администратора Windows и Linux. И совсем немного административной работы.
  • Какой стек технологий использую:
    • в моём случае это больше стек TCP/IP
      Image Not Showing Possible Reasons
      • The image file may be corrupted
      • The server hosting the image is unavailable
      • The image path is incorrect
      • The image format is not supported
      Learn More →
    • 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