Skip to content

Repository files navigation

INCY TV Relay

Релей для передачи подписки на Apple TV / Android TV из любой сети.

Сервер хранит два непрозрачных блоба с TTL 5 минут и не может прочитать передаваемые данные: ключ выводится на устройствах из 8-значного кода по протоколу CPace, релей его вывести не может.

Эндпоинты

Метод Путь Кто вызывает
POST /pair/init TV — занимает код
GET /pair/{code} Sender — читает {sid, ya}
POST /pair/{code}/send Sender — кладёт шифротекст
GET /pair/{code}/result TV — забирает (long-poll 30 с)

Служебные: /healthz, /readyz.

Защита от перебора

Ключевой лимит — 5 попыток на код, дальше код сгорает целиком. Смена IP не помогает: счётчик привязан к коду. Именно поэтому 8 знаков достаточно — офлайн-перебор невозможен, каждая попытка требует обращения к серверу.

Дополнительно: 300 запросов/мин на IP и тело до 64 KiB.

Отдельного лимита на создание кодов нет намеренно: за одним внешним адресом (CGNAT оператора, общежитие) могут быть сотни устройств, и почасовой лимит отрезал бы часть пользователей. От заполнения Redis защищают общий лимит и вытеснение записей по TTL.

Разработка

npm install
redis-server --port 6379 --save ''
npm test
npm start

Запуск

docker compose up -d

Поднимет релей на :8080 и Redis рядом. Ничего больше не нужно — сервис не хранит состояния между перезапусками, кроме активных пейрингов (5 минут).

Готовый образ: ghcr.io/incy-dev/incy-tv-relay:main.

Проверить, что сервер ничего не читает

Смотреть стоит два файла:

  • src/app.js — обработчики: тела запросов только валидируются по длине и передаются в хранилище как есть;
  • src/store.js — Redis: два поля с TTL, никакой расшифровки.

Ключ шифрования выводится на устройствах из 8-значного кода по протоколу CPace. Сервер видит только публичные значения ya и yb, из которых секрет не восстанавливается.

About

Zero-knowledge relay for INCY TV subscription pairing

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages