86. Типы сетей и основные технологии
Устройство, которое выходит в сеть, живёт по её правилам: у него есть адрес, сосед по подсети, шлюз, и кто-то решает, может ли до него достучаться посторонний. Как поднять сокет и веб-сервер, разобрано в разделе 78, какими путями STM32 вообще подключается к сети — в разделе 37.1. Здесь — сама сеть: какие они бывают, как устроены адреса и почему прибор за домашним роутером не ждёт входящих соединений, а звонит сам.
Адресная арифметика раздела написана на C так, чтобы работать на
микроконтроллере, собрана armclang и сверена с независимым эталоном —
модулем ipaddress из стандартной библиотеки Python.
Как это называется в документации
Оригинал Перевод PAN, LAN, MAN, WAN персональная, локальная, городская, глобальная сеть topology: star, bus, ring, mesh топология: звезда, шина, кольцо, ячеистая circuit / packet switching коммутация каналов / пакетов client–server, peer-to-peer клиент-сервер, одноранговая сеть MAC address физический адрес интерфейса subnet mask, prefix (CIDR) маска подсети, длина префикса default gateway шлюз по умолчанию DHCP, DNS, DDNS автонастройка адреса, служба имён, динамическое имя NAT, PAT, port forwarding трансляция адресов, с подменой портов, проброс порта VLAN, ACL, QoS виртуальная сеть, список доступа, качество обслуживания load balancer, reverse proxy балансировщик нагрузки, обратный прокси
86.1 Какие бывают сети
По охвату:
| Сеть | Где | Пример для прибора |
|---|---|---|
| персональная (PAN) | на столе, на теле | браслет и телефон по Bluetooth |
| локальная (LAN) | комната, здание, территория | Ethernet и Wi-Fi цеха или дома |
| городская (MAN) | город | сеть оператора, счётчики района |
| глобальная (WAN) | страна, континент | каналы между филиалами |
| интернет | весь мир | объединение всех сетей |
По способу передачи. В коммутации каналов на время разговора выделяется целый путь — так работала телефония. В коммутации пакетов данные режут на пакеты, и каждый идёт сам; так устроены Ethernet и IP. Широковещательная среда слышна всем (радио, общая шина), в соединении «точка-точка» — только двоим (UART между платами).
По топологии. Звезда — все к одному узлу: коммутатор или точка доступа Wi-Fi. Шина — все на одной паре проводов: CAN (раздел 19) и RS-485. Кольцо — каждый передаёт соседу. Ячеистая (mesh) — каждый связан с несколькими, данные идут в обход вышедших из строя узлов (раздел 89). Топология определяет, что будет, когда откажет узел или провод.
По роли узлов. В схеме клиент-сервер одни узлы запрашивают, другие отвечают. В одноранговой сети все равны.
86.2 Централизация и распределённость
| Централизованная | Децентрализованная | Распределённая | |
|---|---|---|---|
| устройство | один сервер для всех | несколько серверов, каждый — часть системы | все узлы равноправны |
| достоинства | просто, дёшево, данные согласованы | нет одной точки отказа, растёт вширь | самая высокая живучесть |
| недостатки | отказ сервера — отказ всего; растёт с трудом | дороже, узлы надо согласовывать | согласование — самая трудная часть |
| в IoT | приборы и один брокер | несколько брокеров по площадкам | ячеистая сеть датчиков |
Большинство приборов работает по первой схеме: устройство отправляет данные брокеру или серверу (раздел 37.2). Поэтому дальше в разделе — что нужно, чтобы устройство до этого сервера добралось.
86.3 Адрес устройства: MAC и IP
MAC — шесть байт, адрес интерфейса внутри локального сегмента. У Wi-Fi модуля он записан на заводе. У STM32 с Ethernet (F407) заводского MAC нет, и прошивка задаёт его сама. Способа три: купить блок адресов для серии изделий, поставить микросхему памяти с записанным адресом или вывести локально назначенный адрес из уникального номера камня (раздел 79.7):
void mac_from_uid(const uint32_t uid[3], uint8_t mac[6])
{
uint32_t h = 2166136261u, g = 0; /* FNV-1a по 12 байтам номера */
for (int i = 0; i < 12; i++) {
h ^= (uid[i / 4] >> (8 * (i % 4))) & 0xFFu;
h *= 16777619u;
g = g * 31u + h;
}
mac[0] = 0x02;
mac[1] = (uint8_t)(h >> 24);
mac[2] = (uint8_t)(h >> 16);
mac[3] = (uint8_t)(h >> 8);
mac[4] = (uint8_t)h;
mac[5] = (uint8_t)(g ^ (g >> 8) ^ (g >> 16) ^ (g >> 24));
}
Первый байт 0x02 — это два флага: «адрес назначен локально» (бит 1) и
«одиночный, не групповой» (бит 0 сброшен). Остальные пять — свёртка
номера. В проверке 10 000 соседних номеров дали 10 000 разных MAC; номера,
отличающиеся одним битом, — разные адреса. Локальный адрес уникален в
пределах сети, а не мира — для прибора в своей сети этого достаточно, для
массовой серии правильнее купить блок.
IPv4 — 32 бита, записанные четырьмя числами. Адрес делится на две части: номер сети и номер узла в ней. Где проходит граница, задаёт длина префикса (или маска): /24 — первые 24 бита сеть, остальные 8 — узел.
Отсюда частая путаница. При маске 255.255.255.0 первые три числа — это сеть, а последнее — номер узла, а не наоборот. И граница вовсе не обязана проходить по точкам:
| 192.168.1.77 с префиксом | Маска | Сеть | Широковещательный | Узлов |
|---|---|---|---|---|
| /16 | 255.255.0.0 | 192.168.0.0 | 192.168.255.255 | 65 534 |
| /24 | 255.255.255.0 | 192.168.1.0 | 192.168.1.255 | 254 |
| /26 | 255.255.255.192 | 192.168.1.64 | 192.168.1.127 | 62 |
| /30 | 255.255.255.252 | 192.168.1.76 | 192.168.1.79 | 2 |
Адрес сети и широковещательный узлам не раздают — отсюда «минус два». Всё это — несколько битовых операций:
uint32_t ip_mask(unsigned prefix)
{
return prefix == 0 ? 0 : 0xFFFFFFFFu << (32 - prefix);
}
uint32_t ip_network(uint32_t ip, unsigned prefix)
{
return ip & ip_mask(prefix);
}
uint32_t ip_broadcast(uint32_t ip, unsigned prefix)
{
return ip | ~ip_mask(prefix);
}
/* В одной ли подсети два узла: да — пакет идёт напрямую, нет — через шлюз */
int ip_same_subnet(uint32_t a, uint32_t b, unsigned prefix)
{
return ((a ^ b) & ip_mask(prefix)) == 0;
}
Префикс 0 разобран отдельно: сдвиг 32-битного числа на 32 в C не определён (раздел 3а). Последняя функция — то самое решение, которое принимает стек TCP/IP на каждом пакете: 192.168.1.10 и 192.168.1.200 в одной /24 — пакет идёт напрямую; 192.168.2.10 — уже через шлюз, хотя в /16 они были бы соседями. Неверная маска в настройках прибора — и он пытается напрямую достучаться до сервера, который стоит за шлюзом.
Частные адреса. Диапазоны 10.0.0.0/8, 172.16.0.0/12 и 192.168.0.0/16 в интернете не маршрутизируются: это адреса внутренних сетей. Ещё один диапазон, 100.64.0.0/10, — адреса сети оператора, за которой стоит его собственный NAT (так часто подключены сотовые модемы).
int ip_private(uint32_t ip)
{
return (ip >> 24) == 10u /* 10.0.0.0/8 */
|| (ip >> 20) == (172u << 4 | 1u) /* 172.16.0.0/12 */
|| (ip >> 16) == (192u << 8 | 168u); /* 192.168.0.0/16 */
}
86.4 DHCP и DNS
DHCP выдаёт устройству при включении адрес, маску, шлюз и адрес сервера имён. Стеки TCP/IP для микроконтроллеров умеют это из коробки. Если прибор должен всегда находиться по одному адресу, адрес за ним закрепляют на роутере — по MAC. Поэтому MAC и должен быть постоянным: выведенный из номера камня, он не меняется от прошивки к прошивке.
DNS превращает имя в адрес. Сервер, брокер, служба обновлений в прошивке записываются именем, а не адресом: адрес сервера может смениться, имя — нет. DDNS обновляет запись, когда меняется адрес самого узла — для домашнего подключения без постоянного адреса.
86.5 NAT: почему прибор звонит сам
Домашний или офисный роутер выпускает все внутренние устройства в интернет через один внешний адрес. Чтобы различать их, он подменяет порты и помнит, кому что принадлежит:
/* Исходящий пакет: найти или завести запись; вернёт внешний порт, 0 — мест нет */
uint16_t nat_out(nat_t *n, uint32_t ip, uint16_t port)
{
for (int i = 0; i < NAT_SLOTS; i++)
if (n->e[i].used && n->e[i].in_ip == ip && n->e[i].in_port == port)
return n->e[i].out_port;
for (int i = 0; i < NAT_SLOTS; i++)
if (!n->e[i].used) {
n->e[i] = (nat_entry_t){ip, port, n->next_port++, 1};
return n->e[i].out_port;
}
return 0;
}
/* Входящий пакет на внешний порт: кому он? 0 — записи нет, пакет отброшен */
uint32_t nat_in(const nat_t *n, uint16_t out_port, uint16_t *port)
{
for (int i = 0; i < NAT_SLOTS; i++)
if (n->e[i].used && n->e[i].out_port == out_port) {
*port = n->e[i].in_port;
return n->e[i].in_ip;
}
return 0;
}
В модели три устройства — 192.168.1.10, .11 и .12 — вышли в сеть с одного и того же своего порта 5000. Роутер выпустил их через внешние порты 40000, 40001 и 40002; ответ на 40001 вернулся к .11 на порт 5000, а пакет, пришедший на 40005, где записи нет, отброшен.
Последнее — главное для IoT. Запись в таблице появляется только от исходящего пакета. Снаружи до прибора за NAT достучаться нельзя, пока он сам не начал разговор, — а за NAT оператора, в диапазоне 100.64.0.0/10, нельзя даже с пробросом порта на своём роутере. Поэтому:
- прибор сам подключается к брокеру или серверу и держит соединение (MQTT и keep-alive — раздел 37.2): записи в NAT живут, пока по ним идёт трафик, а сколько живут без него — решает роутер (ниже);
- команды на прибор идут по этому же соединению, а не отдельным входящим запросом;
- проброс порта на веб-сервер прибора (раздел 78) выставляет его в интернет всем желающим — без проверки доступа и шифрования так делать нельзя (раздел 37.4).
Сколько живёт запись без трафика. В ядре Linux, на котором работает большинство роутеров, по умолчанию: UDP — 30 с, пока не было ответа, и 120 с после обмена в обе стороны; установленное TCP-соединение — 5 суток. Требования к шлюзам — не меньше 2 минут для UDP и 2 ч 4 мин для TCP, — но у операторов связи, особенно сотовых, записи без трафика нередко снимают через минуты. Поэтому интервал keep-alive берут заметно короче самого короткого срока: для MQTT через сотовую сеть — минута-две (в 37.2 — 60 с), для протоколов на UDP (CoAP, раздел 89) — десятки секунд.
86.6 Остальные термины сетевика
| Технология | Что делает | Зачем разработчику прибора |
|---|---|---|
| VLAN | делит одну физическую сеть на несколько логических | приборы — в своей сети, отдельно от офисных компьютеров |
| ACL | правила «кому куда можно» | прибору можно только к брокеру, больше никуда |
| QoS | приоритет одним видам трафика перед другими | управляющие команды не должны стоять за видео |
| агрегирование каналов | несколько линий как одна | для прибора редко нужно; для серверов — да |
| балансировщик нагрузки | делит запросы между серверами | тысячи приборов не упираются в один сервер |
| прямой прокси | посредник для клиентов | прибор в закрытой сети выходит наружу только через него |
| обратный прокси | посредник перед серверами | принимает соединения приборов, шифрует и раздаёт серверам |
У балансировщика и прокси есть общая оборотная сторона: сами они становятся единой точкой отказа, если не продублированы.
86.7 Грабли
Два прибора из одной партии «воюют» в сети. В прошивке записан один и тот же MAC — у всех устройств одинаковый.
После замены роутера прибор пропал. Адрес был вписан вручную, а новая сеть выдаёт другие.
Прибор видит соседей, но не сервер. Неверная маска или не задан шлюз: прибор считает, что сервер в его подсети, и ищет его напрямую.
Прибор не находит брокер по имени. При ручной настройке забыли сервер имён; DHCP выдал бы его сам.
Сервер не может «достучаться» до прибора. Прибор за NAT ждёт входящего соединения; нужно, чтобы он подключался сам.
Соединение с брокером молча рвётся раз в несколько минут. По нему нет трафика, и роутер удалил запись NAT; нужен keep-alive.
Проброс порта не помогает на сотовом модеме. Модем за NAT оператора. Признак — внешний адрес модема не совпадает с тем, с которого сервер видит подключение; сам адрес бывает из 100.64.0.0/10, но многие операторы выдают и частные 10.x.x.x.
Веб-страница прибора доступна всему интернету. Проброшен порт на прибор без пароля и шифрования.
«Последнее число адреса — номер сети». Наоборот: при /24 последнее число — номер узла, а границу вообще задаёт префикс.
86.8 Итоги
- Сети различают по охвату (от персональной до интернета), по способу передачи, по топологии (звезда, шина, кольцо, ячеистая) и по роли узлов.
- Централизованная схема проста, но имеет одну точку отказа; большинство приборов работает с одним брокером или сервером.
- У STM32 нет заводского MAC: локально назначенный адрес выводят из номера камня, первый байт 0x02.
- Границу сети и узла в IPv4 задаёт префикс: при /24 — 254 узла, при /26 — 62, адрес сети и широковещательный не раздаются.
- DHCP выдаёт адрес, маску, шлюз и сервер имён; серверы в прошивке пишут именами.
- NAT пропускает внутрь только ответы на исходящие пакеты: прибор подключается сам и держит соединение; проброс порта без защиты недопустим.
- VLAN и ACL отделяют приборы от остальной сети и ограничивают, куда им можно.
Дальше: раздел 87 «Виртуализация, облака, контейнеры».