View on GitHub

Methodics of Linux Network Protocols

Practical materials for learning TCP/IP and its implementation on Linux

Продолжая разговор о прикладном уровне стека протоколов и работе systemd над ним, в данной главе будут обсуждены дополнительные сетевые службы, обеспечивающие работу приложений в сети.

Для начала повторим настройку выхода в интернет с помощью systemd:

srv

[root@srv ~]# vim /etc/systemd/network/10-inet.network  
[root@srv ~]# cat /etc/systemd/network/10-inet.network  
[Match]  
Name=eth0  
  
[Network]  
DHCP=ipv4  
IPv4Forwarding=yes  
  
[root@srv ~]# systemctl enable --now systemd-networkd  
Created symlink '/etc/systemd/system/dbus-org.freedesktop.network1.service' -> '/usr/lib/systemd/system  
/systemd-networkd.service'.  
Created symlink '/etc/systemd/system/multi-user.target.wants/systemd-networkd.service' -> '/usr/lib/sys  
temd/system/systemd-networkd.service'.  
Created symlink '/etc/systemd/system/sockets.target.wants/systemd-networkd.socket' -> '/usr/lib/systemd  
/system/systemd-networkd.socket'.  
Created symlink '/etc/systemd/system/sysinit.target.wants/systemd-network-generator.service' -> '/usr/l  
ib/systemd/system/systemd-network-generator.service'.  
Created symlink '/etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service'  
-> '/usr/lib/systemd/system/systemd-networkd-wait-online.service'.  

[root@srv ~]# networkctl    
IDX LINK TYPE     OPERATIONAL SETUP         
 1 lo   loopback carrier     unmanaged  
 2 eth0 ether    routable    configured    
 3 eth1 ether    off         unmanaged  
 4 eth2 ether    off         unmanaged  
 5 eth3 ether    off         unmanaged  
  
5 links listed.  

[root@srv ~]#

Перезапустим сервис и соберём tcpdump DHCP-обращения машины srv:

srv

[root@srv ~]# systemctl stop systemd-networkd  
Stopping 'systemd-networkd.service', but its triggering units are still active:  
systemd-networkd.socket  
[root@srv ~]# systemctl stop systemd-networkd.socket    

[root@srv ~]# tcpdump -i eth0 -w eth0.log &  # пишем все принятые данные в log-файл
[1] 1321  
[root@srv ~]# systemctl enable --now systemd-networkd  
[root@srv ~]# %  
tcpdump -i eth0 -w eth0.log  
4 packets captured  
4 packets received by filter  
0 packets dropped by kernel  

[root@srv ~]# tcpdump -r eth0.log -nnv # Читаем log-файл, не именуем порты и смотрим полную информацию
reading from file eth0.log, link-type EN10MB (Ethernet), snapshot length 262144  

16:09:08.113873 IP (tos 0xc0, ttl 64, id 0, offset 0, flags [none], proto UDP (17), length 317)  
   0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 08:00:27:41:3a:0a, length 289, xid 0xd486  
8e3e, secs 1, Flags [none]  
         Client-Ethernet-Address 08:00:27:41:3a:0a  
         Vendor-rfc1048 Extensions  
           Magic Cookie 0x63825363  
           DHCP-Message (53), length 1: Discover  
           Client-ID (61), length 19: hardware-type 255, e2:34:3f:3e:00:02:00:00:ab:11:94:36:80:2b:5c:  
22:44:89  
           Parameter-Request (55), length 11:    
             Subnet-Mask (1), Default-Gateway (3), Domain-Name-Server (6), Hostname (12)  
             Domain-Name (15), Static-Route (33), NTP (42), URL (114)  
             Unknown (120), Classless-Static-Route (121), Unknown (162)  
           MSZ (57), length 2: 1472  
           SLP-NA (80), length 0""  
           Hostname (12), length 3: "srv"  

16:09:08.114033 IP (tos 0x10, ttl 64, id 32, offset 0, flags [none], proto UDP (17), length 576)  
   10.0.2.2.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 548, xid 0xd4868e3e, Flags [none]  
         Your-IP 10.0.2.15  
         Server-IP 10.0.2.2  
         Client-Ethernet-Address 08:00:27:41:3a:0a  
         file "srv.pxe"  
         Vendor-rfc1048 Extensions  
           Magic Cookie 0x63825363  
           DHCP-Message (53), length 1: Offer  
           Server-ID (54), length 4: 10.0.2.2  
           Subnet-Mask (1), length 4: 255.255.255.0  
           Default-Gateway (3), length 4: 10.0.2.2  
           Domain-Name-Server (6), length 4: 10.0.2.3  
           Lease-Time (51), length 4: 86400  
           Hostname (12), length 4: "vbox"  

16:09:08.114321 IP (tos 0xc0, ttl 64, id 0, offset 0, flags [none], proto UDP (17), length 327)  
   0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 08:00:27:41:3a:0a, length 299, xid 0xd486  
8e3e, secs 1, Flags [none]  
         Client-Ethernet-Address 08:00:27:41:3a:0a  
         Vendor-rfc1048 Extensions  
           Magic Cookie 0x63825363  
           DHCP-Message (53), length 1: Request  
           Client-ID (61), length 19: hardware-type 255, e2:34:3f:3e:00:02:00:00:ab:11:94:36:80:2b:5c:  
22:44:89  
           Parameter-Request (55), length 11:    
             Subnet-Mask (1), Default-Gateway (3), Domain-Name-Server (6), Hostname (12)  
             Domain-Name (15), Static-Route (33), NTP (42), URL (114)  
             Unknown (120), Classless-Static-Route (121), Unknown (162)  
           MSZ (57), length 2: 1472  
           Server-ID (54), length 4: 10.0.2.2  
           Requested-IP (50), length 4: 10.0.2.15  
           Hostname (12), length 3: "srv"  

16:09:08.114438 IP (tos 0x10, ttl 64, id 33, offset 0, flags [none], proto UDP (17), length 576)  
   10.0.2.2.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 548, xid 0xd4868e3e, Flags [none]  
         Your-IP 10.0.2.15  
         Server-IP 10.0.2.2  
         Client-Ethernet-Address 08:00:27:41:3a:0a  
         file "srv.pxe"  
         Vendor-rfc1048 Extensions  
           Magic Cookie 0x63825363  
           DHCP-Message (53), length 1: ACK  
           Server-ID (54), length 4: 10.0.2.2  
           Subnet-Mask (1), length 4: 255.255.255.0  
           Default-Gateway (3), length 4: 10.0.2.2  
           Domain-Name-Server (6), length 4: 10.0.2.3  
           Lease-Time (51), length 4: 86400  
           Hostname (12), length 4: "vbox"  
[root@srv ~]#

При настройке DHCP между абонентом и DHCP-сервером присходит двухэтапный запрос данных: Абонент отправляет запрос на получение IP-адреса, DNS-сервера, пути по умолчанию и других параметров. В ответ сервер отправляет данные, а также собственные указания по именованию и обращению к абоненту (в частности, предлагает hostname для абонента). Третьим сообщением абонент делает повторный запрос, в котором указывает часть полученных данных от сервера, а также повторно запрашивает некоторые параметры, с которыми не соглашается. Повторный ответ сервера жёстко фиксирует описываемые параметры и разрешает или запрещает повторные запросы (к нашем примере сервер дважды отвергает запрос srv на собственный hostname, фиксируя имя vbox).

При настройке с помощью systemd-networkd снова возникает FrBrGeorge/MyDict/normancoffepot.png-особенность работы системы: в таблицу маршрутизации автоматически добавляются путь до DNS-сервера и маршрутизатора по умолчанию:

srv

[root@srv ~]# ip r  
default via 10.0.2.2 dev eth0 proto dhcp src 10.0.2.15 metric 1024    
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15 metric 1024    
10.0.2.2 dev eth0 proto dhcp scope link src 10.0.2.15 metric 1024    
10.0.2.3 dev eth0 proto dhcp scope link src 10.0.2.15 metric 1024    
[root@srv ~]#

Если от сервера явно приедут другие маршруты, поведение networkd не определено.

Ещё одна FrBrGeorge/MyDict/normancoffepot.png-особенность настройки из DHCP - невозможность смены hostname (или его смена строго на localhost)

DNS

Система доменных имён - одна из важнейших при работе в сети. Маршрутизация в сети ведётся с помощью сетевых протоколов (в частности, IP), при этом все обращения в большинстве случаев ведутся при помощи обращений к доменным именам. Более того, преобразование имени в IP-адрес и IP-адреса в имя производится динамически.

Система DNS представляет из себя распределённую по всей сети базу данных доменных имён абонентов и соответсвующих им адресов. Простейшим узлом этой распределённой БД выступает само устройство пользователя, хранящее некоторый набор расшифрованных доменных имён в файле /etc/hosts

srv

[root@srv ~]# cat /etc/hosts  
127.0.0.1       localhost.localdomain localhost  
::1     localhost6.localdomain localhost6  
[root@srv ~]#

Для работы системы разрешения доменных имён (name resolving) достаточно вручную внести в этот файл необходимые параметры. Такой способ работает, поскольку для службы, выполняющей разрешение доменных имён, просмотр данных из файловой системы устройства входит в указания для name resolving:

srv

[root@srv ~]# cat /etc/nsswitch.conf | grep hosts  
hosts:      files myhostname mdns4_minimal [NOTFOUND=return] dns  
#hosts:     db files nisplus nis dns  
[root@srv ~]#

