× К оглавлению На главную Об авторе

   Дата и время публикации:

Проблемы и решение

1. Суть проблемы

Ранее, когда поднимал сетевой мост между центральным (физическим) узлом гипервизора и гостевой ВМ, особо не задумывался, что у режима nat, есть режим коммутации пакетов путем их фильтрации (Package filtering) и ретрансляции по адресу и порту(Network Address Translation) .

Особенно, как показано на рисунке 1.1, если гостевая виртуальная машина выполняет роль сервера, на котором запущены службы DNS, SSH, POP3, SMTP, IMAP, сборщика системных журналов и сообщений и т.д.

Дамп 1.1

Рисунок 1.1

Поэтому для перенаправления портов вышеперечисленных служб, воспользуемся ретрансляцией входящих и исходящих соединений по IP-адресам и портам, реализуемой с помощью программного межсетевого экрана iptables, о котором рассказывал ранее в обзорной статье, как использовать политику FORWARD и правила NAT

Теперь применим полученные теоретические знания в реальной схеме межсетевого взаимодействия, показанной на рисунке 1.1 и состоящей из двух узлов виртуальных машин (гостевых ОС) и одного связующего их – центрального узла гипервизора, где:

2. Решение

2.1 Сканирование на открытые порты

В ходе решения схемы межсетевого взаимодействия, показанной на рисунке 1.1, применял поверхностное тестирование на открытые (tcp-, udp-) порты гостевых ОС, которые запускал с центрального узла гипервизора с помощью программного сетевого сканера, утилиты nmap, как показано в дампе 2.1.1

Дамп 2.1.1

sudo nmap -A -T4 --max-retries 100  --min-parallelism 100 --max-parallelism 900  --min-hostgroup 1 --max-hostgroup 1 -sU -sT  192.168.2.10
...
Starting Nmap 7.80 ( https://nmap.org ) at 2021-10-29 18:21 MSK
Nmap scan report for 192.168.2.10
Host is up (0.00045s latency).
Not shown: 1986 closed ports
PORT     STATE         SERVICE  VERSION
22/tcp   open          ssh      OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey: 
|   2048 ce:09:0e:a7:23:91:fc:44:c7:e9:54:55:5c:d1:e6:45 (RSA)
|   256 61:a2:60:9c:a2:43:73:ae:76:1d:8f:c6:b6:4c:01:61 (ECDSA)
|_  256 44:ff:93:bb:89:0e:99:50:48:a4:6f:21:bb:0b:d9:91 (ED25519)
25/tcp   open          smtp     Postfix smtpd
|_smtp-commands: slpnet.tld, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, SMTPUTF8, CHUNKING, 
| ssl-cert: Subject: commonName=debian10-uni
| Subject Alternative Name: DNS:debian10-uni
| Not valid before: 2021-04-17T10:36:40
|_Not valid after:  2031-04-15T10:36:40
|_ssl-date: TLS randomness does not represent time
53/tcp   open          domain   ISC BIND 9.11.5-P4-5.1+deb10u5 (Debian Linux)
110/tcp  open          pop3     Courier pop3d
|_pop3-capabilities: USER TOP PIPELINING IMPLEMENTATION(Courier Mail Server) UTF8(USER) STLS UIDL LOGIN-DELAY(10)
| ssl-cert: Subject: commonName=localhost/organizationName=Courier Mail Server/stateOrProvinceName=NY/countryName=US
| Subject Alternative Name: email:postmaster@example.com
| Not valid before: 2021-04-19T16:11:49
|_Not valid after:  2022-04-19T16:11:49
|_ssl-date: TLS randomness does not represent time
143/tcp  open          imap     Courier Imapd (released 2018)
|_imap-capabilities: IMAP4rev1 UIDPLUS QUOTA IDLE UTF8=ACCEPTA0001 CAPABILITY ENABLE SORT NAMESPACE OK ACL2=UNION STARTTLS completed THREAD=REFERENCES CHILDREN THREAD=ORDEREDSUBJECT ACL
| ssl-cert: Subject: commonName=localhost/organizationName=Courier Mail Server/stateOrProvinceName=NY/countryName=US
| Subject Alternative Name: email:postmaster@example.com
| Not valid before: 2021-04-19T16:11:36
|_Not valid after:  2022-04-19T16:11:36
|_ssl-date: TLS randomness does not represent time
514/tcp  open          shell?
993/tcp  open          ssl/imap Courier Imapd (released 2018)
|_imap-capabilities: IMAP4rev1 UIDPLUS QUOTA IDLE AUTH=PLAIN UTF8=ACCEPTA0001 CAPABILITY ENABLE SORT NAMESPACE OK ACL completed THREAD=REFERENCES CHILDREN THREAD=ORDEREDSUBJECT ACL2=UNION
| ssl-cert: Subject: commonName=localhost/organizationName=Courier Mail Server/stateOrProvinceName=NY/countryName=US
| Subject Alternative Name: email:postmaster@example.com
| Not valid before: 2021-04-19T16:11:36
|_Not valid after:  2022-04-19T16:11:36
|_ssl-date: TLS randomness does not represent time
995/tcp  open          ssl/pop3 Courier pop3d
|_pop3-capabilities: USER TOP PIPELINING IMPLEMENTATION(Courier Mail Server) UTF8(USER) UIDL LOGIN-DELAY(10)
| ssl-cert: Subject: commonName=localhost/organizationName=Courier Mail Server/stateOrProvinceName=NY/countryName=US
| Subject Alternative Name: email:postmaster@example.com
| Not valid before: 2021-04-19T16:11:49
|_Not valid after:  2022-04-19T16:11:49
2525/tcp open          smtp     Postfix smtpd
|_smtp-commands: slpnet.tld, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, SMTPUTF8, CHUNKING, 
| ssl-cert: Subject: commonName=debian10-uni
| Subject Alternative Name: DNS:debian10-uni
| Not valid before: 2021-04-17T10:36:40
|_Not valid after:  2031-04-15T10:36:40
|_ssl-date: TLS randomness does not represent time
53/udp   open          domain   ISC BIND 9.11.5-P4-5.1+deb10u5 (Debian Linux)
| dns-nsid: 
|_  bind.version: 9.11.5-P4-5.1+deb10u5-Debian
68/udp   open|filtered dhcpc
69/udp   open|filtered tftp
514/udp  open|filtered syslog
5353/udp open          mdns     DNS-based service discovery
| dns-service-discovery: 
|   9843/tcp webdav
|_    Address=192.168.2.10 fe80::5054:ff:fe8b:7048
MAC Address: 52:54:00:8B:70:48 (QEMU virtual NIC)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.80%E=4%D=10/29%OT=22%CT=1%CU=2%PV=Y%DS=1%DC=D%G=Y%M=525400%TM=6
OS:17C1681%P=x86_64-pc-linux-gnu)SEQ(SP=104%GCD=1%ISR=108%TI=Z%CI=Z%II=I%TS
OS:=A)OPS(O1=M5B4ST11NW7%O2=M5B4ST11NW7%O3=M5B4NNT11NW7%O4=M5B4ST11NW7%O5=M
OS:5B4ST11NW7%O6=M5B4ST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE
OS:88)ECN(R=Y%DF=Y%T=40%W=FAF0%O=M5B4NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=
OS:S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q
OS:=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A
OS:%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y
OS:%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T
OS:=40%CD=S)

Network Distance: 1 hop
Service Info: Host:  slpnet.tld; OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE
HOP RTT     ADDRESS
1   0.45 ms 192.168.2.10

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 1315.13 seconds

Как показано в дампе 2.1.1, сканирование утилитой nmap скорее всего будет поверхностным, в случае применения опций -A, -T5, -sU и -sT

Опция -T5 указывает применять временной шаблона тестирования, устанавливающий временные характеристики тестирования udp- и tcp- соединений, которые можно замедлить или наоборот ускорить двигаясь от -T0 до и включая -T5

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

Опция -T4 не допускает превышение задержки динамического тестирования не выше 10 ms для портов TCP , в то время как опция -T5 устанавливает это значение к 5 ms. Вместе с опциями временных шаблонов можно использовать опции детализированного контроля [3.2].

Начиная с опции -T3 включается распараллеливание [3.3], которое ускоряет процесс тестирования портов и обнаружения узлов. Управлять этим процессом можно через опции --min-parallelism и --max-parallelism , а так же --min-hostgroup, --max-hostgroup . Первые две опции устанавливает минимальную и максимальную границу количества тестовых проходов, которым подвергается каждый узел из данной группы узлов, дипапазон которых указан в последних двух опциях. [3.4] Соответственно, в моем случае максимальные граничные значения обоих диапазонов были установлены равными диапазону 100 проб-тесирования (--max-parallelism) к одному узлу (--max-hostgroup).

Кроме того, были установлены опции тестирования udp- (-sU) и tcp- ( -sT) соединений, а также опция -A , которая заставляет nmap проводить проверки в полном объеме, такие как обнаружение типа и версии операционной системы, сканирования служб и версий (version scanning), трассировку маршрутизации и так называемого сканирования на основе сценария (script scanning), которое осуществляется одновременно со сканированием портов. С помощью опции --max-retries 10 установил приемлемое значение, в моем случае, для парирования предупреждения "giving up on port because retransmission cap hit (2)" [3.2].

Таким образом, после тестирования мной были обнаружены следующие открытые порты гостевой ОС, видные с центрального узла и которые перечислены в дампе 2.1.2

Дамп 2.1.2

22/tcp   open          ssh      OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
...
25/tcp   open          smtp     Postfix smtpd
...
53/tcp   open          domain   ISC BIND 9.11.5-P4-5.1+deb10u5 (Debian Linux)
110/tcp  open          pop3     Courier pop3d
…
143/tcp  open          imap     Courier Imapd (released 2018)
...
514/tcp  open          shell?
...
993/tcp  open          ssl/imap Courier Imapd (released 2018)
…
995/tcp  open          ssl/pop3 Courier pop3d
...
2525/tcp open          smtp     Postfix smtpd
...
53/udp   open          domain   ISC BIND 9.11.5-P4-5.1+deb10u5 (Debian Linux)
...
9843/tcp webdav
...
68/udp   open|filtered dhcpc
...
69/udp   open|filtered tftp
...
514/udp  open|filtered syslog
...
5353/udp open          mdns     DNS-based service discovery

Где, из всех открытых портов для клиента 192.168.2.10/32, согласно рисунку 1.1, должны быть перенаправлены порты: исходящие – в диапазоне 32678-65535 (ответные пакеты), входящие – в диапазоне 1-32000 портов (пакеты на запрос соединения )

Таким образом, из полученного распределения портов на узле ВМ "ОС Debain-11" можно заключить, что получаемые на входе шлюза virbr1 сообщения от узла ВМ "ОС Yocto/poky", будут содержат запросы к портам 22/tcp (SSH), 69/tcp (TFTP), 53/tcp (BIND) и других интересующих служб, запросы на соединения к которым будут приходит от узла ВМ "ОС Yocto/poky" в диапазоне портов 32001 до 32767. Поэтому порты во входящих сообщений на входе шлюза virbr1 должны быть перенаправлены на порты в диапазоне 1-32767 на узел ВМ "ОС Debain-11". При этом отправляемые обратно с выхода шлюза virbr1 сообщения должны передаваться на эмфиральные порты в диапазоне 32768-65535

2.1 Настройка nat в Gnome-boxes

Производил её таким же образом, как это делал в virt-manager во время создания мостовой сети для организации сетевого доступа к гостевой ОС "Debian-10". Но, с одним изменением, что в XML-настройках подсети 192.168.2.0/24 задействуются элементы <nat> и <ports>, с помощью которых устанавливается перенаправление трафика на эмфиральные порты в диапазоне 32768-65535 в virt-manager"ОС Yocto/poky" с использованием политик SNAT или MASQUERADE межсетевого экрана в iptables / netfilter . При этом, доступ к перечисленным на рисунке 1.1 портам из диапазона 1-32000 узла ВМ "ОС Debian-10" останется открытым, т.к. никакие ограничений к ним не применяются.

Для включения режима ретрансляции адреса указал значение "nat" в атрибуте mode элемента <forward> в сетевых настройках для подсети c ip:192.168.2.0/24 в XML-файле libvirt-slpnet.xml, как показано в листинге 2.2.1

Дамп 2.2.1

<network>
  <name>slpnet.tld</name>
  <uuid>52008539-dd34-4b5f-95f5-c9e8591e57c8</uuid>
  <forward mode='nat' dev='tap0'>
     <nat>
        <port start='32768' end='65535'/>
     </nat>
     <interface dev='tap0'/>
  </forward>
  <bridge name='virbr1' stp='on' delay='0'/>
  <mac address='52:54:00:77:1d:d5'/>
  <domain name='slpnet.tld'/>
  <dns>
    <forwarder domain='slpnet.tld' addr='192.168.2.10'/>
    <host ip='192.168.2.10'>
      <hostname>slpnet.tld</hostname>
      <hostname>mail.slpnet.tld</hostname>
    </host>
  </dns>
  <ip address='192.168.2.2' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.2.100' end='192.168.2.254'/>
      <host mac='52:54:00:8b:70:48' name='mail.slpnet.tld' ip='192.168.2.10'/>
    </dhcp>
  </ip>
</network>

Как показано в листинге 2.2.1, элемент <forward> отвечает за маршрутизацию пакетов из физической сети и обратно в режиме ретрансляции сетевого адреса, который устанавливается атрибутом mode='nat'. Дополнительно, также указывается сетевой интерфейс tap0, сопрягаемый эмулятором Qemu/KVM, на который будет производится продвижения пакетов с использованием ретрансляции по адресу.

Поэтому в нем указал два элемента <nat> и <interface>, первый отвечает за диапазоны портов, элемента <port>, и адресов, элемента <address>, на которые производится перенаправление трафика, а второй явно указывает сетевой интерфейс, участвующий в данном перенаправлении [3.9].

Диапазон перенаправляемых, так называемых, эмфиральных портов на узел ВМ "ОС Yocto/poky" с "ip: 192.168.7.2", диапазон которых начинается с 32768 и заканчивается 65535 портом и установлен во многих версиях ядра Linux [3.8]. При этом первые 768 портов, начиная с 32001 следует отдать службам ssh, tftp, bind9, smtp, pop и т.д., поэтому в элементе <port> указано перенаправлять все исходящие пакеты исходящие пакеты, передаваемые по эмфиральным портам (32768-65535), от узла подсети с ip:192.168.2.0/254 к узлам подсети ip:192.168.7.0/24 . При этом, как увидим ниже [2.5], порты остаются неизменными, а для указанного диапазона портов будет происходит лишь замена адреса при передачи пакетов получателя в обратном направлении к отправителю, но никак не самих портов.

В конечном итоге в таблицах mangle, filter и nat будут установлены правила программному межсетевому экрану (iptables) в определяемых libvirt цепочках, после создания сети slpnet.tld , процесс создания которой показан в дампе 2.2.2

Дамп 2.2.2

~$ sudo virsh
[sudo] пароль для user:                                                         
Добро пожаловать в virsh — интерактивный терминал виртуализации.                
                                                                                
Введите  «help» для получения справки по командам                               
         «quit», чтобы завершить работу и выйти.                                
                                                                                
virsh # net-create /home/user/libvirt-slpnet.xml
Сеть slpnet.tld создана из /home/user/libvirt-slpnet.xml
                                                                                
virsh #

2.3 Реализация режима роутера с помощью пакетной фильтрации в (iptables / netfilter) в IPTables

Обеспечивается за счет использования таблиц mangle, filter и nat, где будут установлены правила программному межсетевому экрану (iptables / netfilter) для организации перенаправления трафика, как показано на рисунке 2.3.1

Рисунок 2.3.1

Как показано на рисунке 2.3.1 существует два режима пакетной фильтрации (Packet filtering) и продвижение пакетов (Packet forwarding) в подсистеме ядра netfilter, когда задействуются правила фильтрации и перенаправления (коммутации) за счет изменения сетевого адреса или порта для каждого принимаемого или отправляемого пакета на уровне ядра. При этом таблица маршрутизации остается нетронутой и используется для перенаправления с "поправленным" заголовком пакетов на уровне ядра подсистемой netfilter.

Поэтому пакетная фильтрация (Packet filtering) является нечто большим чем просто продвижение пакетов (Packet forwarding), потому что последний использует лишь таблицу маршрутизиции, чтобы перенаправить пакет на тот узел-назначения куда нужно отправителю . В то время как пакетная фильтрация использует перечень правил позволяющий ей решать, на уровне ядра, что делать с каждым входящим (input) или выходящим (output) пакетом, а так же отфильтровывать пакеты с использованием политики FORWARD [3.10].

Соответственно, подсистема ядра netfilter настраиваетcя утилитой iptables в основном для фильтрации каждого пакета, проходящего через цепочки INPUT, FORWARD и OUTPUT таблицы filter на уровне сокета процесса. Например, как показано на рисунке 2.3.1, при обращении клиента (ВМ "ОС Yocto/poky") к их слушающему сокету, открытого на одном из портов 69 и 25, 2525 служб tftpd-hpa и postfix на сервере (ВМ "ОС Debian-10"), с помощью пакетной фильтрации можно контролировать какой именно узел отправитель (source host) создает соединение для передачи запроса к узлу отправителя (destionation source) и/или порт службы (service port). Так же как, с помощью неё можно контролировать куда обратно передавать запрашиваемые данные отправителем на один или несколько эмфиральных портов узла получателя.

Для этого Libvirt задействует цепочки LIBVIRT-{FWO,FWX,FWI, INP, OUT}, которые создаются сервером libvirtd в ходе реализации правил службы ядра Linux межсетевого экрана netfilter и задаются через ее интерфейс – утилиты iptables [3.11]

Приватные цепочки LIBVIRT-{FWO,FWX,FWI, INP, OUT} были введены в libvirt 5.1.0 из-за снижения производительности в следствии постоянной перезагрузки модуля ядра conntrack и последующего запуска им процедуры отслеживания и обработки соединений. Поэтому модуль conntrack не будет загружен до тех пор пока не будет поднята подсеть, как было показано ранее в дампе 2.2.2 для slpnet.tld, и когда libvirt не добавит правила во встраиваемые цепочки LIBVIRT-{FWO,FWX,FWI, INP, OUT} [3.12].

В таблицу filter цепочки LIBVIRT-{FWO,FWX,FWI, INP, OUT} встраиваются цепочки FORWARD, INPUT, OUTPUT таблицы filter, как показано в дампе 2.3.2

Дамп 2.3.2

~$ sudo iptables -t nat -S
...
-P INPUT ACCEPT
-P FORWARD ACCEPT
...
-N LIBVIRT_FWI
-N LIBVIRT_FWO
-N LIBVIRT_FWX
-N LIBVIRT_INP
-N LIBVIRT_OUT
-N LIBVIRT_OUT
-A INPUT -j LIBVIRT_INP
-A FORWARD -j LIBVIRT_FWX
-A FORWARD -j LIBVIRT_FWI
-A FORWARD -j LIBVIRT_FWO
-A OUTPUT -j LIBVIRT_OUT
...

Как показано в дампе 2.3.2, сначала разрешается прохождение пакетов любых типов протоколов в цепочках INPUT, FORWARD, OUTPUT, что на первый взгляд не безопасно [3.13]. Но, вводимые ограничения в цепочках LIBVIRT-{FWO,FWX,FWI, INP, OUT} позволяют снять определенный градус накала страстей и сделать соединения безопасными. Далее, создаются определяемые пользователем цепочки LIBVIRT-{FWO,FWX,FWI, INP, OUT} (опция -N) и добавляются правила перехода (опция -j) к ним согласно той последовательности, как эти правила были добавлены.

Все только что перечисленные и создаваемые libvirt пользовательские цепочки образуют прямой и обратный канал движения трафика между узлами с ip:192.168.7.2 и 192.168.2.10. Прямой канал показан на рисунке 2.3.4, который был отработан ранее при перенаправлении трафика между двумя интерфейсами узлов гостевых ОС с ip:192.168.7.2 и 192.168.2.10

Рисунок 2.3.4

Как показано на рисунке 2.3.4, кроме добавленных правил libvirt, после инициализации сети с ip:192.168.2.0/24, мне пришлось добавить свои правила и пользовательские цепочки YP_FWI, YP_FWO в таблице фильтрации (filter) для обхода установленных правил и цепочек libvirt

Рисунок 2.3.5

Организация обратного канала показана на рисунке 2.3.5, который был реализован с использованием тех же самых цепочек и правил, что и прямой канал, как показано в листинге 2.3.6, от отправителя в направлении получателя.

Листинг 2.3.6

# Цепочка FORWARD:
-P FORWARD ACCEPT
1:-A FORWARD -j LIBVIRT_FWX
2:-A FORWARD -j YP_FWI
3:-A FORWARD -j LIBVIRT_FWI
4:-A FORWARD -j LIBVIRT_FWO
5:-A FORWARD -j YP_FWO

# Пользов. цепочка YP_FWI:
1: -A YP_FWI -s 192.168.2.10/32 -i virbr1 -o tap1 -j ACCEPT
2: -A YP_FWI -s 192.168.2.10/32 -i virbr1 -j YP_FWO
3: -A YP_FWI -s 192.168.7.0/24 -d 192.168.2.0/24 -i tap2 -j YP_FWO

# Пользов. цепочка YP_FWO:
1: -A YP_FWO -s 192.168.7.2/32 -i tap1 -j RETURN
2: -A YP_FWO -s 192.168.7.2/32 -i tap2 -o virbr1 -j ACCEPT

Кроме правил фильтрации для организации продвижения пакетов трафика в нужном направлении, была использована политика MASQUERADE на выходе сетевого интерфейса virbr1 при передачи пакета к узлу-получателю ВМ "ОС Debian-10" и маскирования в заголовке IP-пакета IP-адреса 192.168.7.2 узла-отправителя ВМ "ОС Yocto/poky", как показано в листинге 2.3.7

Листинг 2.3.7

 
-P POSTROUTING ACCEPT
# Цепочка POSTROUTING: 
1:-A POSTROUTING -j YP_PRT
2:-A POSTROUTING -j LIBVIRT_PRT
…
# Цепочка YP_PRT
-A YP_PRT ! -s 192.168.7.2/32 -i tap2 -j RETURN
-A YP_PRT -d 192.168.2.0/24 -o virbr1 -j MASQUERADE 

Как показано, в листинге 2.3.7, цепочка YA_PRT обеспечивает обход цепочки LIBVIRT_PRT, ранее определенной libvirt, и установку правил перенаправления пакета по сетевому адресу или портам, передаваемые в подсеть с ip:192.168.2.0/24

2.4 Процедура отслеживание соединений в режимах фильтрации и трансляции сетевого адреса (IPTables / NFTables / conntrack)

Перед тем, как рассмотреть все политики перенаправления сетевого адреса и портов NAT, предлагаю ознакомится с работой подсистемы отслеживания соединений, реализованной в модуле (nf_)conntrack ядра ОС GNU/Linux

Как вытекает из самого названия подсистемы, её основной задачей является отслеживание соединений, называемой в некоторых источниках "ct system" уровня ядра [3.17], и оценка пакетов вычислительных сетей IPv4 и/или IPv6 на их полезность и чтобы определить какие пакеты связаны друг с другом, например с точки зрения ореентированного на установление постоянного соединения протокола TCP

Эту задачу (nf_)conntrack выполняет в качестве беспристрастного наблюдателя (transparent observer) и не принимает активного участия в создании и управлении соединений между конечными точками, как и не имеет значение являются ли это соединение удаленным или локальным. Так же не играет роли, где находятся конечные точки соединения, даже если они находятся на удаленных узлах, в таком случае (nf_)conntrack будет рассматривать их до тех пор пока управляет им на узле, который выполняет маршрутизацию (routing packets) или соединение (bridging packets) пакетов соответствующего соединения. Как вариант, одна или даже обе конечных точек могут расположены на локальных сокетах того же самого узла, где выполняется (nf_)conntrack . Эта не вносит никаких различий, потому что (nf_)conntrack постоянно обновляет список всех отслеживаемых соединений, по установленному каждому из них собственному таймауту, и классифицирует сетевые пакеты, так как они проходят сетевой стек ядра, снабжая каждого из них ссылкой (указателем) на другой пакет отслеживаемых экземплярах соединений. Поэтому любой другой компонент ядра может иметь доступ к этой совокупности соединений и принимать на основе этого решение.

Главными кандидатами кто может задействовать (nf_)conntrack являются подсистемы фильтрации пакетов и проверки состояния пакетов, реализуемые для пользователя в качестве интерфейсов межсетевых экранов IPTables и Nftable [3.18]. При этом нужно понимать, что сам (nf_)conntrack никогда не отсеивает и управляет пакетами, а применяется на 3-ем сетевом и 4-м транспортном уровни модели OSI, что делает возможным отслеживания соединений на базе протоколов TCP, UDP, ICMP, ICMPv6, SCTP, DCCP и GRE. Очевидно, что определение термина «соединение» в (nf_)conntrack не ограничивается лишь ориентированными на устанавливающие постоянное соединения протоколов, так как несколько только что упомянутых протоколов такими не являются. Как например в случае с протоколом ICMP, где установленным соединением считается переданный пакет с эхо запросом (echo-request) и принятый в ответ (echo-reply). Так же (nf_)conntrack обеспечивает несколькими вспомогательными компонентами и расширениями, которые позволяют осуществлять отслеживание на 5-м прикладном уровне модели OSI, таких протоколов как TFTP, PPTP, SIP и т.д.

Теперь рассмотрим в каких цепочка IPTables, где и с какими приоритетами задействуется conntrack, как показано на рисунке 2.4.1

Рисунок 2.4.1

Как показано на рисунке 2.4.1, в случае использования NFTables нужно не забывать о приоритетах, иначе пакет не преодолеет conntrack и где-нибудь там «застрянет». Так, например, при прохождение PREROUTNIG и OUTPUT приоритет нужно устанавливать меньше -200 , а вот для цепочек INPUT и PREROUTING должно быть максимальное положительное значение, но уже в так называемых помощниках conntrack, которые определяет соответствие пакета выше перечисленных прикладного уровня [3.20].

Чтобы получить список соединений и их состояний следует обратить свой взор на файл /proc/net/nf_conntrack, который можно прочитать командой cat из консоли, как показано в дампе 2.4.2 . При этом, тот же самый список соединений возможно получить из файла /proc/net/ip_conntrack [3.22]

Листинг 2.4.2

 
sudo cat /proc/net/nf_conntrack | grep src=192.168.2.2
...
ipv4     2 udp      17 25 src=192.168.2.10 dst=192.168.2.2 sport=39182 dport=53 src=192.168.2.2 dst=192.168.2.10 sport=53 dport=39182 mark=0 zone=0 use=2
ipv4     2 tcp      6 431995 ESTABLISHED src=192.168.2.2 dst=192.168.2.10 sport=38452 dport=2525 src=192.168.2.10 dst=192.168.2.2 sport=2525 dport=38452 [ASSURED] mark=0 zone=0 use=2

В данном случае, было зарегистрировано два соединения: первое – TCP, а второе – UDP-соединение. Каждая строка файла /proc/net/nf_conntrack или /proc/net/ip_conntrack содержит информацию об зарегистрированном соединении и имеет определенный формат записи, которые перечислены в таблице 2.4.3

Таблица 2.4.3
Поз. Назначение поля записи Поддержка в /proc/net/nf_conntrack Поддержка в /proc/net/ip_conntrack
1 Наименование сетевого протокола: ipv4 или ipv6 +
2 Номер сетевого протокола +
3 Наименование протокола транспортного уровня, может принимать значения: icmp, tcp, udp, dccp, gre, sctp, udplite, icmpv6 + +
4 Номер протокола транспортного уровня + +
5 Содержит значение таймера обратного отсчета срока истечения валидности соединения в секундах + +
6 Состояние соединения (поддерживается не всеми протоколами) + +
7,... Остальные поля содержат либо параметр соединения, состоящий из именованного ключа и его значения, или флаги в виде текстовых обозначений, напиример [UNREPLIED][ASSURED],... + +

Назначение флагов:

[ASSURED] трафик был передан в обоих направления: в направлении отправителя и с ответом от получателя (request and respond directions), т.е была зафиксирована передача пакета с запросом на установку соединения от отправителя (request directions) и прием им ответного пакета от получателя (respond directions).

[UNREPLIED] устанавливается в случае отсутствия каких либо пакетов обратного направления от получателя . В этом случае КЭШ отслеживаемых соединений неизбежно переполнится, поэтому такие соединения отбрасываются первыми.

[OFFLOAD] в 2017 году в подсистему фильтрации и ретрансляции сетевого адреса и портов была добавлена программная инфраструктура (flow offload infrastructure), обеспечивающая снижение нагрузки за отслеживаемыми на уровне подсистемы ядра netfilter соединений и оптимизации пути следования внутри пакетов TCP/IP (flow offload infrastructure), путем выгрузки такого соединения в таблицу передачи пакетов (flow table).

Таймер со стороны пользователя у таких записей (поле 5) в файле /proc/net/nf_conntrack выглядит застывшим. Это было сделано для того, чтобы такое соединение не выскользало из виду и не исчезало из файла /proc/net/nf_conntrack . Таймер [модуля] conntrack (на уровне ядра) периодически устанавливает произвольное большое значение этой записи в файле /proc/net/nf_conntrack, поэтому эта запись в нем не исчезает. Тем самым через такую блокировку conntrack позволяет сохранить битовую проверку пути следования (передачи) пакета [3.27], пример которой приводится в дампе 2.4.4 .

Дамп 2.4.4

 
# cat /proc/net/nf_conntrack
 ipv4     2 tcp      6 src=10.141.10.2 dst=147.75.205.195 sport=36392 dport=443 src=147.75.205.195 dst=192.168.2.195 sport=443 dport=36392 [OFFLOAD] mark=0 zone=0 use=2

В дампе приводится пример установки флага [OFFLOAD] из найденной мной документации [3.25], т.к. флаги [OFFLOAD] и [HW_OFFLOAD] в записях списка соединений возникают только при использовании NFTables, увы.

[HW_OFFLOAD] применяется начиная с версии ядра 5.13 в conntrack стал поддерживать выгрузку соединений сетевых интерфейсов в flow table [3.29].

Оба флага, OFFLOAD и HW_OFFLOAD, используются в политиках продвижения пакетов цепочки FORWARD и устанавливаются в более свежей реализации интерфейса управления NFTables подсистемы netfilter на уровне ядра Linux и позволяют высчитывать оптимальный путь следования их пакетов, например во время использования политики FORWARD, пример использования который взят с документации NFTables [3.30] и показан в дампе 2.4.5

Дамп 2.4.5

table inet x {

    flowtable f {
        hook ingress priority 0 devices = { eth0, eth1 };
    }

    chain forward {
        type filter hook forward priority 0; policy drop;

        # offload established connections
        ip protocol { tcp, udp } flow offload @f
        ip6 nexthdr { tcp, udp } flow offload @f
        counter packets 0 bytes 0

        # established/related connections
        ct state established,related counter accept

        # allow initial connection
        ip protocol { tcp, udp } accept
        ip6 nexthdr { tcp, udp } accept
    }
}

Кроме выше перечисленных флагов [ASSURED] , [UNREPLIED] , [OFFLOAD] и [РЦ_OFFLOAD] в перемешку с ними могут идти параметры соединения, такие как параметры src, dst, sport и dport, содержащие значения IP-адрес/порт отправителя и получателя/назначения, таймаут , устанавливаемый в зависимости от состояний dccp-, sctp- и tcp- соединения, и т.д.

Кроме того, у некоторых протоколов, таких как icmp, dccpsctptcpudp, udplite, и gre, запись в списке (установленных) соединений могут иметь дополнительные параметры, которые следует рассматривать отдельно.

2.5 Применение MASQUERADE, SNAT / DNAT для перенаправления портов

2.5.1 Политика SNAT и MASQUERADE

Как можно было и ожидать, для полноценного обмена по протоколам прикладного уровня модели OSI, просто установки политики FORWARD оказалось недостаточно, чтобы реализовать схемe, ранее показанную на рисунке 1.1

Поэтому рассмотрим схему применения цепочки POSTROUTING для перенаправления пакета tcp- или udp- c порта отправления (source port) узла отправителя на порт назначения (destination port) узла получателя, как показано на рисунке 2.5.1

Рисунок 2.5.1

Который практически полностью повторяет рисунок 2.3.4, но с одной лишю разницей, что для определения наличия неустановленного соединения здесь будем использовать conntrack в цепочке YA_PRT, которая разделяет обмен ВМ "ОС Debian-10" с центрального узла гипервизора и ВМ "ОС Yocto/poky".

Для обмена ВМ "ОС Debian-10" с центрального узла гипервизора служит цепочка LIBVIRT_PRT, которая определена пользователем и задействуется в основной цепочки POSTROUTING таблицы nat

Цепочка LIBVIRT_PRT установливает правила, осуществляющие перенаправление исходящего трафика c ВМ "ОС Debian-10" на порты узлов, не относящихся к сети 192.168.2.0/24, используя политику MASQUERADE, как показано в дампе 2.5.2

Дамп 2.5.2

user@kvm-host: ~$ sudo iptables -t nat -S POSTROUTING
...
-A LIBVIRT_PRT -s 192.168.2.0/24 ! -d 192.168.2.0/24 -o tap0 -p tcp -m  -j MASQUERADE --to-ports 32768-65535
-A LIBVIRT_PRT -s 192.168.2.0/24 ! -d 192.168.2.0/24 -o tap0 -p udp -j MASQUERADE --to-ports 32768-65535
-A LIBVIRT_PRT -s 192.168.2.0/24 ! -d 192.168.2.0/24 -o tap0 -j MASQUERADE
...

Где производится маскирование, согласно выделенному диапазону эмфиральных портов (32768-65535), указанного ранее в листинге 2.2.1 и указаному в XML-конфигурации подсети с ip:192.168.2.0/24 с помощью элемента <port> для перенаправления всех исходящих пакеты, передаваемые по эмфиральным портам от узла подсети с ip:192.168.2.0/24 к узлам подсети ip:192.168.7.0/24, что на самом деле, как видно из дампа 2.5.2, здесь применяется маскирование диапазона эмфиральных портов протоколов транспортного уровня tcp и udp, а также для любых других передаваемых со шлюза (virbr1)

Листинг 2.5.3

# Цепочка YP_PRT
1:-A YP_PRT ! -s 192.168.7.2/32 -i tap2 -j RETURN
2:-A YP_PRT -d 192.168.2.0/24 -o virbr1 -j MASQUERADE 

Как показано в листинге 2.5.3, цепочка YA_PRT служит для замещения или маскирования внутреннего ip:192.168.7.2 в передаваемом IP-пакете узла ВМ "ОС Yocto/poky" на внешний ip:192.168.2.2 , как показано в списке соединений в дампе 2.5.4 для udp-соединений.

Дампе 2.5.4

user@kvm-host: ~$ sudo cat /proc/net/nf_conntrack | grep 192.168.2.2
ipv4     2 udp      17 25 src=192.168.7.2 dst=192.168.2.10 sport=54069 dport=53 src=192.168.2.10 dst=192.168.2.2 sport=53 dport=54069 mark=0 zone=0 use=2
ipv4     2 udp      17 13 src=192.168.7.2 dst=192.168.2.10 sport=38511 dport=53 src=192.168.2.10 dst=192.168.2.2 sport=53 dport=38511 mark=0 zone=0 use=2
ipv4     2 udp      17 13 src=192.168.7.2 dst=192.168.2.10 sport=59803 dport=53 src=192.168.2.10 dst=192.168.2.2 sport=53 dport=59803 mark=0 zone=0 use=2
ipv4     2 tcp      6 431998 ESTABLISHED src=192.168.7.2 dst=192.168.2.10 sport=49648 dport=110  src=192.168.2.10 dst=192.168.2.2 sport=110 dport=49648 [ASSURED] mark=0 zone=0 use=2
ipv4     2 udp      17 25 src=192.168.7.2 dst=192.168.2.10 sport=34910 dport=53 src=192.168.2.10 dst=192.168.2.2 sport=53 dport=34910 mark=0 zone=0 use=2

Где, если верить параметрам зарегистрированных udp- и tcp- соединений, IP-адрес отправителя, инициатора соединения является IP:192.168.7.2, который наблюдаем в параметре src=192.168.7.2 в пятой позиции или седьмой позиции соответственно. Потому что в регистрационной записи файла /etc/net/nf_conntrack содержатся два похожих друг на друга набора именованных параметров.

В первом наборе (выделены подчеркиванием в дампе 2.5.4) отображаются оригинальные значения портов и IP-адрес заголовоку отправляемого tcp- или udp- пакета, начиная с 5-й позиции (udp) или 7-й позиции (tcp), ip-адрес отправителя (src=), ip-адрес получателя (dst=), порт отправителя (sport=), порт получателя (dport=) . Во втором наборе (выделен жирным в дампе 2.5.4), который сразу же следует за первым, отображаются содержимого заголовка ответного пакета, который пришел обратно от получателя. Поэтому, если посмотреть на дамп 2.5.4 с установленной политика MASQUERADE, IP-адрес узла получателя в ответном пакете, преподаваемого в направлении от получателя (destination direction), будет равен ip-адресу шлюза 192.168.2.2 (выделен жирным с курсивом в дампе 2.5.4 ).

Если же удалить политику MASQUERADE из цепочки YA_PRT(выделена жирным в листинге 2.5.6), тогда IP-адрес назначения в ответном пакете направлении от получателя (destination direction) будет равен IP-адресу инициатору соединения, т.е. узлу отправителю (source) и равен 192.168.7.2 (выделен жирным в дампе 2.5.5).

Листинг 2.5.6

# Цепочка YP_PRT:
1:-A YP_PRT ! -s 192.168.7.2/32 -i tap2 -j RETURN
2:-A YP_PRT  -s 192.168.7.2 -d 192.168.2.10 -o virbr1 -j SNAT --to 192.168.2.2 

В результате, добавленного правила (выделено жирным в дампе 2.5.6), IP-адрес назначения в направлении от получателя (destionation direction) будет снова равен 192.168.2.2 (выделен жирным), как показано в дампе 2.5.7

Дампе 2.5.7

user@kvm-host:~$ sudo cat /proc/net/nf_conntrack | grep 192.168.2
ipv4     2 tcp      6 431991 ESTABLISHED src=192.168.7.2 dst=192.168.2.10 sport=49660 dport=110 src=192.168.2.10 dst=192.168.2.2 sport=110 dport=49660 [ASSURED] mark=0 zone=0 use=2
ipv4     2 udp      17 12 src=192.168.7.2 dst=192.168.2.10 sport=42750 dport=53 src=192.168.2.10 dst=192.168.2.2 sport=53 dport=42750 mark=0 zone=0 use=2
ipv4     2 udp      17 12 src=192.168.7.2 dst=192.168.2.10 sport=42660 dport=53 src=192.168.2.10 dst=192.168.2.2 sport=53 dport=42660 mark=0 zone=0 use=2

2.5.2 Политика DNAT

Если же мы хотим перенаправить пакет на нужный номер порта отправителю или получателю в схеме, показанной на рисунке 1.1, то наш путь лежит в царство цепочки PREROUTING

Цепочка PREROUTING позволяет устанавливать нужные правила для перенаправления заданного порта передаваемого пакета получателю и отсеивать те пакеты отправителя, к портам которых доступ ему ограничен. Для чего, необходимо определить пользовательскую цепочку YP_PRRT, на которая показана на рисунке 2.5.8

Рисунок 2.5.8

Как показано на рисунке 2.8, пользовательская цепочка YP_PRRT производит замену порта на требуемый по указанным в нем значению порта-назначения узла отправителя, которым является ВМ "ОС Yocto/poky". При этом, пакет в направлении получателя с запросом на соединение может поступить из одного интерфейса tap1 или tap2 из-за путаницы эмулятором Qemu/KVM связки интерфесов eth0, eth1 на узле ВМ "ОС Yocto/poky" с интерфейсами tap1, tap2 на центральном узле гипервизора . При этом, в данной схеме поробуем в целях обучения игнорировать все пакеты в цепочке PREROUTING, которые не будут иметь значения, соотв. порта-назначения получателя (подсети с ip:192.168.2.10/24) в требуемом диапазоне 32001–32767

Согласно представленной схемы прохождения пакетом цепочек на рисунке 2.5.8, выполнение первого условия будет выполняться прямо в начале цепочки YP_PRRT, как показано в 1-й и 2-й ее позиции листинга 2.5.9

Листинг 2.5.9

 
-P PREROUTING ACCEPT
-N YP_PRRT

# Цепочка PRETROUTING: 
1:-A PREROUTING -j YP_PRRT

# Цепочка YP_PRRT:
1:-A YP_PRRT ! -d 192.168.2.0/24 -i tap1 -j RETURN
2:-A YP_PRRT ! -d 192.168.2.0/24 -i tap2 -j RETURN
3:-A YP_PRRT -d 192.168.2.10/32 -p udp -m udp ! --dport 32001:32767 -j REJECT
4:-A YP_PRRT -d 192.168.2.10/32 -p tcp -m tcp ! --dport 32001:32767 -j REJECT

Как показано в листинга 2.5.9, в нем зачеркнутыми являются правила в 3-й и 4-й позиции цепочке YP_PRRT, где пытался установить правила для отсеивания пакет при не соблюдении 2-го условия, показанного на рисунке 2.5.8

При попытки добавления правил в зачеркнутых 3-й и 4-й позиции цепочки YP_PRRT, пользовательский интерфейс iptables завершился с ошибкой, как показано в дампе 2.5.10

Листинг 2.5.10

 
user@kvm-host:~$ sudo iptables -t nat -D YP_PRRT -p udp --dst 192.168.2.10 ! --dport 32001:32767 -j REJECT
iptables: Bad rule (does a matching rule exist in that chain?).
user@kvm-host:~$ sudo iptables -t nat -D YP_PRRT -p tcp --dst 192.168.2.10 ! --dport 32001:32767 -j REJECT
iptables: Bad rule (does a matching rule exist in that chain?).

Поэтому, как показано в листинге 2.5.11, правила в зачеркнутой 3-й и 4-й позиции цепочки YP_PRRT были приведены в соответствии со схемой, показанной ранее на рисунке 2.5.8

Листинг 2.5.11

# Цепочка YP_PRRT:
1:-A YP_PRRT ! -d 192.168.2.0/24 -i tap1 -j RETURN
2:-A YP_PRRT ! -d 192.168.2.0/24 -i tap2 -j RETURN
3:-A YP_PRRT -d 192.168.2.10/32 -s 192.168.7.2/32 -p udp -m udp ! --dport 32001:32767 -j RETRUN
4:-A YP_PRRT -d 192.168.2.10/32 -s 192.168.7.2/32 -p tcp -m tcp ! --dport 32001:32767 -j RETRUN

А именно, произведена передача пакета к цепочке FORWARD таблицы filter при условии, что порт назначения в tcp-, udp- пакетах не находится в ожидаемом диапазоне 32001-32767, произойдет его отбраковка в цепочки YP_FWO, которую рассмотрю ниже, после применения политики DNAT

Как показано в листинге 2.5.12, для ретрансляции пакетов в направлении получателя от отправителя (request direction) на нужный открытый порт ВМ "ОС Debian-10", добавил следующие правила согласно схеме, показанной на рисунке 1.1

Листинг 2.5.12

# Цепочка YP_PRRT:
1:-A YP_PRRT ! -d 192.168.2.0/24 -i tap1 -j RETURN
2:-A YP_PRRT ! -d 192.168.2.0/24 -i tap2 -j RETURN
# Любые пакеты передаваемые 
3:-A YP_PRRT -d 192.168.2.10/32 -s 192.168.7.2/32 -p udp -m udp ! --dport 32001:32767 -j RETRUN
4:-A YP_PRRT -d 192.168.2.10/32 -s 192.168.7.2/32 -p tcp -m tcp ! --dport 32001:32767 -j RETRUN
# Ретрансляция порта получателя с 32001/tcp на реальный открытый 22/tcp 
5:-A YP_PRRT -s 192.168.7.2/32 -d 192.168.2.10/32 -p tcp -m tcp --dport 32001 -j DNAT --to-destination 192.168.2.10:22
# Ретрансляция порта получателя с 32002/udp на реальный открытый 69/udp
6:-A YP_PRRT -s 192.168.7.2/32 -d 192.168.2.10/32 -p udp -m udp --dport 32002 -j DNAT --to-destination 192.168.2.10:69
# Ретрансляция порта получателя с 32004/tcp на реальный открытый 110/tcp
7:-A YP_PRRT -s 192.168.7.2/32 -d 192.168.2.10/32 -p tcp -m tcp --dport 32004 -j DNAT --to-destination 192.168.2.10:110
# Ретрансляция порта получателя с 32005/tcp на реальный открытый 143/tcp
8:-A YP_PRRT -s 192.168.7.2/32 -d 192.168.2.10/32 -p tcp -m tcp --dport 32005 -j DNAT --to-destination 192.168.2.10:143
# Ретрансляция порта получателя с 32006/tcp на реальный открытый 2525/tcp
9:-A YP_PRRT -s 192.168.7.2/32 -d 192.168.2.10/32 -p tcp -m tcp --dport 32006 -j DNAT --to-destination 192.168.2.10:2525
# Ретрансляция порта получателя с 32007/udp на реальный открытый 514/tcp
9:-A YP_PRRT -s 192.168.7.2/32 -d 192.168.2.10/32 -p tcp -m tcp --dport 32007 -j DNAT --to-destination 192.168.2.10:514
# Ретрансляция порта получателя с 32007/udp на реальный открытый 514/udp
10:-A YP_PRRT -s 192.168.7.2/32 -d 192.168.2.10/32 -p udp -m udp --dport 32007 -j DNAT --to-destination 192.168.2.10:514

Как показано в листинге 2.5.12, с 5-й по 10-ю позицию цепочки YP_PRRT устанавливаются правила, которые перенаправляют пакет в направлении получателя от отправителя (request direction) на нужный открытый порт ВМ "ОС Debian-10" в соответствии со схемой, показанной на рисунке 1.1. При этом, используется опция --to-destination , которая идет следом за -j DNAT и от нее зависящей.

Опция --to-destination [ipaddr[-ipaddr]][:port[-port]], зависимая от -j DNAT, используется для перенаправления tcp-, udp- соединений (на стороне получателя ) на новый IP-адрес или диапазон IP-адресов ([ipaddr[-ipaddr]]), так же как указанный через двоеточие новый порт или диапазон портов.

Кроме того, чтобы не наскочить на сообщение об неизвестной опции, например "--dport", как показано в дампе 5.13, следует четко понимать последовательность ввода оцпий, иначе ошибок типа "unknown option" не избежать.

Листинг 5.13

user@kvm-host:~$ sudo iptables -t nat -A YP_PRRT -s 192.168.7.2/32 -d 192.168.2.10/32 --dport 32001 -j DNAT --to-destination 192.168.2.10:22
iptables v1.8.7 (nf_tables): unknown option "--dport"
Try `iptables -h' or 'iptables --help' for more information.

Правильной последовательностью опций будет следование сначала опции -s, --source address[/mask], за ней опции -d, --destination address[/mask]. Следом нужно указать опции протокола -p tcp -m tcp, последняя активирует более расширенное обнаружения соответствий протоколу TCP, которые в данном случае включают определение номера порта назначения в tcp-пакете отправителя в направление получателя. Поэтому следующий порядок следования опций, показанный в листинге 5.14, является правильным и распространяемый на все остальные позиции ниже в цепочке YP_PRRT

Листинг 5.14

# Ретрансляция порта получателя с 320001/tcp на реальный открытый 22/tcp 
5:-A YP_PRRT -s 192.168.7.2/32 -d 192.168.2.10/32 -p tcp -m tcp --dport 32001 -j DNAT --to-destination 192.168.2.10:22
# Ретрансляция порта получателя с 320002/udp на реальный открытый 69/tcp
6: A YP_PRRT -s 192.168.7.2/32 -d 192.168.2.10/32 -p udp -m udp --dport 32002 -j DNAT --to-destination 192.168.2.10:69 

Далее оставалось выполнить команду на стороне отправителя "ssh -p 32001 user@192.168.2.10", чтобы, как показано в дампе 5.15, увидеть следы на центральном узле гипервизора (kvm-host), перенаправления пакета порта 32001, вводимого отправителем, на реально открытый порт 22 на стороне получателя.

Дамп 5.15

user@kvm-host:~$ sudo iptables -t nat -v -nL YP_PRRT
Chain YP_PRRT (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 RETURN     all  --  tap1   *       0.0.0.0/0           !192.168.2.0/24      
    0     0 RETURN     all  --  tap2   *       0.0.0.0/0           !192.168.2.0/24      
    0     0 RETURN     udp  --  *      *       192.168.7.2          192.168.2.10         udp dpts:!32001:32767
    2   120 RETURN     tcp  --  *      *       192.168.7.2          192.168.2.10         tcp dpts:!32001:32767
    1    60 DNAT       tcp  --  *      *       192.168.7.2          192.168.2.10         tcp dpt:32001 to:192.168.2.10:22

user@kvm-host:~$ sudo cat /proc/net/nf_conntrack | grep src=192.168.2.10
ipv4     2 tcp      6 431993 ESTABLISHED src=192.168.7.2 dst=192.168.2.10 sport=44338 dport=32001 src=192.168.2.10 dst=192.168.2.2 sport=22 dport=44338 [ASSURED] mark=0 zone=0 use=2

Как показано, в дампе 5.15, на стороне kvm-host можно обнаружить, что указанное в дампе 5.14 правило, сработало согласно выводу команды sudo iptables -t nat -v -nL YP_PRRT и было установлено двунаправленное соединение между отправителем и получателем в результате изменения в заголовке udp-пакета номера порта с 32001 на 22 соответственно, как показано в дампе 5.15

Дамп 5.15

user@kvm-host:~$ sudo cat /proc/net/nf_conntrack | grep src=192.168.2.
ipv4     2 tcp      6 431998 ESTABLISHED src=192.168.7.2 dst=192.168.2.10 sport=44336 dport=32001 src=192.168.2.10 dst=192.168.2.2 sport=22 dport=44336 [ASSURED] mark=0 zone=0 use=2
ipv4     2 udp      17 15 src=192.168.2.10 dst=192.168.2.2 sport=57230 dport=53 src=192.168.2.2 dst=192.168.2.10 sport=53 dport=57230 [ASSURED] mark=0 zone=0 use=2
ipv4     2 tcp      6 116 TIME_WAIT src=192.168.7.2 dst=192.168.2.10 sport=44334 dport=32001 src=192.168.2.10 dst=192.168.2.2 sport=22 dport=44334 [ASSURED] mark=0 zone=0 use=2

А вот случае с UDP соединением нужно будет попотеть и внести изменения в цепочку YA_PRRT(политики DNAT). Потому что если верить дампам обмена по всем сетевым устройствам, участвующих в нем и показанным на рисунке 5.16, просто сделанных и установленных ранее правил недостаточно.

Рисунок 2.5.16

Как показано на рисунке 5.16, препятствием для дальнейшей передачи, стало правило, устанавливаемое, как раз с помощью SNAT, определенное во 2-й позиции цепочки YP_PRT и показанное в листинге 5.17

Дамп 5.17

# Цепочка YP_PRT:
...
2:-A YP_PRT -s 192.168.7.2/32 -d 192.168.2.10/32 -o virbr1 -j SNAT --to-source 192.168.2.2

Поэтому, чтобы восстановить обмен в обратном направлении от получателя (ВМ "ОС Debain-10") к отправителю (ВМ "ОС Yocto/poky"), мне понадобилось все udp-пакеты в диапазоне 32768-65535 перенаправить на с ip: 192.168.2.10 первого на ip: 192.168.7.2 последнего, как показано в 7-й позиции YP_PRRT листинга 5.18

Поэтому, чтобы восстановить обмен в обратном направлении от получателя (ВМ "ОС Debain-10") к отправителю (ВМ "ОС Yocto/poky"), мне понадобилось все udp-пакеты в диапазоне 32768-65535 перенаправить на с ip:192.168.2.10 первого на ip:192.168.7.2 последнего, как показано в 7-й позиции YP_PRRT листинга 5.18

Дамп 5.18

# Цепочка YP_PRRT:
1:-A YP_PRRT ! -d 192.168.2.0/24 -i tap1 -j RETURN
2:-A YP_PRRT ! -d 192.168.2.0/24 -i tap2 -j RETURN
3:-A YP_PRRT -s 192.168.7.2/32 -d 192.168.2.10/32 -p udp -m udp ! --dport 32001:32767 -j RETURN
4:-A YP_PRRT -s 192.168.7.2/32 -d 192.168.2.10/32 -p tcp -m tcp ! --dport 32001:32767 -j RETURN
5:-A YP_PRRT -s 192.168.7.2/32 -d 192.168.2.10/32 -p tcp -m tcp --dport 32001 -j DNAT --to-destination 192.168.2.10:22
6:-A YP_PRRT -s 192.168.7.2/32 -d 192.168.2.10/32 -p udp -m udp --dport 32002 -j DNAT --to-destination 192.168.2.10:69
...
11: -A YP_PRRT -s 192.168.2.10/32 -p udp -m udp --dport 32768:65535 -j DNAT --to-destination  192.168.7.2:32768-65535
...

В результате был получен полноценный обмен для UDP-соединения, реализуемого TFTP протоколом, на узле центрального гипервизора, как показано в дампе 5.19

Дамп 5.19

user@kvm-host:~$ sudo tcpdump -n -i any host 192.168.2.2 or 192.168.2.10
...
18:27:46.765171 tap2  In  IP 192.168.7.2.58776 > 192.168.2.10.32002: UDP, length 38
18:27:46.765242 virbr1 Out IP 192.168.2.2.58776 > 192.168.2.10.69: TFTP, length 38, RRQ "tftserv-768s-charcters.txt" netascii
18:27:46.765252 tap0  Out IP 192.168.2.2.58776 > 192.168.2.10.69: TFTP, length 38, RRQ "tftserv-768s-charcters.txt" netascii
18:27:46.766493 tap0  P   IP 192.168.2.10.39319 > 192.168.2.2.58776: UDP, length 516
18:27:46.766493 virbr1 In  IP 192.168.2.10.39319 > 192.168.2.2.58776: UDP, length 516
18:27:46.766557 tap1  Out IP 192.168.2.10.39319 > 192.168.7.2.58776: UDP, length 516
...

Как показано в дампе 5.19 (строчка выделена), в результате изменения IP-адреса назначения на 192.168.7.2 в передаваемом UDP-пакете приведет к регистрации двух UDP-соединений, как показано в дампе 5.20

Дамп 5.20

user@kvm-host:~$ sudo cat /proc/net/nf_conntrack | grep src=192.168.2

ipv4     2 udp      17 25 src=192.168.2.10 dst=192.168.2.2 sport=39319 dport=58776 src=192.168.7.2 dst=192.168.2.10 sport=58776 dport=39319 [ASSURED] mark=0 zone=0 use=2
ipv4     2 udp      17 25 src=192.168.7.2 dst=192.168.2.10 sport=58776 dport=32002 [UNREPLIED] src=192.168.2.10 dst=192.168.2.2 sport=69 dport=58776 mark=0 zone=0 use=2

В списке соединений будет два соединения. Первое – однонаправленное в строну отправителя с флагом ([ASSURED]), а второе – двунаправленное с флагом [UNREPLIED], т.к. после переданного первого UDP-пакета с данными в обои стороны будут повторно передаваться UDP-пакеты согласно протоколу TFTP до тех пор пока не будет передано содержимое всего файла.

$ ∞ $

3. Библиография

3.1 Словарь Академик. Встроенная операционная система

3.2 explainshell.com. Network exploration tool and security / port scanner

3.3 SECLIST.ORG. nmap parallelization

3.4 nmap(1) - Linux man page

3.5 Linux Packet Filtering and iptables. Chapter 11. Iptables targets and jumps

3.6 Linuxhint.Iptables Tutorial

3.7 Stackoverflow. New IPs are added to IPTABLES INPUT REJECT with "reject-with icmp-port-unreachable" from nowhere

3.8 WikipediA.Ephemeral port

3.9 Libvirt:Network XML format

3.10 Part V. iptables firewall. Chapter 8. iptables firewall

3.11 Red Hat Customer Portal. 2.8. FIREWALLS

3.12 [libvirt] [PATCH RFC] network: Delay creating private chains until starting network

3.13 CentOS community. Iptables FORWARD ACCEPT, is this not secure?

3.14 iptables: Small manual and tutorial with some examples and tips. Written by Guillermo Garron

3.15 Superuser. Linux Netfilter: How does connection tracking track connections changed by NAT?

3.16 Conntrack-tool. Support page

3.17 Connection tracking (conntrack) - Part 1: Modules and Hooks

3.18 https://netfilter.org/projects/nftables/

3.19 Connection tracking (conntrack) - Part 3: State and Examples

3.20 netfilter hacking HOWTO. 3. Netfilter Architecture

3.21 wiki.nftables.org. Netfilter hooks

3.22 Stackoverflow. Details of /proc/net/ip_conntrack and /proc/net/nf_conntrack

3.23 Source code nf_conntrack

3.24 [PATCH 1/6] netfilter: nf_conntrack: add IPS_HW_OFFLOAD status bit

3.25 Hash Suite: Windows password security audit tool. GUI, reports in PDF.

3.26 LWN.net. netfilter flowtable hardware offload

3.27 [PATCH RFC,WIP 3/5] netfilter: nf_flow_offload: integration with conntrack

3.28 Netfilter’s flowtable infrastructure

3.29 [PATCH 1/6] netfilter: nf_conntrack: add IPS_HW_OFFLOAD status bit

3.30 WikDetails of /proc/net/ip_conntrack and /proc/net/nf_conntracki.nftables.org. Flowtables

3.32 ИСПОЛЬЗОВАНИЕ ПОЛИТИКИ FORWARD И ПРАВИЛ NAT В IPTABLES

3.33 iptables-extensions -- Manual page