惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 聂微东
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
L
LangChain Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 司徒正美
WordPress大学
WordPress大学
T
The Blog of Author Tim Ferriss
Blog — PlanetScale
Blog — PlanetScale
J
Java Code Geeks
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
GbyAI
GbyAI
Vercel News
Vercel News
大猫的无限游戏
大猫的无限游戏
T
Tailwind CSS Blog
Jina AI
Jina AI
B
Blog
Recorded Future
Recorded Future
MyScale Blog
MyScale Blog
I
InfoQ
aimingoo的专栏
aimingoo的专栏
博客园_首页
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
雷峰网
雷峰网
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
腾讯CDC
爱范儿
爱范儿
Last Week in AI
Last Week in AI
博客园 - 三生石上(FineUI控件)
博客园 - Franky
Schneier on Security
Schneier on Security
V
V2EX
TaoSecurity Blog
TaoSecurity Blog
H
Hacker News: Front Page
Cloudbric
Cloudbric
D
DataBreaches.Net
B
Blog RSS Feed
P
Palo Alto Networks Blog
云风的 BLOG
云风的 BLOG
NISL@THU
NISL@THU
I
Intezer
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Cyberwarzone
Cyberwarzone
F
Fortinet All Blogs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Cybersecurity and Infrastructure Security Agency CISA
C
Cisco Blogs
K
Kaspersky official blog
Forbes - Security
Forbes - Security

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Интернет выключили целиком: офлайн-чат на Bluetooth и Wi-Fi Direct, и почему мы не обещаем mesh на весь город
Iaroslav Tager · 2026-06-07 · via Все публикации подряд на Хабре

Средний

6 мин

16K

Блокировки это одно. Их обходят: VLESS, Reality, прокси, про это уже написано много, в том числе у нас. Но есть сценарий жёстче. Интернета нет вообще. Не «YouTube не открывается», а мобильную сеть увели в ноль, Wi-Fi бесполезен, потому что аплинк перекрыт. Такое включают точечно: митинг, площадь, район, иногда целая страна на несколько часов.

Вопрос простой: могут ли два телефона в этой ситуации всё равно обменяться сообщением. Без вышек, без интернета, без сервера. Ответ: да, но честный ответ длиннее, и в нём много «но». Мы (команда из трёх человек, делаем мессенджер RCQ) собрали для этого режим, который называется Radio. Ниже что он реально умеет, чего не умеет, и какие грабли мы собрали по дороге.

Сначала о честности: «городского mesh» почти не существует

В жанре «мессенджер без интернета» принято обещать mesh: телефоны образуют сеть, сообщение прыгает с устройства на устройство и доходит до адресата на другом конце города, даже если вас разделяют сотни метров. Звучит красиво. На стоковых телефонах это в основном не работает.

Причины приземлённые. У смартфона два коротких радио: Bluetooth и Wi-Fi. Дальность Bluetooth это метры, в лучшем случае десятки метров в прямой видимости. Wi-Fi Direct добивает дальше, но это всё равно прямая связь точка-точка, а не магия. Чтобы сделать настоящий многохоповый mesh, нужно, чтобы на каждом промежуточном телефоне крутился сервис, который принимает чужой трафик, ретранслирует его дальше, делает это в фоне, не сажая батарею в ноль, и при этом не ломается, когда вокруг сотни таких же устройств. Операционные системы фоновую работу с радио душат намеренно, ради той же батареи. История Bridgefy, который продавали протестующим как mesh, а потом исследователи показали, что там и с шифрованием, и с самой mesh-моделью большие проблемы, хороший памятник этим обещаниям.

Поэтому мы сразу решили: не врать. RCQ Radio это не «mesh на весь город». Это связь с теми, кто физически рядом. Один хоп, прямая радиосвязь, небольшой радиус. Внутри этих рамок оно работает честно. За их пределами мы ничего не обещаем.

Два слоя: маячок и труба

Наивная реализация делает всё на одном радио и упирается либо в дальность, либо в полосу, либо в батарею. Мы разнесли задачу на два слоя.

Первый слой это присутствие, «кто рядом». Здесь работает Bluetooth Low Energy. Телефон постоянно шлёт крошечный маячок и слушает чужие. BLE для этого идеален: дёшево по энергии, не требует соединения. На Android мы не берём Google Nearby, а работаем с радио напрямую, через BluetoothLeAdvertiser и BluetoothLeScanner. Плата за дешевизну это размер: в legacy-рекламу BLE влезает около 24 байт полезных данных. В них надо упаковать магический префикс, версию, флаги (комната или личный чат, есть ли пароль), короткий идентификатор сессии и обрезанное имя. Полное имя долетает уже после соединения, отдельным кадром.

Второй слой это сами данные. Здесь нужна полоса, а не экономия, поэтому включается Wi-Fi Direct. На Android это WifiP2pManager: одно устройство становится владельцем группы, поднимает у себя TCP-сокет (у нас порт 8989, кадры с префиксом длины, потолок 512 КБ на кадр), остальные подключаются к нему. Обнаружение внутри группы идёт через DNS-SD с TXT-записью, в которой лежит идентификатор сессии. На iOS мы не дёргаем эти примитивы вручную, а берём Apple MultipeerConnectivity (MCSession, тип сервиса rcq-radio), который сам жонглирует комбинацией Wi-Fi и Bluetooth под капотом.

Разделение простое: BLE отвечает на вопрос «кто вокруг», Wi-Fi Direct и MultipeerConnectivity тащат полезную нагрузку.

Топология: звезда, а не паутина

Это самый важный технический факт, и мы проговариваем его прямо. Топология у Radio это звезда с одним центром, а не многохоповая паутина.

Когда вы создаёте комнату или зовёте человека в личный чат, ваш телефон становится центром: владельцем Wi-Fi Direct группы на Android или хостом сессии на iOS. Все остальные подключаются напрямую к нему. Центр получает кадр от одного участника и рассылает его остальным, кто подключён к нему же. Всё. Никакого TTL, никакого флуда, никакой пересылки «дальше по цепочке». Устройство, которое не подключено к центру напрямую, в разговоре не участвует. Комнаты маленькие (на iOS потолок 8 участников).

Радиус это радиус прямой связи: метры для Bluetooth, до сотни метров в прямой видимости для Wi-Fi Direct. Этого хватает на этаж, на двор, на вагон, на небольшую площадь. Этого не хватает, чтобы дотянуться через район. И мы не делаем вид, что хватает.

Можно было бы попробовать собрать многохоп самим, поверх этих же радио. Мы сознательно не стали, и не только из-за батареи и фоновых ограничений ОС. У многохопа есть цена, о которой в рекламе mesh молчат: промежуточный узел это телефон постороннего человека, через который идёт ваш трафик. Он его пересылает, видит факт пересылки, может его придержать или подменить, становится точкой для спама и для деанона по тому, кто рядом с кем оказался. Чтобы сделать это безопасно, нужна целая модель доверия к незнакомым ретрансляторам, и на стоковых телефонах она быстро превращается в фикцию. Честный один хоп, где вы видите, к кому именно подключились, нам кажется более правдивым, чем красивая паутина, которой нельзя доверять.

Шифрование без сервера

В обычном режиме RCQ шифрует переписку через libsignal с forward secrecy. Но libsignal по дизайну опирается на сервер: там лежат prekey-бандлы, через них устройства делают первичный обмен. В офлайне сервера нет. Значит, для Radio нужен отдельный путь, и он есть.

Личный чат: оба устройства генерируют эфемерную пару ключей Curve25519, обмениваются публичными ключами в открытую (на iOS это едет в invitation-контексте MultipeerConnectivity), считают общий секрет через ECDH, прогоняют его через HKDF-SHA256 с info-строкой rcq-radio-1to1 для доменного разделения. На выходе 32-байтный ключ AES.

Комнаты: открытая комната выводит ключ как SHA256 от идентификатора комнаты, кто увидел строку, тот и зашёл. Комната с паролем выводит ключ через PBKDF2-SHA256, 100 тысяч итераций, солью служит идентификатор комнаты (около 200 мс на iPhone 12). Проверка пароля честная и неявная: пока первый кадр от хоста не расшифровался, вы «зашли, но в муте». Расшифровался, значит ключ совпал, вы в комнате. Не расшифровался, значит пароль не тот, вас выкидывает.

Само сообщение запечатывается в AES-GCM: 12-байтный одноразовый nonce на каждое сообщение, 128-битный тег аутентификации. На обеих платформах одна и та же схема (rcq-radio-1to1, те же параметры комнат), хотя транспорты разные.

Два важных следствия. Первое: UIN, ваша личность в сети RCQ, в эфир не уходит вообще. В радиоэфире вас видно как четырёхбайтный эфемерный идентификатор сессии и анонимное имя-метку. Второе: ничего не оседает на диск. Сообщения Radio живут только в оперативной памяти сессии, в основную базу не пишутся, разорвалась связь и переписки нет нигде. Это сознательно: офлайн-разговор не оставляет следа.

Грабли по дороге

24 байта это очень мало. Первая версия упаковки маячка не влезала в бюджет legacy-рекламы BLE, и часть устройств её просто не показывала. Пришлось резать всё до минимума и принять, что в маячке едет огрызок имени, а полное имя досылается после соединения.

Wi-Fi Direct это диалог с пользователем. Формирование группы на Android требует согласия через системный диалог, и переговоры о том, кто станет владельцем группы, идут не мгновенно. На iOS отдельная боль была с приглашениями MultipeerConnectivity. Если приглашение «повисало» (пользователь смахнул шит, не нажав ни «принять», ни «отклонить»), сторона-инициатор сидела в состоянии .connecting до 30-секундного таймаута, а потом схлопывалась в «УШЁЛ». Именно этот симптом нам и приносили тестеры. Лечится тем, что любой не-обработанный явно invite мы теперь авто-отклоняем, чтобы транспорт не висел.

Эмулятор бесполезен. У эмулятора нет ни BLE-радио, ни Wi-Fi Direct, ни MultipeerConnectivity. Крипто-слой мы покрыли юнит-тестами (симметрия ECDH, round-trip seal/open, детерминизм ключей комнаты, отсев по паролю проходят на устройстве). Но весь транспорт проверяется только так: берёшь два настоящих телефона и идёшь с ними по коридору, проверяя, на каком расстоянии связь рвётся.

Платформы не дружат между собой. Android-Radio построен на сыром BLE плюс WifiP2pManager, iOS-Radio на MultipeerConnectivity. Это разные стеки, которые между собой не стыкуются на уровне транспорта. Поэтому пока Radio работает в пределах одной платформы: Android с Android, iOS с iOS. Кросс-платформенный мост это отдельная большая задача, и обещать её сейчас мы не будем.

Бонусом по той же Wi-Fi Direct трубе работает push-to-talk голос (сырой PCM, 16 кГц, кадрами по 40 мс), рация в чистом виде. Полоса локальной сети это позволяет.

Что это НЕ решает

Раздел, без которого статья была бы рекламой.

  • Это не обход блокировок на расстоянии. Если вы и собеседник в разных частях города, Radio не поможет, ему нужна прямая радиосвязь. Для «интернет есть, но всё заблокировано» у нас другой механизм (VLESS и Reality внутри приложения), это про другое.

  • Это не многохоповый mesh. Сообщение не путешествует через чужие телефоны. Один хоп, и точка.

  • Метаданные присутствия видны. Любой с BLE-сканером рядом увидит, что какое-то устройство RCQ светит маячок, и анонимную метку-имя. Содержимое зашифровано AES-GCM, но сам факт «тут кто-то есть в эфире» по радио не спрячешь.

  • Батарея. Постоянное BLE-сканирование плюс активная Wi-Fi Direct группа греют телефон и сажают заряд. Это режим «когда нужно», а не «всегда включено».

  • Аудита у нас не было. Схему мы описываем честно, но независимой проверки третьей стороной не проходили. iOS-клиент открыт под AGPL-3.0, код можно читать.

Когда оно реально полезно

Не «вместо интернета всегда», а в конкретных дырах. Площадь или район, где сеть увели в ноль, а люди стоят рядом. Этаж здания, подвал, бункер, куда не достаёт ни одна вышка. Самолёт, поезд, глухой поход. Фестиваль, где сота перегружена и не отвечает. Везде, где люди физически близко, а инфраструктуры нет.

Внутри этих рамок два телефона RCQ всё равно поговорят: личным чатом или комнатой, с шифрованием, без сервера и без следа на диске. За этими рамками мы вам ничего не обещаем, и считаем, что честно сказать об этом важнее, чем нарисовать на коробке слово «mesh».

Android-клиент уже в проде, режим Radio в нём есть. iOS идёт через TestFlight. Ссылки и исходники iOS (AGPL-3.0) на rcq.app.