Непосредственно глобальная система DNS устроена в виде каскада серверов, отвечающих за отдельные зоны доменных имён. Слово “каскад” использовано не просто так. Доменное имя устроено из множества имён зон. Каждый DNS-сервер отвечает за информацию о именах в его зоне, однако не обладает информацией о всех подзонах имени его зоны (поэтому в данном контексте и было использовано слово “каскад”, как последовательность, в нашем случае, DNS-серверов, вообще говоря, связанных лишь с соседями в цепочке обращений и ничего не знающих о последующих за соседями серверах, доменных зонах и т.д.). Разрешение доменного имени происходит путём многократных обращений к иерархической последовательности серверов для получения итогового IP-адреса.

Разберём работу DNS на примере разыменования адреса www.mit.edu:

srv

[root@srv ~]# ping www.mit.edu -c1  
PING e9566.dscb.akamaiedge.net (184.51.226.27) 56(84) bytes of data.  
64 bytes from a184-51-226-27.deploy.static.akamaitechnologies.com (184.51.226.27): icmp_seq=1 ttl=255 time=46.5 ms  
  
--- e9566.dscb.akamaiedge.net ping statistics ---  
1 packets transmitted, 1 received, 0% packet loss, time 0ms  
rtt min/avg/max/mdev = 46.455/46.455/46.455/0.000 ms  
[root@srv ~]#

Для просмотра DNS-обращений с абонента воспользуемся утилитой dig, возвращающей DNS-ответ по заданному доменному имени. Первое обращение делается на указанный для абонента DNS-сервер, от DHCP пришёл его адрес 10.0.2.3. Первым запросом выясняется IP-адрес сервера, заведующего зоной edu:

srv

[root@srv ~]# echo 'nameserver 10.0.2.3' > /etc/resolv.conf
[root@srv ~]# dig edu -t ns  
  
; <<>> DiG 9.18.35 <<>> edu -t ns  
;; global options: +cmd  
;; Got answer:  
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11231  
;; flags: qr rd ra; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 27  
  
;; OPT PSEUDOSECTION:  
; EDNS: version: 0, flags:; udp: 1232  
;; QUESTION SECTION:  
;edu.                           IN      NS  
  
;; ANSWER SECTION:  
edu.                    21442   IN      NS      h.edu-servers.net.  
edu.                    21442   IN      NS      c.edu-servers.net.  
edu.                    21442   IN      NS      g.edu-servers.net.  
edu.                    21442   IN      NS      k.edu-servers.net.  
edu.                    21442   IN      NS      l.edu-servers.net.  
edu.                    21442   IN      NS      e.edu-servers.net.  
edu.                    21442   IN      NS      b.edu-servers.net.  
edu.                    21442   IN      NS      i.edu-servers.net.  
edu.                    21442   IN      NS      d.edu-servers.net.  
edu.                    21442   IN      NS      a.edu-servers.net.  
edu.                    21442   IN      NS      j.edu-servers.net.  
edu.                    21442   IN      NS      f.edu-servers.net.  
edu.                    21442   IN      NS      m.edu-servers.net.  
  
;; ADDITIONAL SECTION:  
a.edu-servers.net.      86242   IN      A       192.5.6.30  
b.edu-servers.net.      86242   IN      A       192.33.14.30  
c.edu-servers.net.      86242   IN      A       192.26.92.30  
d.edu-servers.net.      86242   IN      A       192.31.80.30  
e.edu-servers.net.      86242   IN      A       192.12.94.30  
f.edu-servers.net.      86242   IN      A       192.35.51.30  
g.edu-servers.net.      86242   IN      A       192.42.93.30  
h.edu-servers.net.      86242   IN      A       192.54.112.30  
i.edu-servers.net.      86242   IN      A       192.43.172.30  
j.edu-servers.net.      86242   IN      A       192.48.79.30  
k.edu-servers.net.      86242   IN      A       192.52.178.30  
l.edu-servers.net.      86242   IN      A       192.41.162.30  
m.edu-servers.net.      86242   IN      A       192.55.83.30  
a.edu-servers.net.      86242   IN      AAAA    2001:503:a83e::2:30  
b.edu-servers.net.      86242   IN      AAAA    2001:503:231d::2:30  
c.edu-servers.net.      86242   IN      AAAA    2001:503:83eb::30  
d.edu-servers.net.      86242   IN      AAAA    2001:500:856e::30  
e.edu-servers.net.      86242   IN      AAAA    2001:502:1ca1::30  
f.edu-servers.net.      86242   IN      AAAA    2001:503:d414::30  
g.edu-servers.net.      86242   IN      AAAA    2001:503:eea3::30  
h.edu-servers.net.      86242   IN      AAAA    2001:502:8cc::30  
i.edu-servers.net.      86242   IN      AAAA    2001:503:39c1::30  
j.edu-servers.net.      86242   IN      AAAA    2001:502:7094::30  
k.edu-servers.net.      86242   IN      AAAA    2001:503:d2d::30  
l.edu-servers.net.      86242   IN      AAAA    2001:500:d937::30  
m.edu-servers.net.      86242   IN      AAAA    2001:501:b1f9::30  
  
;; Query time: 16 msec  
;; SERVER: 10.0.2.3#53(10.0.2.3) (UDP)  
;; WHEN: Tue Apr 29 16:22:31 UTC 2025  
;; MSG SIZE  rcvd: 827  
  
[root@srv ~]

Далее происходит обращение с одному из указанных серверов для разрешения имени mit.edu и так далее.

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

Также глобальные облачные провайдеры (google, cloudflare) предоставляют сеть DNS-серверов с единым IP-адресом, который можно использовать в качестве DNS-сервера.

Обратное преобразование адреса можно осуществлять с помощью ключа -x, при этом возвращаться может сгенерированное текстовое имя, однозначно определяющее IP-адрес:

srv

[root@srv ~]# dig ya.ru  
  
; <<>> DiG 9.18.35 <<>> ya.ru  
;; global options: +cmd  
;; Got answer:  
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6927  
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1  
  
;; OPT PSEUDOSECTION:  
; EDNS: version: 0, flags:; udp: 1232  
;; QUESTION SECTION:  
;ya.ru.                         IN      A  
  
;; ANSWER SECTION:  
ya.ru.                  297     IN      A       5.255.255.242  
ya.ru.                  297     IN      A       77.88.44.242  
ya.ru.                  297     IN      A       77.88.55.242  
  
;; Query time: 11 msec  
;; SERVER: 10.0.2.3#53(10.0.2.3) (UDP)  
;; WHEN: Tue Apr 29 17:10:30 UTC 2025  
;; MSG SIZE  rcvd: 82  
  
[root@srv ~]# dig -x 5.255.255.242  
  
; <<>> DiG 9.18.35 <<>> -x 5.255.255.242  
;; global options: +cmd  
;; Got answer:  
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10311  
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1  
  
;; OPT PSEUDOSECTION:  
; EDNS: version: 0, flags:; udp: 1232  
;; QUESTION SECTION:  
;242.255.255.5.in-addr.arpa.    IN      PTR  
  
;; ANSWER SECTION:  
242.255.255.5.in-addr.arpa. 251 IN      PTR     ya.ru.  
  
;; Query time: 56 msec  
;; SERVER: 10.0.2.3#53(10.0.2.3) (UDP)  
;; WHEN: Tue Apr 29 17:10:41 UTC 2025  
;; MSG SIZE  rcvd: 74  
  
[root@srv ~]#

DNS в SystemD

Для работы DNS в примере использовалась статическая таблица разрешения доменных имён /etc/resolv.conf. Её использование, вообще говоря, создаёт проблему при переходе между сетями (например, при переподключении между точками доступа Wi-Fi) с разными DNS-серверами. В systemd данную проблему решает использование специального сервиса systemd-resolved, срабатывающего в роли DNS-ретранслятора на 127.0.0.53:53

Сервис динамически обновляет данные в файле /run/systemd/resolve/resolv.conf. При неиспользовании статической таблицы необходимо сделать из неё символическую ссылку на данный файл на случай, если сторонние сервисы захотят что-то добавлять в таблицу

srv

[root@srv ~]# > /etc/resolv.conf    
[root@srv ~]# systemctl enable --now systemd-resolved            
Created symlink '/etc/systemd/system/dbus-org.freedesktop.resolve1.service' -> '/usr/lib/systemd/system  
/systemd-resolved.service'.  
Created symlink '/etc/systemd/system/sysinit.target.wants/systemd-resolved.service' -> '/usr/lib/system  
d/system/systemd-resolved.service'.  
[root@srv ~]# cat /run/systemd/resolve/resolv.conf    
# This is /run/systemd/resolve/resolv.conf managed by man:systemd-resolved(8).  
# Do not edit.  
#  
# This file might be symlinked as /etc/resolv.conf. If you're looking at  
# /etc/resolv.conf and seeing this text, you have followed the symlink.  
#  
# This is a dynamic resolv.conf file for connecting local clients directly to  
# all known uplink DNS servers. This file lists all configured search domains.  
#  
# Third party programs should typically not access this file directly, but only  
# through the symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a  
# different way, replace this symlink by a static file or a different symlink.  
#  
# See man:systemd-resolved.service(8) for details about the supported modes of  
# operation for /etc/resolv.conf.  
  
nameserver 10.0.2.3  
search .  
[root@srv ~]  
[root@srv ~]# ln -fs /run/systemd/resolve/resolv.conf /etc/resolv.conf    
[root@srv ~]# cat /etc/resolv.conf    
# This is /run/systemd/resolve/resolv.conf managed by man:systemd-resolved(8).  
# Do not edit.  
#  
# This file might be symlinked as /etc/resolv.conf. If you're looking at  
# /etc/resolv.conf and seeing this text, you have followed the symlink.  
#  
# This is a dynamic resolv.conf file for connecting local clients directly to  
# all known uplink DNS servers. This file lists all configured search domains.  
#  
# Third party programs should typically not access this file directly, but only  
# through the symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a  
# different way, replace this symlink by a static file or a different symlink.  
#  
# See man:systemd-resolved.service(8) for details about the supported modes of  
# operation for /etc/resolv.conf.  
  
