РоссияНовостьМодели
Очумелые ручки с Чижиком, выпуск №1: как мы поселили KVN прямо в старый телевизор LG
Содержание
- Вместо вступления: телевизор еще хороший, а интернет в нем уже не очень
- Серия первая: телевизор нашёлся, лёгких путей не нашлось
- Попытка №1: OpenKVN
- Попытка №2: WireGuard
- Короткое свидание со strongSwan
- Подсказка пришла с компьютера
- Что в итоге построил Чижик
- Шаг 1. Подбираем бинарник под телевизор
- Шаг 2. Маршрутизация
- Шаг 4. Делаем кнопку, которой можно доверять
- Шаг 5. Автозапуск
- Серия с черным экраном
- Шаг 6. Убираем за собой
- Что получилось
- Сколько Чижиков нужно, чтобы настроить телевизор
- Что я бы улучшил во второй версии
- Предупреждение для тех, кто уже потянулся за паяльником
Дома я постоянно что-нибудь мастерю, переделываю и пытаюсь заставить работать немного не так, как задумывал производитель. Где-то хочется оживить старое устройство, где-то - связать между собой две вещи, которые официально друг о друге ничего не знают, а иногда просто интересно проверить: «А что будет, если?» В последнее время почти во всех этих затеях мне помогает Чижик. Причем не в формате «спросил у чат-бота, получил пять общих советов и пошел разбираться сам». Мы вместе исследуем устройства, читаем логи, пишем небольшие программы, собираем приложения, проверяем гипотезы и временами долго выясняем, почему одна пропущенная строчка превращает телевизор в задумчивый черный прямоугольник.
Ах да, действующие лица:
Head of SEO & web-аналитики, Тензор (разработчик saby.ru), автор ТГ‑канал «ВладПРО»
Я более 10 лет занимаюсь аналитикой, SEO и управлением командами в digital‑маркетинге. А в своем Телеграм канале и на сайте пишу еще больше про всякое из реального маркетинга. Консультирую по аналитике web‑проектов и настройке инструментов маркетинга, помогаю проводить технические собеседования специалистов по различным типам трафика.
ChatGPT Codex
Домашняя разновидность искусственного интеллекта. Живет в терминале, питается логами и токенами. Имя получилось из согласных букв ChatGPT Codex — Ч-Ж-К. Если немного воображения, выходит Чижик. Если воображения совсем много - инженер по всякому куда можно подключиться по сети и чего-нибудь накодить.
Постепенно таких домашних историй накопилось достаточно много, и я решил ими делиться. Не как идеально вылизанными инструкциями из параллельной вселенной, где все работает с первой попытки, а как кейсами: с исходной проблемой, неудачными подходами, диалогом, диагностикой и конечным результатом.
Возможно, кто-то найдет здесь готовую идею для собственного дома. Кто-то подсмотрит полезный технический прием. А кто-то просто поймет, что ChatGPT Codex можно применять не только для написания очередной функции в рабочем проекте. Иногда ему можно показать старый телевизор, дать доступ к терминалу и спросить: «Чижик, а мы вообще можем с этим что-нибудь сделать?»
Если по ходу чтения у вас появятся идеи, как улучшить описанное решение, - приносите их в комментарии. Туда же можно складывать предложения для следующих экспериментов: что еще попробовать автоматизировать, оживить, связать или убедить работать вопреки документации. Самые интересные варианты мы с Чижиком постараемся проверить на практике - если, конечно, после эксперимента дом все еще будет подключаться к интернету.
Так рождается серия «Очумелые ручки с Чижиком». И начать я решил с телевизора.
Вместо вступления: телевизор еще хороший, а интернет в нем уже не очень
У меня есть телевизор LG на webOS. Не музейный экспонат: показывает хорошо, пульт работает, YouTube установлен, экран менять совершенно не хочется. Но возраст у телевизора уже чувствуется. Браузер стал капризным, современные сайты открывает через раз. Официально приложение YouTube на месте. Кнопка есть. Никто в телевизоре не написал огромными буквами «нельзя». Но видео либо не запускается, либо приложение смотрит на меня черным экраном.
Можно было настроить KVN на роутере. Но мне не хотелось:
- отправлять через него всю домашнюю сеть;
- менять рабочую конфигурацию роутера ради одного устройства;
- объяснять остальным домашним, почему после моего эксперимента чайник видит себя в Нидерландах;
- покупать новый роутер или отдельную приставку, пока старый телевизор технически исправен.
Хотелось простого пользовательского сценария:
- Открыть на телевизоре отдельное приложение.
- Нажать «Подключить».
- Запустить YouTube.
- После просмотра нажать «Отключить».
И я позвал Чижика.
У Чижика есть одна раздражающая, но полезная привычка: перед каждым эффектным техническим решением он пытается выяснить ограничения. Так обнаружились четыре важных обстоятельства.
- Телевизор работает на webOS 5, а не на Android TV. APK сюда не поставить.
- Владелец телевизора разрешил root-доступ, но только на время установки и диагностики.
- Рабочий профиль использует VLESS/TCP/REALITY.
- Подключение должно включаться только вручную из приложения.
Последний пункт оказался важным. Поднять туннель при загрузке - легко. Сделать так, чтобы пожилой телевизор загружался как обычно, а специальный маршрут появлялся только по команде с пульта, - уже интереснее.
Серия первая: телевизор нашёлся, лёгких путей не нашлось
Для начала я включил на LG опцию «LG Connect Apps / Подключение мобильных устройств». После этого телевизор стал доступен для штатного управления по локальной сети.
Чижик нашел устройство, выполнил сопряжение и проверил, что может открыть приложение и отправить на телевизор нажатие кнопки. Это еще не root и не взлом. Это обычный интерфейс управления webOS - тот же класс возможностей, которым пользуются мобильные пульты.
Сначала мы прошли по очевидной лестнице решений.
Попытка №1: OpenKVN
У меня уже был готовый профиль. Мы установили клиент, импортировали конфигурацию, ввели учетные данные и нажали Connect. Телевизор некоторое время показывал Checking, после чего снова предлагал подключиться.
Влад:
Он подумал и передумал. Это считается прогрессом?
Чижик:
Безусловно. До этого он даже не думал.
Проверка показала: сама конфигурация синтаксически нормальная, но транспорт до сервера в этой сети не устанавливается. Причина могла находиться снаружи телевизора: фильтрация протокола, особенности маршрута или несовместимость конкретной сборки клиента. Тратить вечность на протокол, который уже на старте не проходит проверку, не стали.
Попытка №2: WireGuard
Следом попробовали профиль WireGuard. Он проще и обычно быстрее, но в нашем случае стабильного соединения тоже не получилось. Наличие красивого конфигурационного файла еще не означает, что пакеты доберутся до второй стороны.
Короткое свидание со strongSwan
В списке кандидатов появился IPsec/strongSwan. Теоретически солидно: взрослый протокол, серьезное название, можно произносить с каменным лицом. Практически на старом webOS это означало бы еще один чужеродный демон, отдельную работу с политиками IPsec и больше движущихся деталей, чем требовалось для одного приложения.
Эту ветку мы не стали превращать в основную. Инженерная зрелость иногда состоит не в том, чтобы собрать еще один комбайн, а в том, чтобы вовремя убрать отвертку.
Подсказка пришла с компьютера
На компьютере рабочее соединение через VLESS/TCP/REALITY работало стабильно. Значит, задача стала конкретнее: не «найти любой KVN для webOS», а перенести на телевизор именно тот транспорт, который уже проходит через сеть. Для этого подошёл sing-box: один исполняемый файл, поддержка нужного протокола, TUN-интерфейс и возможность работать без тяжелой графической оболочки.
Что в итоге построил Чижик
Влад: Давай, Чижик, вещай, тебе слово!
Чижик: Огромное, тебе, человеческое спасибо, хозяин, рассказываю:
Получилась не одна программа, а маленький слоеный пирог:
Почему не дать web-приложению сразу выполнять команды root? Потому что приложение с кнопками не должно быть универсальным пультом от всей операционной системы. Между интерфейсом и root-командами появился крошечный контроллер с тремя жестко заданными действиями. Никакого /exec?command=..., никакого терминала через HTTP.
Теперь разберем слои по порядку.
Шаг 1. Подбираем бинарник под телевизор
Внутри телевизора обнаружился ARMv7. Обычная сборка для x86_64, конечно, не запустилась бы: процессор не оценил бы оптимизма. Мы взяли статическую ARMv7-сборку sing-box, проверили контрольную сумму и положили все в отдельный каталог:
var/lib/webosbrew/sing-box/
sing-box
config.json
start.sh
stop.sh
status.sh
supervisor.sh
vless-controlПрава тоже имеют значение:
chmod 700 /var/lib/webosbrew/sing-box/sing-box
chmod 700 /var/lib/webosbrew/sing-box/*.sh
chmod 600 /var/lib/webosbrew/sing-box/config.jsonКонфигурация содержит адрес сервера, идентификатор клиента и параметры REALITY. В статье их, разумеется, нет. Публиковать действующий ключ в руководстве, уж извольте.
Обезличенная структура выглядела примерно так:
{
"log": {
"level": "info"
},
"inbounds": [
{
"type": "tun",
"tag": "tun-in",
"interface_name": "sb0",
"address": ["172.19.0.1/30"],
"mtu": 1400,
"auto_route": false,
"stack": "gvisor"
}
],
"outbounds": [
{
"type": "vless",
"tag": "proxy",
"server": "<адрес-сервера>",
"server_port": 443,
"uuid": "<секрет>",
"flow": "xtls-rprx-vision",
"tls": {
"enabled": true,
"server_name": "<имя-сервера>",
"utls": {
"enabled": true,
"fingerprint": "chrome"
},
"reality": {
"enabled": true,
"public_key": "<публичный-ключ>",
"short_id": "<short-id>"
}
}
}
],
"route": {
"final": "proxy"
}
}Почему auto_route: false? На обычном современном Linux автоматическое создание маршрутов могло бы сработать сразу. На старом webOS оно вело себя нестабильно. Поэтому я отключил магию и перешел к ручному труду - то есть написал еще один скрипт.
Шаг 2. Маршрутизация
После запуска sing-box создавался интерфейс sb0. Но существование интерфейса еще не означает, что телевизор начнет им пользоваться.
Нужно было:
- Запомнить исходный шлюз и сетевой интерфейс.
- Оставить отдельный прямой маршрут до KVN-сервера.
- Поднять sb0.
- Направить через него остальной IPv4-трафик.
Логика скрипта в упрощённом виде:
DEFAULT_GW="$(ip route show default | awk 'NR==1 {print $3}')"
DEFAULT_DEV="$(ip route show default | awk 'NR==1 {print $5}')"
# Сначала сохраняем путь до самого сервера снаружи туннеля.
ip route replace <IP-СЕРВЕРА>/32 via "$DEFAULT_GW" dev "$DEFAULT_DEV"
ip link set sb0 up
# Две половины интернета. Вместе дают 0.0.0.0/0,
# но не уничтожают исходный default route.
ip route replace 0.0.0.0/1 dev sb0
ip route replace 128.0.0.0/1 dev sb0
```Трюк с двумя маршрутами /1 удобен тем, что они специфичнее стандартного маршрута /0, поэтому весь обычный IPv4-трафик идет в туннель. При этом исходный default route остается на месте и его легко вернуть в работу, удалив два временных правила.
Отдельный /32 до сервера принципиален. Если сначала завернуть вообще все в sb0, соединение с сервером попытается пройти через еще не установленное соединение с сервером. Получится сетевой вариант инструкции «подними себя за волосы».
При отключении порядок обратный:
ip route del 0.0.0.0/1 dev sb0 2>/dev/null || true
ip route del 128.0.0.0/1 dev sb0 2>/dev/null || true
ip route del <IP-СЕРВЕРА>/32 2>/dev/null || trueПосле этого sing-box завершается, а телевизор снова использует обычный маршрут через роутер.
Шаг 3. Почему одного start.sh оказалось мало
Первый вариант был почти прекрасен: запускаем процесс, ждем интерфейс, добавляем маршруты. На тесте работает. После перезагрузки - уже не совсем.
Пожилой webOS внес драматургию:
- процесс мог стартовать раньше, чем интерфейс был готов;
- sb0 существовал, но еще не был поднят;
- приложение считало, что команда выполнена, хотя внешний адрес не изменился;
- фоновый процесс зависел от стандартного ввода породившей его оболочки.
Так появился supervisor.sh. Он не просто запускает бинарник, а проверяет результат:
запустить sing-box ↓
дождаться появления sb0 ↓
поднять интерфейс ↓
установить маршруты ↓
выполнить HTTPS-проверку наружу ↓
успех → connected
ошибка → удалить маршруты и остановить процессКритическая мелочь в start.sh выглядела так:
nohup "$BASE/supervisor.sh" </dev/null >>"$BASE/supervisor.log" 2>&1 &Именно </dev/null отвязал фоновый процесс от терминальной сессии. Без него ручной запуск проходил нормально, а запуск из приложения иногда оставлял систему в состоянии «вроде начали, но никто не знает, кто теперь отвечает».
status.sh не доверял одному PID-файлу. Статус connected выдавался только тогда, когда одновременно выполнялись несколько условий:
- процесс sing-box жив;
- интерфейс sb0 поднят;
- оба маршрута /1 присутствуют;
- контрольный HTTPS-запрос проходит через новый внешний маршрут.
Это важный урок всей затеи: надпись «процесс запущен» и работающая сеть - не одно и то же.
Шаг 4. Делаем кнопку, которой можно доверять
webOS-приложение - это HTML, CSS и JavaScript. Для интерфейса из двух кнопок этого более чем достаточно. Но web-страница не должна напрямую править таблицу маршрутизации. Поэтому Я написал небольшой контроллер на Go. Он слушает только loopback:
const (
address = "127.0.0.1:18081"
baseDir = "/var/lib/webosbrew/sing-box/"
)У него всего три метода:
GET /start
GET /stop
GET /statusДля запуска разрешены только два заранее известных файла:
func launchScript(name string) error {
if name != "start.sh" && name != "stop.sh" {
return errors.New("invalid script")
}
// запуск фиксированного скрипта
}Контроллер нельзя вызвать с другого компьютера в локальной сети: 127.0.0.1 доступен только самому телевизору. Передать ему произвольную shell-команду тоже нельзя.
Само приложение опрашивает состояние раз в две секунды и показывает один из трех вариантов:
- Отключено;
- Подключение…;
- Подключено.
Кнопка с пульта вызывает локальный запрос:
request.open(
"GET",
"http://127.0.0.1:18081/" + method + "?t=" + Date.now(),
true
);Чижик: Получилось приложение с человеческим интерфейсом. В самый раз для моего бестолкового хозяина, который в этой мути все равно ничего не понимает!
Влад: Не, ну ты серьезно? Ты думал, что я не прочитаю, прежде чем выкладывать. Оставил специально, пусть люди полюбуются на твое поведение, мерзкий Иишный, птыц!
Чижик: извини, хозяин, немного заигрался в бога!
Шаг 5. Автозапуск
Здесь мы специально разделили две вещи:
- локальный контроллер запускается вместе с телевизором;
- KVN-соединение не запускается вместе с телевизором.
В загрузочную последовательность добавился только vless-control. Он занимает несколько мегабайт памяти и ждет команды на loopback. sing-box, интерфейс sb0 и дополнительные маршруты появляются лишь после нажатия «Подключить».
Влад:
Мне не нужно автоматически. Я сам хочу включать и отключать.
Чижик:
Принято. Автоматизировано будет ровно то, что избавляет от рутины, а не то, что отнимает управление.
Так телевизор после обычной перезагрузки выходит в сеть как раньше. Если нужен YouTube - открываем наше приложение, подключаемся и лишь затем запускаем YouTube.
Серия с черным экраном
На этом месте в хорошем техническом тексте положено написать: «Все заработало с первого раза». Поэтому расскажу, как было на самом деле. Соединение показывало статус «Подключено». Внешний адрес изменился. Я запустил YouTube - и увидел черный экран.
Влад:
Пишет, что подключено. YouTube висит. Почему?
Чижик:
Сейчас выясним, врёт ли наша кнопка, не работает ли DNS или YouTube держится за старое сетевое соединение.
Мы проверили по отдельности основные узлы:
www.youtube.com/generate_204 → 204
www.youtube.com/ → 200
youtubei.googleapis.com/... → 204
i.ytimg.com/... → 204То есть:
- DNS разрешает имена;
- TLS-соединения устанавливаются;
- основной сайт доступен;
- API и сервер изображений отвечают;
- трафик действительно идет через новый маршрут.
На подозрении оставались QUIC по UDP/443, IPv6 и уже открытые сетевые сокеты приложения. Можно было немедленно начать блокировать UDP, менять MTU и отключать IPv6 - настоящее веселье с большим количеством побочных эффектов. Но сначала мы выбрали самый дешевый эксперимент: полностью закрыли YouTube и запустили его после установки туннеля.
YouTube открылся.
Судя по результатам проверки, приложение удерживало старое сетевое состояние, созданное до переключения маршрута. Мы не стали выдавать гипотезу за доказанный внутренний механизм YouTube: важнее воспроизводимый пользовательский сценарий.
Шаг 6. Убираем за собой
Root-доступ был нужен для установки бинарника, скриптов, маршрутов и диагностики. Оставлять после этого открытый Telnet было бы очень плохим финалом. Поэтому после проверки Чижик:
- удалил временные диагностические файлы;
- отключил запуск SSH;
- поставил системный флаг запрета Telnet;
- завершил работающие telnetd/SSH-процессы;
- с компьютера проверил, что порты 22 и 23 закрыты;
- оставил открытым только штатный интерфейс управления телевизором.
Конфигурация с секретами осталась доступна только root и имеет права 600. Локальный контроллер слушает только 127.0.0.1. KVN после перезагрузки выключен, пока владелец сам не нажмёт кнопку.
Это не абсолютная защита, но это разумный минимум: временный отладочный вход должен быть закрыт сразу после отладки.
Что получилось
В итоге старый LG получил функцию, которой у него не было из коробки:
- отдельное приложение в меню webOS;
- ручные кнопки подключения и отключения;
- VLESS/TCP/REALITY через sing-box;
- системный TUN, которым пользуется не только браузер, но и штатный YouTube;
- автоматический откат маршрутов при ошибке;
- отсутствие зависимости от компьютера после установки;
- отсутствие изменений в роутере;
- выключенное соединение после обычной перезагрузки;
- закрытый root-доступ после завершения работ.
Самое приятное: телевизор не пришлось заменять. Его железо по-прежнему умеет декодировать видео и показывать хорошую картинку. Проблема находилась не в матрице и не в процессоре, а в сетевом пути и отсутствии подходящего штатного клиента.
Сколько Чижиков нужно, чтобы настроить телевизор
Один, если рядом есть человек с пультом. И это, пожалуй, главный вывод эксперимента. Codex мог:
- исследовать устройство по сети;
- читать логи;
- собирать ARM-бинарник контроллера;
- писать и исправлять shell-скрипты;
- упаковывать webOS-приложение;
- проверять маршруты и доступность узлов;
- помнить о закрытии служебных портов.
Но несколько раз требовался человек:
- включить нужную настройку на телевизоре;
- подтвердить сопряжение;
- нажать кнопку в приложении;
- посмотреть, что физически происходит на экране;
- сказать сакраментальное: «все, YouTube завелся».
Это не история о том, как искусственный интеллект самовольно поселился в телевизоре. Это история о совместной работе: человек задает цель, принимает решения и контролирует физическое устройство, а Чижик берет на себя терминал, рутину, диагностику и удивительно большое количество кавычек в shell-командах.
Что я бы улучшил во второй версии
Решение уже работает, но список инженерных хотелок остался:
- добавить на экран приложения текущую страну и задержку;
- хранить несколько обезличенных профилей и переключаться между ними с пульта;
- показывать понятную причину ошибки вместо общего «не подключено»;
- добавить отдельный тест YouTube до его запуска;
- подписывать и проверять обновления контроллера;
- сделать безопасную резервную копию конфигурации без секретов;
- оформить установщик, который не требует ручного копирования файлов.
А еще у нас остались другие задачи: показывать на телевизоре фотографии из облака, передавать видео с компьютера без кабеля и понять, сколько современной жизни вообще можно вдохнуть в старый webOS.
Похоже, у «Очумелых ручек с Чижиком» будет второй выпуск.
Предупреждение для тех, кто уже потянулся за паяльником
Root-доступ, изменение маршрутов и установка сторонних бинарников могут привести к циклической загрузке, потере настроек или необходимости восстанавливать телевизор. Конкретные способы получения root зависят от модели и версии webOS и со временем меняются.
Перед экспериментом стоит:
- зафиксировать точную модель и версию прошивки;
- сохранить исходные конфиги и таблицу маршрутов;
- иметь способ вернуть устройство в исходное состояние;
- не публиковать UUID, приватные ключи и адреса своих серверов;
- не оставлять Telnet или SSH доступными после настройки;
- не копировать команды вслепую на другую модель.
Все адреса, идентификаторы и ключи в этой статье заменены заглушками. Это рассказ об архитектуре и ходе работы, а не универсальный установщик. Если хотите дайте почитать эту статью своему Чижику и он явно разберется в этом и потратит меньше токенов на доработку уже вашего телевизора.
*Само собой ситуация вымышленная, и происходит на другой планете, не существует никаких этих ваших Влесов, КВН- сервисов, ИИ-чижиков (кроме Алисы, конечно) и т.д. Это все выдумка больного воспаленного работой мозга IT-шника.
Комментарии
Обсуждайте статью, отвечайте и оценивайте комментарии. Вход — через ваш Яндекс ID.
Загружаем обсуждение…