Как один зависший плейлист научил меня, что протокол всегда найдёт щель под абстракцией, которую ты считал непроницаемой.
Всё работает. Почта грузится, мессенджер дышит, видео тянется без запинки. А Apple Music крутит спиннер. Не «ошибка сети», не «попробуйте позже» - просто белое колесо, вечное, как загрузка, которая никогда не станет содержимым. Поиск не ищет. Главная не открывается. Библиотека, та что уже на диске, играет - но всё, что требует свежего запроса к серверу, повисает в лимбе.
Первая мысль всегда одна и та же: «опять этот прокси».
Что я проверил первым - и зря
Весь мой трафик я гоняю через свой «анализатор трафика» - привычка человека, который любит держать свои пакеты под контролем: приватность, отладка, свой маршрут. И когда что-то ломается, палец первым делом тянется обвинить именно его. Сменил выходной узел - спиннер крутится. Вернул обратно - крутится. Пинг живой, скорость есть.
Значит, Apple? Их страница статуса - сплошь «operational». Значит, DNS? Резолвинг API-хоста мгновенный и корректный. Всё, что я проверял по привычке, отвечало «я в порядке» - а Apple Music не грузился.
Симптом есть, виноватого нет. Это классическая ловушка отладки: ты добросовестно опрашиваешь все системы, которые умеешь опросить, они хором рапортуют «чисто» - и ты застреваешь, потому что сломана та система, проверить которую ты не додумался.
Один тупой вопрос
Я позвал на помощь ИИ - не за готовым ответом, а чтобы кто-то задавал тупые вопросы, пока я упираюсь в собственную картину мира. И один вопрос оказался ключом:
«А ты уверен, что этот трафик вообще идёт через твои правила роутинга?»
.conf-правила у меня перехватывают TCP-соединения и уводят их в туннель. Аккуратно, надёжно, тотально - так я думал. Но Apple Music для своих API давно ходит по HTTP/3. А HTTP/3 - это QUIC. А QUIC - это UDP.
UDP-пакет на порт 443 не является TCP-соединением. Мой «тотальный» перехватчик его попросту не видел. Музыка утекала мимо туннеля - по UDP, налегке - и уходила в сеть тем путём, который мои правила роутинга не контролировали. Сервер на том конце видел запрос, пришедший из одной географии, тогда как всё остальное про эту сессию говорило о другой. Гео не сходилось. И API, вместо ответа, впадал в ту же задумчивость, что и мой спиннер.
Абстракция, которую я считал непроницаемой - «весь трафик идёт через туннель», - имела щель ровно в форме протокола, о котором я не подумал. Прогресс сделал музыку быстрее (HTTP/3 и правда быстрее) и той же рукой прокопал дыру под моей схемой. Тёплая изнанка.
Починить оказалось проще, чем понять
Если UDP-ветку нельзя провести через туннель - нужно её закрыть, чтобы приложение откатилось на то, что туннель умеет: на TCP.
Одно правило: всё, что UDP на порт 443, - отклонять. В синтаксисе моих .conf-правил это выглядит примерно так:
AND,((PROTOCOL,UDP),(DST-PORT,443)),REJECT
Поставить его нужно до финального правила - иначе оно не успеет сработать. Приложение утыкается в закрытый QUIC, пожимает плечами и переустанавливает соединение по HTTP/2 поверх TCP. А TCP послушно уходит в туннель, гео сходится, спиннер наконец превращается в обложку альбома.
Побочный эффект честный: ты глушишь QUIC для всего на 443. На практике почти незаметно - всё живое умеет откатываться на TCP. Цена - небольшая потеря той самой скорости HTTP/3. Плата за то, чтобы твой туннель снова стал тем, чем ты его считал: тотальным.
Сноска, которую ты не читал
Мораль не про музыку. Она про абстракции, которые мы держим за герметичные. «Весь трафик идёт по моим правилам» звучало как факт, а было допущением с невидимой сноской: весь TCP-трафик. Протокол, о котором ты не подумал, - это и есть щель, через которую вытекает то, что ты пытался удержать.
И роль ИИ здесь - тоже точная. Он не выдал мне ответ, готового не было. Он задал вопрос, который я себе не задавал, потому что был слишком уверен: «а точно ли этот трафик идёт туда, куда ты думаешь?» Иногда вся отладка - это найти одно допущение, которое ты перестал проверять, потому что оно слишком очевидно, чтобы быть ложным. А ещё «музыка тормозит» бывает трёх разных природ - утечка по UDP лишь одна из них; остальные две разобраны в «Трёх голосах одной тишины».
