MikroTik: Webhook Telegram через VPN
Решение проблемы, когда Telegram webhook не доходит до сервера при использовании policy routing для заворачивания трафика Telegram в VPN.
Описание проблемы
При настройке MikroTik для отправки трафика Telegram через VPN возникает проблема с входящими webhook:
- Webhook от Telegram приходит на WAN-интерфейс
- Запрос доходит до сервера (n8n, бот и т.д.)
- Сервер отвечает
- MikroTik видит dst=IP_Telegram → маркирует → отправляет в VPN
- Telegram не получает ответ (другой src IP) → timeout
Схема проблемы
Telegram ──► WAN:443 ──► DNAT ──► Сервер ──► Ответ
│
▼
dst = IP Telegram
│
▼
Правило VPN: dst в to-vpn? ── ДА
│
▼
Ответ уходит в VPN ──► Telegram DROP
Решение
Используем connection-mark для пометки входящих соединений от Telegram. Conntrack запоминает метку и применяет ко всем пакетам соединения, включая ответы.
Шаг 1: Создаём address-list для webhook
/ip firewall address-list add list=telegram-webhook address=149.154.160.0/20 comment="telegram webhook src" add list=telegram-webhook address=91.108.4.0/22 comment="telegram webhook src" add list=telegram-webhook address=91.108.8.0/22 comment="telegram webhook src" add list=telegram-webhook address=91.108.12.0/22 comment="telegram webhook src" add list=telegram-webhook address=91.108.16.0/22 comment="telegram webhook src" add list=telegram-webhook address=91.108.20.0/22 comment="telegram webhook src" add list=telegram-webhook address=91.108.56.0/22 comment="telegram webhook src" add list=telegram-webhook address=91.105.192.0/23 comment="telegram webhook src" add list=telegram-webhook address=185.76.151.0/24 comment="telegram webhook src" add list=telegram-webhook address=95.161.64.0/20 comment="telegram webhook src"
Шаг 2: Добавляем правила mangle
# Помечаем входящие соединения от Telegram (в начало цепочки!) /ip firewall mangle add chain=prerouting \ in-interface-list=wan \ connection-state=new \ protocol=tcp \ src-address-list=telegram-webhook \ dst-port=443 \ action=mark-connection \ new-connection-mark=wan_webhook \ passthrough=yes \ comment="Mark incoming Telegram webhooks" \ place-before=0 # Пропускаем помеченные соединения мимо VPN /ip firewall mangle add chain=prerouting \ connection-mark=wan_webhook \ action=accept \ passthrough=no \ comment="Skip VPN for Telegram webhook responses" \ place-before=1
<note important>Правила должны быть выше правила маркировки трафика в VPN!</note>
Шаг 3: Проверка
Проверяем порядок правил:
/ip firewall mangle print
Ожидаемый результат:
0 mark-connection wan_webhook src-address-list=telegram-webhook 1 accept connection-mark=wan_webhook passthrough=no ... N mark-routing to_vpn dst-address-list=to-vpn
Проверяем счётчики после отправки тестового webhook:
/ip firewall mangle print stats where connection-mark=wan_webhook
Принцип работы
ВХОДЯЩИЙ WEBHOOK:
Telegram ──► WAN ──► Правило 0: src=telegram-webhook? ── ДА
│
▼
connection-mark = wan_webhook
│
▼
Правило 1: connection-mark=wan_webhook? ── ДА
│
▼
accept ──► ВЫХОД ИЗ MANGLE
│
▼
DNAT ──► Сервер ──► Ответ
│
▼
connection-mark=wan_webhook (conntrack)
│
▼
Правило 1: accept ──► WAN ──► Telegram ✅
ИСХОДЯЩИЙ ЗАПРОС (бот → Telegram API):
Сервер ──► dst=Telegram ──► Правило 0: src=telegram-webhook? ── НЕТ
│
▼
Правило 1: connection-mark? ── НЕТ
│
▼
Правило VPN: dst=to-vpn? ── ДА
│
▼
mark-routing=to_vpn ──► VPN ✅
| Тип трафика | Connection-mark | Маршрут |
|---|---|---|
| Webhook Telegram → Сервер | wan_webhook | WAN |
| Ответ Сервер → Telegram | wan_webhook | WAN |
| Бот → Telegram API | нет | VPN |
Диагностика
tcpdump на сервере
# Замените IP на ваш WAN tcpdump -ni any host <IP_TELEGRAM_SERVER> and port 443
Правильный вывод — ответ уходит с вашего WAN IP:
eth0 In IP 149.154.x.x.443 > 192.168.0.x.xxxxx # входящий eth0 Out IP 192.168.0.x.xxxxx > 149.154.x.x.443 # ответ через WAN ✅
Проверка conntrack
/ip firewall connection print where connection-mark=wan_webhook