Свой прокси для ElevenLabs на VPS: почему Squid не чинит виджет и что нужно на самом деле
Инструкции «поднимите Squid на VPS» решают задачу доступа для вас, но не для голосового виджета на сайте. Разбираем, почему обычный HTTP-прокси здесь бесполезен, что должен уметь релей для ConvAI и во что обходится сделать это самому.
По запросу «elevenlabs прокси» в топе выдачи лежит инструкция: возьмите VPS, поставьте Squid, пропишите логин и пароль, готово. Инструкция рабочая, но она решает не ту задачу, которая у большинства людей.
Она чинит доступ для вас лично. Если у вас на сайте стоит голосовой агент ElevenLabs Conversational AI и он молчит у российских посетителей, Squid здесь не поможет никак. Разберём почему и что нужно вместо него.
Две разные задачи, которые постоянно путают
Задача А: вам нужно ходить к API ElevenLabs со своего бэкенда. Вы генерируете озвучку, дёргаете text-to-speech из скрипта, синхронизируете голоса. Всё происходит на вашем сервере, вы полностью управляете его сетевыми настройками.
Здесь Squid действительно работает. Ставите прокси на европейском VPS, в своём коде указываете HTTPS_PROXY, запросы уходят с европейского адреса. Полчаса работы, задача закрыта.
Задача Б: у вас на сайте виджет <elevenlabs-convai>, и он не работает у посетителей из России. Вот здесь Squid бесполезен, и причина фундаментальная.
Почему HTTP-прокси не чинит виджет
Виджет ElevenLabs это JavaScript, который выполняется в браузере посетителя. Не на вашем сервере. Когда человек из Казани открывает вашу страницу, его браузер сам, напрямую, обращается к api.elevenlabs.io.
Отсюда три причины, по которым классический прокси мимо:
1. Вы не управляете сетью посетителя. Чтобы браузер ходил через ваш Squid, посетитель должен прописать этот прокси у себя в настройках системы. Просить об этом человека, который зашёл спросить про цены, бессмысленно. Прокси, который нужно настраивать на стороне клиента, для публичного сайта не существует как решение.
2. HTTPS через прокси это непрозрачный туннель. Даже если бы браузер посетителя ходил через ваш Squid, при работе с HTTPS прокси видит только метод CONNECT и имя хоста. Дальше идёт зашифрованный поток, в который прокси не может вмешаться: ни подменить адрес назначения, ни переписать заголовки. Он просто перекладывает байты. Значит, запрос всё равно уйдёт на api.elevenlabs.io, и ElevenLabs всё равно увидит адрес посетителя.
3. Виджет ходит по WebSocket, а голос может пойти вообще мимо. Диалог с агентом это не серия HTTP-запросов, а живое двустороннее соединение. Плюс в современных версиях виджета медиапоток по умолчанию может идти через WebRTC, а это UDP напрямую между браузером и медиасервером, в обход любого HTTP-прокси.
Что должен уметь настоящий релей
Если разбирать задачу честно, работающее решение состоит из четырёх частей. Мы прошли этот путь целиком, так что перечислю без прикрас.
Часть 1. Перехват на стороне страницы. Раз браузер посетителя нельзя перенастроить снаружи, вмешиваться нужно изнутри страницы. Практически это скрипт-загрузчик, который подменяет штатный embed виджета и патчит браузерные fetch и WebSocket так, чтобы обращения к домену ElevenLabs уезжали на ваш релей. Всё остальное поведение виджета при этом сохраняется.
Часть 2. Ретрансляция REST. Обычная часть. Ваш сервер принимает запрос, повторяет его к api.elevenlabs.io со своего адреса, отдаёт ответ обратно. Тонкость в заголовках: их нужно передавать аккуратно, не теряя авторизацию и не подставляя ничего лишнего.
Часть 3. Ретрансляция WebSocket. Вот здесь начинается настоящая работа. Соединение диалога нужно проксировать кадр в кадр, с сохранением подпротокола convai, в обе стороны, без буферизации и без задержек. Голос это реальное время: лишние 200 миллисекунд на кадр превращают живой диалог в рацию.
Часть 4. Принудительный WebSocket вместо WebRTC. Если оставить транспорт по умолчанию, медиа может пойти по WebRTC напрямую, минуя релей, и вы получите наполовину рабочий виджет: конфигурация приезжает, а голос не идёт. Транспорт нужно явно зафиксировать атрибутом use-rtc="false" на теге виджета.
Во что это обходится, если делать самому
Считаем честно.
Деньги. VPS с чистым европейским адресом это 5-15 долларов в месяц. Домен и сертификат почти бесплатно. Итого пара тысяч рублей в месяц.
Время. Основная стоимость здесь. Ретрансляция REST это вечер. WebSocket-релей, который не рвёт соединения и не добавляет задержку, это уже несколько дней с отладкой. Плюс загрузчик, который патчит браузерные API и при этом не ломает виджет при обновлении его версии.
Прежде чем что-то поднимать, стоит убедиться, что адрес будущего узла вообще годится. Для этого мы выложили открытый скрипт проверки: запускаете его прямо на VPS и видите, доезжают запросы до ElevenLabs или разворачиваются редиректом.
Главный скрытый расход: чистота адреса. Это то, о чём инструкции по Squid не пишут вообще. Взять VPS мало, нужно чтобы его IP не был помечен как российский. В официальной справке ElevenLabs про это сказано прямым текстом:
Some servers may be impacted by this block even if they are not physically located in one of the affected regions, as our cloud provider might flag them as associated with one of these countries.
Мы на это натыкались не раз на собственной инфраструктуре: два подряд заказанных немецких адреса у одного хостера пришли уже помеченными как российские, при том что физически стояли во Франкфурте. Проверять приходится до того, как вы что-то на этот адрес переносите, а негодные возвращать и заказывать заново.
Поддержка. Виджет ElevenLabs обновляется. Меняются эндпоинты, формат конфигурации, транспорт. Релей, который вы собрали и забыли, однажды сломается тихо, и узнаете вы об этом от клиента.
Когда своё решение оправдано
Не хочу делать вид, что своё никогда не нужно. Оно оправдано, если:
- у вас один проект и вам нравится держать всё под контролем;
- вы и так администрируете серверы, и лишний Node-процесс вас не пугает;
- вам нужны нестандартные вещи: своя логика авторизации, свой учёт, интеграция с внутренними системами;
- вы не хотите, чтобы трафик диалогов проходил через посредника. Это, кстати, полностью законное соображение, и мы его уважаем.
А не оправдано, если вы агентство с десятком клиентских сайтов. Тогда вы получаете десять релеев, десять адресов, которые надо проверять на чистоту, и десять точек, которые могут сломаться в отпуске.
Что делаем мы
ElevenProxy это описанные выше четыре части, собранные и поддерживаемые за вас. На стороне сайта меняется одна строка:
<!-- было -->
<elevenlabs-convai agent-id="AGENT"></elevenlabs-convai>
<script src="https://unpkg.com/@elevenlabs/convai-widget-embed" async></script>
<!-- стало -->
<elevenlabs-convai agent-id="AGENT" use-rtc="false"></elevenlabs-convai>
<script src="https://cdn.elevenproxy.ru/w/proj_XXXXXXXX.js" async></script>
Ключи ElevenLabs остаются вашими, аккаунт ваш, за минуты диалога вы платите ElevenLabs напрямую. Мы отвечаем только за то, чтобы трафик виджета доехал.
Прежде чем что-либо менять, стоит убедиться, что проблема вообще в этом: чекер проверит ваш виджет с российского узла и покажет, доезжает ли он до ElevenLabs. Бесплатно и без регистрации.
Если после этой статьи вы решите собрать своё, тоже нормально. Главное теперь понятно, куда смотреть: не в Squid, а в перехват на стороне страницы и в честный WebSocket-релей.
Узнайте, режется ли ваш агент ElevenLabs по гео для РФ — и почините заменой одной строки.