Токен Telegram-бота утекает чаще других: как его спрятать
У обычного API-ключа есть шанс спрятаться в заголовке запроса. У токена Telegram-бота шанса нет: он живёт прямо в URL — и оседает в каждом логе на пути запроса. Разбираем, чем это грозит и как закрыть проблему, не переписывая бота.
Почему именно телеграм-токен — худший случай
Bot API устроен так, что токен — часть адреса:
https://api.telegram.org/bot123456:AAEhBOweik6ad.../sendMessage
URL — это самая «протекающая» часть HTTP-запроса. Токен бота автоматически оказывается:
- в access-логах любого прокси, балансировщика и CDN на пути запроса;
- в истории shell-команд после первого же отладочного
curl; - в конфиге вебхука, docker-compose, systemd-юните — токен вписывают в URL, а эти файлы коммитят;
- в трейсах APM и сообщениях об ошибках HTTP-клиентов (URL печатается целиком);
- в выводе
docker inspectи CI-логах, где переменные окружения разворачиваются в команды.
С ключом OpenAI нужно постараться, чтобы залогировать его. С токеном бота нужно постараться, чтобы не залогировать.
Что получает тот, кто нашёл токен
Всё, что умеет бот, без исключений:
- Перехват входящих — чужой
getUpdatesворует поллинг: сообщения пользователей уходят злоумышленнику, а ваш бот «молчит»; - Рассылка от имени бота — спам или фишинг по всей аудитории, которая боту доверяет;
- Тихое зеркалирование —
setWebhookна чужой сервер, и весь трафик дублируется туда, а бот продолжает работать как ни в чём не бывало; - в каналах и группах, где бот админ, — удаление сообщений, баны, посты.
Стандартные меры и их пределы
- Revoke в @BotFather — обязательный первый шаг при утечке. Но это лечение симптома: новый токен ляжет в те же логи и конфиги.
secret_tokenу вебхука — защищает endpoint от чужих POST'ов, но никак не защищает сам токен.- Переменные окружения — прячут токен из кода, но не из URL: в момент запроса он всё равно разворачивается в адресную строку.
Корень проблемы не в хранении, а в том, что настоящий токен вообще участвует в каждом запросе.
Прокси-подход: настоящий токен не покидает хранилище
Схема credential proxy для ботов работает особенно красиво. Настоящий токен один раз шифруется в хранилище, бот получает проходку — виртуальный токен, и меняется ровно две вещи: хост и сам токен.
# было
https://api.telegram.org/bot123456:AAEh.../sendMessage
# стало
https://api.proxykey.org/p/telegram-bot/123456:vlt_telegrambot_.../sendMessage
Прокси извлекает проходку из пути, проверяет статус, IP и лимиты, подставляет настоящий токен на своей стороне и передаёт запрос Telegram как есть. Теперь во всех логах, конфигах и истории команд лежит только отзываемая проходка: слив — это один клик «отозвать», а не пожар.
Трюк с валидацией формата
aiogram, telebot и grammY проверяют формат токена <цифры>:<хэш> ещё до первого запроса — «голая» проходка vlt_… их проверку не пройдёт. Поэтому прокси принимает составную форму: подставьте id бота и двоеточие перед проходкой — цифры игнорируются, а валидация библиотек проходит.
# aiogram
bot = Bot(
token="123456:vlt_telegrambot_XXXX",
session=AiohttpSession(api=TelegramAPIServer.from_base(
"https://api.proxykey.org/p/telegram-bot"
)),
)
Long-polling тоже учтён: getUpdates с timeout=50 не обрывается — прокси держит длинные запросы, а скачивание файлов работает через тот же путь /file/bot….
Что это даёт на практике
- Привязка к IP — проходка работает только с сервера бота; утёкшая копия с другого адреса получает 403;
- Лимиты rpm/rpd — чужая рассылка упрётся в потолок, который вы задали;
- Лог каждого вызова —
sendMessageв 3 часа ночи с нетипичной частотой видно сразу; - Отзыв без даунтайма — проходка ротируется в один клик, настоящий токен не трогаем, BotFather не нужен.
Как мы переводили на эту схему два продакшен-бота и на какие грабли наступили — в отдельном разборе.
Частые вопросы
Это работает с вебхуками?
Да: вебхук ставится тем же запросом через прокси, а secret_token продолжает защищать ваш endpoint. Сам токен в конфиге вебхука больше не фигурирует — только проходка.
Замедлится ли бот?
Один дополнительный хоп — единицы-десятки миллисекунд. На фоне сетевой задержки до Telegram это незаметно, а long-polling вообще нечувствителен к ней.
А если утечёт сама проходка?
С чужого IP — 403, сверх лимитов — 429, отзыв — один клик без перевыпуска настоящего токена. Сравните с процедурой после слива оригинала.
Спрячьте токен бота за минуту
Заведите токен в proxykey — получите проходку с привязкой к IP, лимитами и живым логом. Бесплатно, без карты.
Защитить бота →