Транспортный уровень: трансляция адресов и формирование трафика
Ещё про 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
TODO Пример клиент1 → сервер DNAT → сервер
Обход NAT с помощью STUN (на примере UDP)
Проблема: клиент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.
(если успеем) Простой пример для linux
Площадка: client - nat2[NAT:10.3.0.4] - stun - [NAT:10.2.0.2]nat1 - srv
EPort по умолчанию совпадает с IPort, если нет конфликтов (и известен заранее)
«Стартовый» пакет (5) и (6) создаёт conntrack-запись не должен дойти до абонента (иначе отправителю вернётся либо «ответ», либо icmp-reject, и правило удалится), для этого выcтавляем ttl=2
Никакого обмена с координатором (stun) не происходит; он нужен только для того, чтобы пакеты с ttl=2 не доходили до
Настройка:
nat1 и nat2:
# iptables -t nat -A postrouting -o eth2 -j MASQUERADE
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
TCP: а что делать с seqn? А ничего, не работает TCP ☹
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 — рассмотреть не успеем. Тема большая.
Д/З
Изменения в образе:
После обновления пакетной базы пришлось переписать sethostname
autonet и sethostname теперь вместо dmidecode используют /sys/class/dmi/id
Задание 7
- Суть: воспроизвести примеры из лекции, с выходным NAT-ом, пробросом порта и задержкой на интерфейсе.
- Площадка (сетевые адреса и маршруты настроены заранее, в отчёт не входят)
A — адрес delayed
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 delayed
Настроить (с помощью 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.delayed) переслать одним письмом в качестве приложений на uneexlectures@cs.msu.ru
В теме письма должно встречаться слово LinuxNetwork2025