Интерфейсный уровень и его представление
Задачи интерфейсного уровня:
Подключение среды передачи данных к устройству (собственно интерфейс)
- Как отличить данные от не-данных (или начало от середины)?
- Метаинформация
Дисциплина использования среды
- Очерёдность, коллизии, приоритеты и т. п.
- Защита данных и авторизация абонента
Инкапсуляция на физическом уровне (то, чего на интерфейсном уровне не видно):
- Заворачивание фрейма в маркеры начала и конца / межфреймовый заполнитель
- Избыточность при кодировании (борьба с шумом на аппаратном уровне: payload vs overhead)
Ethernet:
- в действительности 10*31 + 11, потому что старший бит октета — последний
Interpacket_gap (12 октетов) пропуска
Пример принципиально иной дисциплины доступа: Token Ring
Фреймы (пакеты интерфейсного уровня)
Сеть с разделением пакетов (окончательно)
Состав фрейма:
- Паспорт (ID отправителя и получателя, сведения о топологии, всякое)
- Полезная нагрузка
- Контрольная сумма (нужно ли больше избыточного кодирования?)
- Данные по шифрованию / авторизации
Ethernet
Общая среда ⇒
- ID отправителя и получателя
Алгоритм доступа: неодновременный
- определение идущей передачи (CSMA)
- определение работоспособности сети
- определение коллизий (CD) — если всё-таки более одного устройства начало передачу
случайная задержка перед повторной передачей
- +увеличение в 2 раза при повторной ошибке
- общий тайм-аут
- определение идущей передачи (CSMA)
⇒ Нет гарантированного времени доставки
Linux
ethtool — взаимодействие с аппаратным уровнем
iproute2 — основной инструмент настройки
ip link (поднятие, останов, свойства)
tcpdump — основной инструмент анализа
Link-level: tcpdump -e
Настройка внутренней сети в VBox
- Типы сетей в VB
- «Внутренняя» появляется просто по факту наименования — это общая среда
- «Втыкание провода» и «неразборчивый режим»
Название firstnet — произвольное
- Из командной строки:
$ VBoxManage modifyvm srv --nic2 intnet --intnet2 firstnet --cableconnected2 on
Проверка работоспособности
2 клона (не забываем: другие MAC-адреса всем интерфейсам)
- Просмотр интерфейсов:
# ip link
- Активация («поднятие») интерфейса
# ip link set eth1 up
- На одной машине:
# tcpdump -XXe -i eth1
-XX означает выводить шестнадцатеричный дамп всего фрейма
На другой машине: # echo "08:00:27:ab:cd:ef 08:00:27:fe:dc:ba 8102 48 69" | xxd -r -p | socat - INTERFACE:eth1
08:00:27:ab:cd:ef — MAC-адрес получателя
08:00:27:fe:dc:ba — MAC-адрес отправителя
8102 — Тип содержимого (IP-пакет, но у нас он неправильный)
48 69 — «Hi»
xxd -r -p — вырезает из входного текста всё, кроме шестнадцатеричных цифр, остальное преобразует в байты (операция, противоположная шестнадцатеричному дампу)
socat - INTERFACE:eth1 — запихивает получившийся фрейм в интерфейс eth1
Минимальный размер фрейма — 64 октета (включая 4 октета контрольной суммы, которая формируется / проверяется аппаратно и не выводится).
Если вместо -XX написать -X, увидим только payload — «Hi».
Если запустить tcpdump с добавочным ключом -p, то:
- Не будет включён promiscuous mode ⇒ если поменять MAC получателя, фрейм не дойдёт
- Вариант: поставить широковещательного получателя ff:ff:ff:ff:ff:ff
- А вот MAC отправителя может быть любой ☺
Протоколы интерфейсного уровня
Вообще-то Тысячи их
Wi-Fi
Например, IEEE 802.11g
- Воздух: затухание и вариабельность сигнала ⇒ избыточность
- Совместный доступ:
- Несколько «каналов»
OFDM (FDM+ортогональность)
…
- Воздух общий ⇒ авторизация/шифрование
WIFI в Linux
(На всякий случай — в конце лекции) Взято отсюда. См. также
rfkill
ip link set wlan0 up
iw wlan0 scan
iw wlan0 link
(stty -echo; wpa_passphrase) > config
wpa_supplicant -B -i wlan0 -c config
iw wlan0 link
dhcpcd wlan0
TUN/TAP
Отступление о screen: как запустить два шелла в одной консоли:
«Горячая клавиша» Ctrl+A
- Два сеанса:
Разбить одно горизонтально на два: Ctrl+A S (от «Split»)
Переключение между окнами: Ctrl+A Tab
Заведение нового сеанса Ctrl+A c (от «create»)
(переключение между сеансами Ctrl+A Ctrl+A)
- …
«Горячая клавиша» Ctrl+B
Разбить одно горизонтально на два: Ctrl+B "
Переключение между окнами: Ctrl+B O
TODO
Виртуальный интерфейс tap.
Если открыть устройство /dev/net/tun и применить к нему ioctl() TUNSETIFF (подробнее тут), заведётся виртуальный сетевой интерфейс (по умолчанию tap0).
# socat TUN,up,tun-type=tap - | hexdump -C`
После этого им можно пользоваться как сетевым интерфейсом — слать туда фреймы и получать их оттуда: * В этот интерфейс можно заслать фрейм
# ip link` — появился интерфейс `tap0` # cal | socat - INTERFACE:tap0
Вручную сложнее всего вызвать этот самый ioctl. Вот программа tapdump.py:
1 import struct
2 import sys
3 import fcntl
4 import binascii
5
6 IFNAMSIZ = 16
7 IFREQSIZ = 40
8 TUNSETIFF = 0x400454ca
9
10 fformat = f"{IFNAMSIZ}sH{IFREQSIZ-2-IFNAMSIZ}s"
11 sflags = """
12 #define IFF_TUN 0x0001
13 #define IFF_TAP 0x0002
14 #define IFF_NAPI 0x0010
15 #define IFF_NAPI_FRAGS 0x0020
16 #define IFF_NO_CARRIER 0x0040
17 #define IFF_NO_PI 0x1000
18 #define IFF_ONE_QUEUE 0x2000
19 #define IFF_VNET_HDR 0x4000
20 #define IFF_TUN_EXCL 0x8000
21 #define IFF_MULTI_QUEUE 0x0100
22 #define IFF_ATTACH_QUEUE 0x0200
23 #define IFF_DETACH_QUEUE 0x0400
24 #define IFF_PERSIST 0x0800
25 #define IFF_NOFILTER 0x1000
26 """.strip().split()
27 fflags = {sflags[i+1]: int(sflags[i+2], 16) for i in range(0, len(sflags), 3)}
28
29 ifname = sys.argv[1] if len(sys.argv) > 1 else "tap0"
30 fd = open("/dev/net/tun", "rb")
31 print(fflags)
32 ifreq = struct.pack(fformat, ifname.encode(), fflags["IFF_TAP"], b'')
33 print(binascii.hexlify(ifreq, ' '))
34 fcntl.ioctl(fd, TUNSETIFF, ifreq)
35 while s := fd.read(128):
36 print(s.decode())
В одном окне запускаем python3 tapdump.py
В другом — поднимаем появившийся интерфейс ip link set tap0 up и снова cal | socat - INTERFACE:tap0
Ежели совсем руками, можно воспользоваться утилитой ioctl (в составе дистрибутивов ALT она пропатчена специально для нас!)
В первом окне вручную заведём tap0 и запустим на нём tcpdump:
# ip tuntap add mode tap name tap0 # ip link set tap0 up # tcpdump -XXe -i tap0
В другом — вызовем утилиту ioctl (параметры там такие: 16 байт имя с нулями, 4 байта флаги и ещё 20 байт нулей) и выведем содержимое фрейма. Некоторая сложность — в том, что и ioctl(), и вывод надо делать на один раз открытое устройство
# ( ( printf "tap0"; printf "%024d0210%044d" 0 0 | xxd -r -p ) | ioctl 3 TUNSETIFF -s 40; date >&3 ) 3> /dev/net/tun
TODO если успеем — socat на двух интерфейсах и IP на них
Д/З
Новый Образ
Добавлен Tmux
Задание 2
Воспроизвести пример из лекции с двумя виртуалками, объединёнными внутренней сетью
- Настроить в самом virtualbox общую виртуальную сеть
- Сделать два клона (base и second) и настроить на обеих машинах «Адаптер 2» как подключённый к некоторой одинаковой сети
- Отчёты:
На базовой машине (report 2 base)
- Поднять сетевой интерфейс, к которому подключена виртуальная сеть
Запустить tcpdump -p -XX -c 2 на этот интерфейс; дождаться окончания
На дублёре (report 2 second)
- Поднять сетевой интерфейс, к которому подключена виртуальная сеть
Трижды сгенерировать и отправить фрейм с помощью xxd + socat по примеру из лекции (payload может быть любым не длиннее 40 символов)
- MAC отправителя и MAC получателя должны совпадать с актуальными
MAC получателя должен не совпадать с актуальным
MAC получателя должен совпадать с актуальным, а MAC отправителя — нет
Оба отчёта (report.02.base и report.02.second) именно с такими названиями переслать одним письмом в качестве приложений на uneexlectures@cs.msu.ru
В теме письма должно встречаться слово LinuxNetwork2025