@kkolorid

Как пробросить webhook Telegram бота на домашний компьютер через виртуальный сервер с OpenVPN и Docker?

Доброго времени суток. Проблема такая... Мне удобно вести разработку и отлаживать бота у себя на домашнем компьютере при помощи Docker, т.к. в дальнейшем сильно упрощается деплой на сервер. Но я не могу позволить пробросить телеграммовский вебхук себе на локальную машину по логичным причинам, а его нужно как-то дебажить в процессе работы, клиенту результат показывать и т.д. Постоянно пушуить/пуллить всё на продакшн сервер и там запускать для дебага - не вариант. Примерно представляю, что в данном случае мне легче заиметь какой-нибудь самый дешевый виртуальный сервер, который будет выступать в роли организатора туннеля через OpenVPN. Вопрос тогда в том, как это правильно всё настроить. С OpenVPN раньше не работал, не знаю с какой стороны подойти. Ситуацию усложняет то, что для вебхука тг необходим ssl сертификат, а домен держать на сервере не хочется. Могу ли я его просто на ip повесить, тг даст мне такой вебхук установить? И как в итоге это всё на моей стороне должно описываться? В случае с aiogram, например... Пример запуска бота с вебхуком:
import logging

from aiogram import Bot, types
from aiogram.contrib.middlewares.logging import LoggingMiddleware
from aiogram.dispatcher import Dispatcher
from aiogram.dispatcher.webhook import SendMessage
from aiogram.utils.executor import start_webhook


API_TOKEN = 'BOT_TOKEN_HERE'

# webhook settings
WEBHOOK_HOST = 'https://your.domain'
WEBHOOK_PATH = '/path/to/api'
WEBHOOK_URL = f"{WEBHOOK_HOST}{WEBHOOK_PATH}"

# webserver settings
WEBAPP_HOST = 'localhost'  # or ip
WEBAPP_PORT = 3001

logging.basicConfig(level=logging.INFO)

bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)
dp.middleware.setup(LoggingMiddleware())


@dp.message_handler()
async def echo(message: types.Message):
    # Regular request
    # await bot.send_message(message.chat.id, message.text)

    # or reply INTO webhook
    return SendMessage(message.chat.id, message.text)


async def on_startup(dp):
    await bot.set_webhook(WEBHOOK_URL)
    # insert code here to run it after start


async def on_shutdown(dp):
    logging.warning('Shutting down..')

    # insert code here to run it before shutdown

    # Remove webhook (not acceptable in some cases)
    await bot.delete_webhook()

    # Close DB connection (if used)
    await dp.storage.close()
    await dp.storage.wait_closed()

    logging.warning('Bye!')


if __name__ == '__main__':
    start_webhook(
        dispatcher=dp,
        webhook_path=WEBHOOK_PATH,
        on_startup=on_startup,
        on_shutdown=on_shutdown,
        skip_updates=True,
        host=WEBAPP_HOST,
        port=WEBAPP_PORT,
    )
  • Вопрос задан
  • 1735 просмотров
Пригласить эксперта
Ответы на вопрос 3
shurshur
@shurshur
Сисадмин, просто сисадмин...
Первое и очень простое решение - можно вообще не использовать вебхуки для тестового бота. Например, пусть у нас будет в конфиге опция, по которой мы запускаем либо сервер для вебхуков, либо поллинг:

import config

if __name__ == '__main__':
    if config.POLLING:
        ... start_polling
    else:
        start_webhook(...


Всё-таки основная часть бота - его бизнес-логика. Каждый раз проверять работу его вебхуков необязательно.

Если всё же хочется вебхуков, то организуем VPN по любой инструкции, коих тысячи, получаем туннель с парой IP. Например, 10.10.10.1 на сервере и 10.10.10.2 локально. На сервере поднимаем nginx, в котором настраиваем что-то типа
location /path/to/api_test {
  proxy_pass http://10.10.10.2:порт/path/to/api_test
}


Обязательно настраиваем https, можно с Let's Encrypt, но можно и с самоподписанным сертификатом. В последнем случае надо будет загрузить этот сертификат в Telegram через API при настройке вебхука.

Локально у себя пробросить в докере тот самый порт в нужный контейнер с ботом.

Возможны разные вариации, не изменяющие общий принцип. Например, можно не настраивать https на сервере, пробросить весь порт "как есть" через nginx stream, haproxy, двойной нат или нат с policy routing, а сам https настраивать у себя локально.
Ответ написан
Комментировать
deepblack
@deepblack
Варианты вдобавок к тому что уже сказали:
  1. Получить у провайдера белый IP адрес и пробрасывать порт на комп на котром ведется разработка (сертификат использовать от Let's Encrypt)
  2. Использовать https://ngrok.com/ - просто и быстро (сертификат у них свой, есть бесплатный тарифный план)
  3. Если есть сервер то: SSH Remote Port Forwarding

Например:
Есть некое приложение слушающее порт 8008 на локальной тачке, пусть будет так:
python3 -m http.server --bind localhost 8008
Мы хотим пробросить этот порт на удаленный сервер на порт 9009:
ssh -R 9009:localhost:8008 my.server.name.tld

В примере выше подразумевается вход по ключу и имя пользователя на удаленной машине такое-же как логин на локальной, либо явно указано в .ssh/config + на файерволле открыт соответствующий порт.
Тогда все делается легко и быстро ))
Ответ написан
@Drno
Эмм.. почему нельзя вести разработу на VPS ?

А так - ставь опенвпн сервер на VPS, подключайся к нему, делай переадресацию порта с помощью iptables на IP клиента в опенВПН

SSL можешь получить бесплатно на IP VPS, с помощью Летснкрипт + sslip.io
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы