Транспортный уровень: трансляция адресов и формирование трафика
Ещё про VirtualBox
VBoxManage:
modifyvm
clonevm
startvm
controlvm … acpipowerbutton
unregistervm … --delete
Всё это умеют сценарии из лекций
- Соответствующая команда выводится на экран
Проброс портов из хост-системы в VirtualBox.
- Что такое и зачем нужно: если в профиль входит интерфейс типа «NAT», подключение к порту H на хост-машине транслируется в подключение к порту G на этом интерфейсе гостевой машины
- В GUI
VBoxManage modifyvm srv --natpf1 guestssh,tcp,,2201,,22 (см. в документации)
NAT
Network address translation — что такое и зачем нужно.
NAT без транспортного уровня
Идея замены конкретного IP другим конкретным IP (и обратно) — например, если «внутренний» IP из интернет-диапазона.
- Работает только 1:1
( actually, не работает)
Проблемы:
Любые контрольные суммы некорректны, если в них входит IP (надо пересчитывать)
- Нет информации для подмены «много → один»
- Давно выбросили ☺
NAT с идентификацией потока (NAPT)
Динамическая подмена IP на основании «состояния»
- Таблица: пара IP + идентификатор «состояния»
- Может работать N:1, M:N
- Destination NAT (например, для отдельного веб-сервера)
- Идентификаторы — всё, что можно извлечь из пакетов
- TCP: 2 порта + 2 IP (+ initial SeqN?)
- DNS (UDP): DNS Query ID (поле прикладного уровня!) + 2 порта + 2 IP
- NTP (UDP): Originator Timestamp (поле прикладного уровня!) + 2 порта + 2 IP
- ping: ICMP-serial (поле сетевого уровня) + IP
- …
- Проблема коллизий SEQN / портов / идентификаторов в вариантах N/1 и M/N:
- Два хоста (A и B идут на один и тот же порт хоста C через NAT):
- У них могут совпасть порты отправителя:
- A:1234 → C:80; B:1234 → C:80
=> коллизия
- Оок, введём в идентификатор ещё seqn:
- A:1234, seqn 4321 → C:80; B:1234, seqn 34234 → C:80
=> вероятность коллизии?
Примеры SNAT и DNAT
SNAT — при отсылке «наружу» (например, из intranet-диапазона)
- Кстати, MASQUERADE — это на случай динамического IP, при формировании conntrack-а всякий IP раз запрашивается у интерфейса
DNAT — при приёме (например, межсетевой экран на одной машине, а веб-сервер — внутри сети, на другой)
- Т. н. «проброс портов» — подключение к манише по попределённому порту «пробрасывается» на другую машину (можно поменять номер порта тоже):
# iptables -t nat -A PREROUTING -i интерфейс -p tcp --dport порт -j DNAT --to-destination внутренний_адрес
- Т. н. «проброс портов» — подключение к манише по попределённому порту «пробрасывается» на другую машину (можно поменять номер порта тоже):
- Работа с iptables (только введение, изучать будем NFTables)
/proc/net/nf_conntrack и утилита conntrack
Обход NAT с помощью STUN (на примере UDP)
TODO это в лекцию не влезло, надо сделать отдельный spin-off
Проблема: клиент1 - сервер1[NAT] - [NAT]сервер2 - клиент2. Как переслать пакет клиенту2 от клиента1?
«Проброс портов»: подключение на сервер2:порт3 транслируется межсетевым экраном в подключение к клиент2:порт2
А если нет административного доступа к серверам? Очевидно, нужен ещё один сервер, к которому оба клиента могуд обратиться (как минимум, для того, чтобы узнать, что до них кто-то хочет достучаться):
клиент1 - сервер1[NAT] - координатор - [NAT]сервер2 - клиент2
Полная ретрансляция через координатор. Делается с помощью ssh, например, или с помощью МЭ
STUN (Session Traversal Utilities for NAT).
Включают в себя несколько протоколов (в том числе полную ретрансляцию, Traversal_Using_Relay_NAT); остальный протоколы работают не всегда
- Базируется на двух (необоснованных) предположениях:
Если с клиента послать UDP-пакет какому-то серверу, в conntrack в течение некоторого времени находится запись, позволяющая получить UDP-«ответ» на этот пакет со стороны сервера, с порта получателя на порт отправителя
Так работают прикладные протоколы (например, DNS), но датаграмма не подразумевает ответ
Предположим, в UDP-пакете, предназначенном координатору, указан порт отправителя A, а при выходе из NAT на сервере1 порт отправителя превратился в B, о чём была сделана запись в conntrack. Тогда если послать ещё один UDP-пакет, на этот раз серверу2, указав тот же самый порт отправителя A, то на сервере1 порт отправителя тоже не изменится и будет B.
Пример организации STUN вручную (не успеем).
- Терминология:
Iip, Iport — соответственно, IP-адрес клиента (внутренний) и порт отправителя на клиенте, которые транслируются NAT-ом в Eip и Eport, внешний IP-адрес новый порт отправилтея.
клиент1 и клиент2 (или время от времени) поддерживают связь с координатором, получая от него информацию. Таки образом, координатор отслеживает таблицу вида Iip1 ⇒ Eip1; Iip2 ⇒ Eip2 (и всех остальных зарегистрированных абонентов).
Протокол установдения «соединения» между клиентом1 и клиентом2 (все «пакеты» далее — UDP):
клиент1 сообщает координатору, что хочет установить соединение с клиентом2; клиент2 (который тоже на связи с координатором) узнаёт от этом
клиент2 отправляет пакет Iip2:Iport2 → координатор
На сервере2 образуется запись в conntrack
Iip2:Iport2 ⇒ координатор:… / Eip2:Eport2
координатор получает этот пакет и отправляет клиенту1 информацию о Eip2:Eport2
клиент1 отправляет пакет Iip1:Iport1 → координатор
На сервере1 образуется запись в conntrack
Iip1:Iport1 → координатор:… / Eip1:Eport1
координатор получает этот пакет и отправляет клиенту2 информацию о Eip1:Eport1
клиент2 отправляет пакет Iip2:Iport2 → Eip1:Eport1
На сервере2 образуется запись в conntrack
Iip2:Iport2 → Eip1:Eport1 / Eip2:Eport2
клиент1 отправляет пакет Iip1:Iport1 → Eip2:Eport2
На сервере1 образуется запись в conntrack
Iip1:Iport1 → Eip2:Eport2 / Eip1:Eport1
Этот пакет доходит до сервера2, и согласно записи в conntrack передаётся клиенту2 как «ответ» на пакет (5)
клиент2 отправляет пакет Iip2:Iport2 → Eip1:Eport1
Этот пакет доходит до сервера1, и согласно записи в conntrack передаётся клиенту1 как «ответ» на пакет (6)
- …
Если клиент1 и клиент2 не будут тупить дольше времени жизни записи в conntrack, процесс будет продолжаться без участия координатора
По концам такого туннеля можно организовать ip over UDP с помощью ip fou
TCP: а что делать с seqn?
Простой пример для linux iptables … -j MASQUERADE, в котором
EPort по умолчанию совпадает с IPort, если нет конфликтов (и известен заранее)
«Стартовый» пакет (5) и (6) создаёт conntrack-запись не должен дойти до абонента (иначе отправителю вернётся либо «ответ», либо icmp-reject, и правило удалится), для этого выcтавляем ttl=2
Никакого обмена с координатором не происходит; он нужен только для того, чтобы пакеты с ttl=2 не доходили
client - nat2[NAT:10.3.0.4] - stun - [NAT:10.2.0.2]nat1 - srv
srv:
# echo QQ | socat - UDP:10.3.0.4:1234,sourceport=4321,ttl=2; socat -d -d -v PIPE UDP-RECVFROM:4321,fork
client:
socat - UDP:10.2.0.2:4321,sourceport=1234
Syn flood атака и SYNPROXY
- Суть: на каждый SYN в ядре выделяется приличная структурка. Можно заDOS-ить большим потоком безответственных SYN-ов.
- Решение: разделить МЭ и сервер, и до сервера доносить только «хорошие» SYN-ы, точнее — SYN-SYNACK-ACK-и всей пачкой (частичное проксирование)
- Требует более сложной логики
- Требует подмены SEQN (потому что мы всё ещё не знаем, какую SEQN выберет сервер, но уже «проиграли» для него 3WH)
Введение в обработку трафика
Эта тема на целый семестр! Поэтому про главную задачу — traffic shaping — только упомянем.
Задача: если сетевое устройство пересылает несколько потоков данных, надо обеспесить:
- «Справедливое» разделение трафика между абонентами (в т. ч. сообразно приоритетам)
- Работоспособность при перегрузках
Базовая статья: Traffic Control HOWTO
Как всегда Арчевики
Общая идея: маршрутизируемые пакеты нельзя просто перекладывать по одному
∃ серьёзная вероятность, что прямо сейчас принятый пакет отсылать нельзя (занято etc.)
- ⇒ буферизация (очередь)
- Приоритизация трафика
- ⇒ Выделение потоков (TCP)
- Например, SSH с быстрыми командами vs HTTP с большими объёмами
- Кстати: SSH / SFTP и ToS 0x48 / 0x00
Различные дисциплины (по длине очереди, по времени ожидания и т. п.)
Деревья очередей и фильтры для ветвления
Проблема: Bufferbloat
Дисциплина по умолчанию: tc-fq_codel:
CoDel (анти-буферблоат: 5ms в очереди + выбрасывание пакетов из «плохих» очередей) + Fair_queuing (равномерное распределение пропускной способности по потокам данных)
Умеет Explicit_Congestion_Notification вместо Random_early_detection
Пример: дисциплина Network Emulator
Статья (не всё работает так, как написано)
- Удобно испльзовать на тест-стендах в курсовах по сетям!
Потестируем её с помощью «flood ping» (безудержной отправки ping-ов с максимальной скоростью)
Исходное состояние:
# tc qdisc show # tc -s qdisc show # ping -f -c1000 10.9.0.2
Дисциплина по умолчанию CoDel
Медленная сеть:
# tc qdisc add dev eth1 root netem delay 400ms # tc qdisc show # ping -f -c100 10.9.0.2
- Должна выстроиться стопка из оправленных но ещё не отвеченных пакетов
Плохая сеть, в которой пакеты пропадают:
# tc qdisc del root dev eth1 # tc qdisc add dev eth1 root netem loss 10% # tc qdisc show # ping -f -c500 10.1.1.2
- Не забудем сначала удалить старую дисциплину
- К. О. рапортует: пакеты пропали
Очень плохая сеть, и медленная, и пакеты портятся:
# tc qdisc del root dev eth1 # tc qdisc add dev eth1 root netem delay 400ms corrupt 5% # tc qdisc show # ping -f -c500 10.1.1.2
Немного про shape:
Шейпить имеет смысл только исходящий трафик, потому что входящий уже получен ☺
- (на самом деле не только, но use case всё равно непростой)
Простейшая дисциплина — Token Bucket Filter
- Очередь пакетов → выдача «жетонов» из «ведра» → отсылка пакета с «жетоном»
По объёму: tbf limit объём_очереди burst ёмкость_ведра rate пропускная_способность
По времени ожидания tbf latency сколько_ждать burst ёмкость_ведра rate пропускная_способность
- Классовая очередь (дерево) — на каждый поток своя труба + общий слив
Простая приоритизация по ToS
Hierarchy Token Bucket с произвольной топологией (учебник)
Будем исследовать пропускную способность с помощью IPerf
На втором абоненте запустим iperf3 -4s (серверная часть, тлько IPv4)
На исследуемой машине будем настраивать дисциплину и запускать iperf3 -4c
Исходная ситуация (эмулятор гигаибтной сетевой карты):
# tc qdisc del root dev eth1 # iperf3 -t5 -4c 10.1.1.2
Понизим пропускную способность до мегабита в секунду:
# tc qdisc add dev eth1 root tbf rate 1mbit burst 32kbit latency 400ms # tc qdisc show # iperf3 -t5 -4c 10.1.1.2
- Не всё ровненько, где-то 0, где-то x2 (интересно, почему?)
К сожалению, наиболее популярную дисциплину — HTB — рассмотреть не успеем. Тема большая.
Д/З
Образ не изменился.
Задание 7
TODO в 2024 году машина B всё ещё называется «shaped», хотя в задании не шейпер, а задержка. Потом поменяю.
- Суть: воспроизвести примеры из лекции, с выходным NAT-ом, пробросом порта и задержкой на интерфейсе.
- Площадка (сетевые адреса и маршруты настроены заранее, в отчёт не входят)
A — адрес shaped
B — адрес client
R — «внешний» (для доступа из srv) адрес router
- Отчёт:
report 7 router
Настроить исходящий NAT на интерфейсе R, который работал бы для A и B (Например, для всей их сети)
Настроить проброс порта 1234 при подключении к R → на порт 1234 адреса B
Запустить tcpdump на «внешнем» интерфейсе, который отловит все пакеты TCP-соединения от client на srv и несколько пакетов ping-а, а затем сам остановится (ключ -c). Если сложно — просто остановите перед продолжением отчёта.
report 7 srv
Принять одно TCP-соединение на порт 1212 (в tcpdump на router-е должно быть видно, что это соединение от R, потому что SNAT)
report 7 shaped
Настроить (с помощью netem) задержку при отсылке пакетов в 200ms
Немного по ping-ать srv (чтобы запущенный там tcpdump остановился)
report 7 client
Отправить несколько строк на порт 1212 машины srv
Запустить ping адреса A (в отчёте должна быть видна задержка ⩾ 200ms)
- Принять одно TCP-соединение на порт 1234
(продолжение отчёта srv)
Отправить несколько строк на порт 1234 адреса R (его должен принять B, потому что DNAT)
Четыре отчёта (названия сохранить, должно быть: report.07.router, report.07.srv, report.07.client, report.07.shaped) переслать одним письмом в качестве приложений на uneexlectures@cs.msu.ru
В теме письма должно встречаться слово LinuxNetwork2024