nameserver 10.0.2.3  
search .  
[root@srv ~]# ls -l /etc/resolv.conf    
lrwxrwxrwx 1 root root 32 Apr 29 17:47 /etc/resolv.conf -> /run/systemd/resolve/resolv.conf  
[root@srv ~]#

С помощью обращения к сервису можно получать разрешения доменных имён, как глоабльных, так и локальных:

srv

[root@srv ~]# resolvectl query ww.ru  
ww.ru: 172.67.177.66                           -- link: eth0  
      104.21.56.42                            -- link: eth0  
  
-- Information acquired via protocol DNS in 65.7ms.  
-- Data is authenticated: no; Data was acquired via local or encrypted transport: no  
-- Data from: network  
[root@srv ~]# resolvectl query srv     
srv: 10.0.2.15                                 -- link: eth0  
  
-- Information acquired via protocol DNS in 1.0ms.  
-- Data is authenticated: yes; Data was acquired via local or encrypted transport: yes  
-- Data from: synthetic  
[root@srv ~]#

systemd-resolved изначально предназначен для отслеживания пространств имён. однако его можно настроить в качестве DNS-сервера. Для этого в настройках /etc/systemd/resolved.conf необходимо указать работу сервиса на IP 0.0.0.0 (исходник, который нужно скопировать для правок, лежит в /usr/lib/systemd/resolved.conf):

srv

[root@srv ~]# cat /usr/lib/systemd/resolved.conf    
#  This file is part of systemd.  
#  
#  systemd is free software; you can redistribute it and/or modify it under the  
#  terms of the GNU Lesser General Public License as published by the Free  
#  Software Foundation; either version 2.1 of the License, or (at your option)  
#  any later version.  
#  
# Entries in this file show the compile time defaults. Local configuration  
# should be created by either modifying this file (or a copy of it placed in  
# /etc/ if the original file is shipped in /usr/), or by creating "drop-ins" in  
# the /etc/systemd/resolved.conf.d/ directory. The latter is generally  
# recommended. Defaults can be restored by simply deleting the main  
# configuration file and all drop-ins located in /etc/.  
#  
# Use 'systemd-analyze cat-config systemd/resolved.conf' to display the full config.  
#  
# See resolved.conf(5) for details.  
  
[Resolve]  
# Some examples of DNS servers which may be used for DNS= and FallbackDNS=:  
# Cloudflare: 1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com 2606:4700:4700::1111#cloudflare-dns  
.com 2606:4700:4700::1001#cloudflare-dns.com  
# Google:     8.8.8.8#dns.google 8.8.4.4#dns.google 2001:4860:4860::8888#dns.google 2001:4860:4860::884  
4#dns.google  
# Quad9:      9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net 2620:fe::fe#dns.quad9.net 2620:fe::9#  
dns.quad9.net  
#DNS=  
#FallbackDNS=  
#Domains=  
#DNSSEC=no  
#DNSOverTLS=no  
#MulticastDNS=no  
#LLMNR=yes  
#Cache=yes  
#CacheFromLocalhost=no  
#DNSStubListener=yes  
#DNSStubListenerExtra=  
#ReadEtcHosts=yes  
#ResolveUnicastSingleLabel=no  
#StaleRetentionSec=0  

[root@srv ~]# cp /usr/lib/systemd/resolved.conf /etc/systemd/resolved.conf  

[root@srv ~]# cat /etc/systemd/resolved.conf | grep DNSStub  
#DNSStubListener=yes  
#DNSStubListenerExtra=  

[root@srv ~]# vim /etc/systemd/resolved.conf                  

[root@srv ~]# cat /etc/systemd/resolved.conf | grep DNSStub  
DNSStubListener=no  
DNSStubListenerExtra=0.0.0.0  
[root@srv ~]#
[root@srv ~]# systemctl restart systemd-resolved.service    
[root@srv ~]# ss -ltp  
State  Recv-Q Send-Q Local Address:Port    Peer Address:PortProcess                                       
LISTEN 0      4096         0.0.0.0:hostmon      0.0.0.0:*    users:(("systemd-resolve",pid=2692,fd=12))  
LISTEN 0      128          0.0.0.0:ssh          0.0.0.0:*    users:(("sshd",pid=667,fd=3))                
LISTEN 0      4096         0.0.0.0:domain       0.0.0.0:*    users:(("systemd-resolve",pid=2692,fd=18))  
[root@srv ~]# dig ww.ru @localhost  
  
; <<>> DiG 9.18.35 <<>> ww.ru @localhost  
;; global options: +cmd  
;; Got answer:  
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6958  
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1  
  
;; OPT PSEUDOSECTION:  
; EDNS: version: 0, flags:; udp: 1232  
;; QUESTION SECTION:  
;ww.ru.                         IN      A  
  
;; ANSWER SECTION:  
ww.ru.                  300     IN      A       172.67.177.66  
ww.ru.                  300     IN      A       104.21.56.42  
  
;; Query time: 58 msec  
;; SERVER: 127.0.0.1#53(localhost) (UDP)  
;; WHEN: Tue Apr 29 19:03:43 UTC 2025  
;; MSG SIZE  rcvd: 66  
  
[root@srv ~]#

DHCP

Самонастройка IPv4 путём обмена сообщениями в сети с информацией о установленных данных существовала в виде отдельного протокола LinkLocal, и systemd-networkd даже поддерживает работу с ним, однако данный способ вызывал множество проблем при настройке в больших сетях.

Протокол DHCP работает по принципу обращений к DHCP-серверам для получения данных аналогично получению разрешений доменных имён в DNS. Также как и в DNS, для DHCP существуют глобальные серверы, и также с помощью systemd возможно развернуть локальный DHCP-сервер

Для этого опишем ещё один конфигурационный systemd-файл для intnet и добавим туда описание DHCP сервера:

srv

[root@srv ~]# vim /etc/systemd/network/50-intnet.network  
[root@srv ~]# cat /etc/systemd/network/50-intnet.network  
[Match]  
Name=eth1  
  
[Network]  
Address=10.9.0.25/24  
DHCPServer=yes  
  
[DHCPServer]  
PoolOffset=100  
PoolSize=10  
DNS=10.9.0.25  
  
[root@srv ~]#

В параметрах сети указывается активация DHCP-службы, в её параметрах указываются начальный адрес выдаваемых адресов (все адреса будут считаться от 10.9.0.100/24), количество генерируемых адресов (вообще говоря, это число не обязано совпадать или быть больше числа абонентов; например, сравнительно небольшим количеством IP можно будет обслужить большое число пользователей, которые непостоянно выходят в сеть), также здесь может быть указан DNS-сервер

srv

[root@srv ~]# networkctl reload    
[root@srv ~]# networkctl    
IDX LINK TYPE     OPERATIONAL SETUP        
 1 lo   loopback carrier     unmanaged  
 2 eth0 ether    routable    configured  
 3 eth1 ether    routable    configured  
 4 eth2 ether    off         unmanaged  
 5 eth3 ether    off         unmanaged  
  
5 links listed.  
[root@srv ~]#

Сервис обновил параметры, теперь настроим клиентскую машину. Для этого при описании параметров systemd необходимо всего лишь указать получение параметров через DHCP и включить все сервисы:

client

[root@client ~]# vim /etc/systemd/network/50-intnet.network  
[root@client ~]# cat /etc/systemd/network/50-intnet.network  
[Match]  
Name=eth1  
  
[Network]  
DHCP=ipv4  
  
[root@client ~]# systemctl enable --now systemd-networkd  
<...>
[root@client ~]# systemctl enable --now systemd-resolved     
<...>
[root@client ~]# ln -fs /run/systemd/resolve/resolv.conf /etc/resolv.conf    

Проверим, что для клиента доступны DNS-сервер и настроены маршруты и IP:

client

[root@client ~]# cat /etc/resolv.conf    
<...>

nameserver 10.9.0.25  
search .  

[root@client ~]# ip r  
default via 10.9.0.25 dev eth1 proto dhcp src 10.9.0.109 metric 1024    
10.9.0.0/24 dev eth1 proto kernel scope link src 10.9.0.109 metric 1024    
10.9.0.25 dev eth1 proto dhcp scope link src 10.9.0.109 metric 1024    

Всё корректно настроено, однако при обращении в интернет происходит сбой: DNS отрабатывает корректно (поскольку ошибки по разрешению имени не появляется), а выхода в сеть нет:

client

[root@client ~]# ping -c3 ww.ru  
PING ww.ru (104.21.56.42) 56(84) bytes of data.  
  
--- ww.ru ping statistics ---  
3 packets transmitted, 0 received, 100% packet loss, time 2026ms  
  
[root@client ~]#    

Это связано с отсутствием настройки NAT на srv. Здесь возникает ещё одна FrBrGeorge/MyDict/normancoffepot.png-особенность настройки - исходящий NAT управляется на внутренних интерфейсах systemd. Решение связано с тем, что при такой настройке можно выделять потоки, которые необходимо будет транслировать.

Настройка NAT подключается дополнительным параметром в секции [Network]. При этом настройка systemd NAT связана не с утилитой iptables, а с nftables, и указываемый параметр разворачивается в довольно крупную структуру при обработке:

srv

[root@srv ~]# vim /etc/systemd/network/50-intnet.network    
[root@srv ~]# cat /etc/systemd/network/50-intnet.network    
[Match]  
Name=eth1  
  
[Network]  
Address=10.9.0.25/24  
DHCPServer=yes  
IPMasquerade=ipv4  
  
[DHCPServer]  
PoolOffset=100  
PoolSize=10  
DNS=10.9.0.25  
  
[root@srv ~]# networkctl reload    

[root@srv ~]# iptables-save  # Ничего
[root@srv ~]# nft list ruleset  # Зато тут...
table ip io.systemd.nat {  
       set masq_saddr {  
               type ipv4_addr  
               flags interval  
               elements = { 10.9.0.0/24 }  
       }  
  
       map map_port_ipport {  
               type inet_proto . inet_service : ipv4_addr . inet_service  
       }  
  
       chain prerouting {  
               type nat hook prerouting priority dstnat + 1; policy accept;  
               fib daddr type local dnat ip to meta l4proto . th dport map @map_port_ipport  
       }  
  
       chain output {  
               type nat hook output priority dstnat + 1; policy accept;  
               ip daddr != 127.0.0.0/8 oif "lo" dnat ip to meta l4proto . th dport map @map_port_ippor  
t  
       }  
  
       chain postrouting {  
               type nat hook postrouting priority srcnat + 1; policy accept;  
               ip saddr @masq_saddr masquerade  
       }  
}  
[root@srv ~]#

client

[root@client ~]# ping -c3 ww.ru  
PING ww.ru (172.67.177.66) 56(84) bytes of data.  
64 bytes from 172.67.177.66: icmp_seq=1 ttl=254 time=183 ms  
64 bytes from 172.67.177.66: icmp_seq=2 ttl=254 time=37.7 ms  
64 bytes from 172.67.177.66: icmp_seq=3 ttl=254 time=204 ms  
  
--- ww.ru ping statistics ---  
3 packets transmitted, 3 received, 0% packet loss, time 2003ms  
rtt min/avg/max/mdev = 37.715/141.704/204.154/74.025 ms  
[root@client ~]#    

Multicast DNS

Говоря об автонастройке сети, нельзя не упомянуть про Zeroconf - набор технологий, обеспечивающих полную автоматическую настройку сети. Для работы используется протокол Multicast DNS, обеспечивающий произвольное преобразование имён. На его основе осуществляется работа по поиску доступных служб. Для этого используется специальный тип записей mDNS-таблицы srv (не путать с именем нашей виртуальной машины; это не связанные параметры)

srv

[root@srv ~]# dig -t srv _imaps._tcp.gmail.com  
#Расшифровка: поиск службы, использующей протокол imaps с TCP-соединением у домена gmail.com #  
; <<>> DiG 9.18.35 <<>> -t srv _imaps._tcp.gmail.com  
;; global options: +cmd  
;; Got answer:  
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33117  
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1  
  
;; OPT PSEUDOSECTION:  
; EDNS: version: 0, flags:; udp: 1232  
;; QUESTION SECTION:  
;_imaps._tcp.gmail.com.         IN      SRV  
  
;; ANSWER SECTION:  
_imaps._tcp.gmail.com.  86400   IN      SRV     5 0 993 imap.gmail.com.  
#Расшифровка результата: на порту 993 указанный протокол используется сервисом с доменным именем imap.gmail.com #
;; Query time: 390 msec  
;; SERVER: 10.0.2.3#53(10.0.2.3) (UDP)  
;; WHEN: Wed Apr 30 00:01:03 UTC 2025  
;; MSG SIZE  rcvd: 84  
  
[root@srv ~]# 

С помощью systemd можно настроить все самоанонсируемые сервисы. Они будут отмечены в системе специальным расширением .local, и к ним будет доступно такое же обращение через mDNS. Для настройки службы необходимо описать её конфигурацию, а также подключить поддержку MulticastDNS для resolved и networkd

srv

# Описание параметров службы
[root@srv ~]# mkdir /etc/systemd/dnssd  
[root@srv ~]# vim /etc/systemd/dnssd/ssh.dnssd  
[root@srv ~]# cat /etc/systemd/dnssd/ssh.dnssd  
[Service]  
Name=%H  
Type=_ssh._tcp  
Port=22  

# Подключение mDNS в resolved
[root@srv ~]# vim /etc/systemd/resolved.conf    
[root@srv ~]# cat /etc/systemd/resolved.conf | grep MulticastDNS  
MulticastDNS=yes  

# Подключение mDNS в networkd
[root@srv ~]# vim /etc/systemd/network/50-intnet.network    
[root@srv ~]# cat /etc/systemd/network/50-intnet.network    
[Match]  
Name=eth1  
  
[Network]  
Address=10.9.0.25/24  
DHCPServer=yes  
IPMasquerade=ipv4  
MulticastDNS=yes  
  
[DHCPServer]  
PoolOffset=100  
PoolSize=10  
DNS=10.9.0.25  

После перезагрузки сервисов служба будет анонсирована в таблице разрешённых имён mDNS:

srv

[root@srv ~]# systemctl restart systemd-resolved.service    
[root@srv ~]# systemctl restart systemd-networkd    

[root@srv ~]# resolvectl service srv._ssh._tcp.local  
srv._ssh._tcp.local: srv.local:22 [priority=0, weight=0]  
                    10.9.0.25                              -- link: eth1  
                    (srv/_ssh._tcp/local)  
  
-- Information acquired via protocol mDNS/IPv4 in 1.5ms.  
-- Data is authenticated: yes; Data was acquired via local or encrypted transport: yes  
-- Data from: zone  
[root@srv ~]#

Ещё один способ автонастройки сети с помощью mDNS- использование сервиса Avahi. Он автоматически осуществляет поиск доступных служб и сервисов с помощью mDNS

client

[root@client ~]# systemctl enable --now avahi-daemon     
Synchronizing state of avahi-daemon.service with SysV service script with /usr/lib/systemd/systemd-sysv  
-install.  
Executing: /usr/lib/systemd/systemd-sysv-install enable avahi-daemon  
Created symlink '/etc/systemd/system/dbus-org.freedesktop.Avahi.service' -> '/usr/lib/systemd/system/av  
ahi-daemon.service'.  
Created symlink '/etc/systemd/system/multi-user.target.wants/avahi-daemon.service' -> '/usr/lib/systemd  
/system/avahi-daemon.service'.  
Created symlink '/etc/systemd/system/sockets.target.wants/avahi-daemon.socket' -> '/usr/lib/systemd/sys  
tem/avahi-daemon.socket'.  

При поиске служб осуществляется mDNS-запрос, на который абонент-владелец службы отвечает с указанием параметров службы:

srv

[root@srv ~]# tcpdump -i eth1  
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode  
listening on eth1, link-type EN10MB (Ethernet), snapshot length 262144 bytes  

client

[root@client ~]# avahi-browse -alt  
+   eth1 IPv4 srv                                           SSH Remote Terminal  local  

srv

[root@srv ~]# tcpdump -i eth1  
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode  
listening on eth1, link-type EN10MB (Ethernet), snapshot length 262144 bytes  
00:12:45.273313 IP 10.9.0.109.5353 > mdns.mcast.net.5353: 0 [3a] [2q] PTR (QM)? _services._dns-sd._udp.  
local. PTR (QM)? _ssh._tcp.local. (115)  
00:12:45.275109 IP srv.5353 > mdns.mcast.net.5353: 0*- [0q] 2/0/0 PTR _ssh._tcp.local., PTR srv._ssh._t  
cp.local. (82)  
  
2 packets captured  
2 packets received by filter  
0 packets dropped by kernel  
[root@srv ~]#

Домашняя работа

  1. Воспроизвести на двух машинах — srv и client — следующие настройки из лекции:
    • «Выход в интернет» с NAT-ом и работающим DNS на srv
    • DHCP сервер на srv
    • Получение настроек по DHCP на client
    • «Работающий интернет» на client
    • Разрешение имён srv.local и client.local при помощи avahi-daemon
    • Все сетевые настройки делаются перманентными с помощью systemd.networkd и активацией соответствующих сервисов
    • Важно: Настраивать resolved в качестве промежуточного DNS не надо:
      • Достаточно в настройке [DHCPServer] указать EmitDNS = yes, и ко всем клиентам будет приезжать внешний DNS
  2. Предварительно настроить srv и client (процесс настройки в отчёт не входит)

  3. После настройки и проверки работоспособности client склонировать его под именем stranger
    • Не забудьте поменять порт для проброса консоли COM→TCP, а то не запустится
    • Запустите stranger и обнулите в нём /etc/machine-id (иначе он получит тот же IP, что и client): [root@stranger ~]# cat /dev/null > /etc/machine-id
    • Запустите на stranger сценарий sethostname srtanger (в этом задании — не только для удобства, а ещё и для анонса по avahi)
    • Перезагрузите stranger
    • Больше ничего на stranger менять не разрешается
  4. Отчёт:
    1. report 9 srv:
      • cat /etc/hosts — этот файл менять не надо
      • grep "" /etc/systemd/network/* — настройки сети
      • cat /etc/resolv.conf — настройки резолвера (по идее — должен смотреть на ваш внешний DNS, но не обязательно)
      • resolvectl — настройки resolved
      • ping -c3 client.local — доступность client по mDNS
      • ping -c3 stranger.local — доступность srv по mDNS
      • ping -c3 ya.ru — доступность ya.ru
    2. report 9 client и report 9 stranger (почти одинаковые)
      • cat /etc/hosts — этот файл менять не надо
      • grep "" /etc/systemd/network/* — настройки сети
      • resolvectl — настройки resolved
      • ping -c3 srv.local — доступность srv по mDNS
      • ping -c3 client.local — доступность srv по mDNS
      • ping -c3 stranger.local — доступность srv по mDNS
      • ping -c3 ya.ru — доступность ya.ru
  5. Три отчёта (названия сохранить, должно быть: report.09.srv, report.09.client и report.09.stranger) переслать одним письмом в качестве приложений на uneexlectures@cs.msu.ru
    • В теме письма должно встречаться слово LinuxNetwork2027