جواب کوتاه: برای اجرای ربات تلگرام روی سرور ایران یه مشکل اصلی داری: سرور ایران مستقیم به api.telegram.org وصل نمیشه، پس ربات باید درخواستهاش رو از یه پروکسی رد کنه. سادهترین راه پایدار اینه: یه تونل SSH به یه سرور خارجی کوچیک، که با autossh همیشه بازه؛ ربات با long polling از همون تونل کار میکنه؛ و هر دو با systemd اجرا میشن تا اگه افتادن، خودشون دوباره بالا بیان. وبهوک فقط وقتی بهدرد میخوره که تلگرام بتونه از بیرون به دامنهت برسه.

چرا اصلاً ربات تلگرام روی سرور ایران؟
اگه کاربرهات ایرانیان، درگاه پرداخت ایرانی داری یا دیتابیس و سایتت همینجاست، سرور ایران ارزونتر و نزدیکتره. مشکل فقط یه جاست: ارتباط با خود تلگرام. یعنی کل داستان اینه که فقط ترافیک تلگرام رو از بیرون رد کنیم و بقیهی کارها روی همین سرور بمونه.
قدم ۱: یه تونل پایدار بساز
یه VPS خارجی کوچیک کافیه (کمترین پلن هم جواب میده). روی سرور ایران:
sudo apt install autossh
ssh-keygen -t ed25519 -f ~/.ssh/tunnel -N ""
ssh-copy-id -i ~/.ssh/tunnel.pub user@FOREIGN_IP
حالا تونل رو بهصورت سرویس تعریف کن. فایل /etc/systemd/system/tg-tunnel.service:
[Unit]
Description=SOCKS tunnel for Telegram
After=network-online.target
[Service]
User=botuser
Environment=AUTOSSH_GATETIME=0
ExecStart=/usr/bin/autossh -M 0 -N -D 127.0.0.1:1080 \
-o ServerAliveInterval=20 -o ServerAliveCountMax=3 \
-o ExitOnForwardFailure=yes -i /home/botuser/.ssh/tunnel user@FOREIGN_IP
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
sudo systemctl enable --now tg-tunnel
curl -s --socks5-hostname 127.0.0.1:1080 https://api.telegram.org | head -c 100
اگه دستور آخر جواب داد، تونل کار میکنه. ServerAliveInterval باعث میشه اتصال مرده زود تشخیص داده بشه، و Restart=always هم یعنی اگه افتاد، خودش دوباره وصل میشه.
نکته: پورت
1080رو فقط روی127.0.0.1باز کن، نه0.0.0.0. وگرنه هر کسی میتونه از پروکسیت استفاده کنه.
قدم ۲: ربات رو به پروکسی وصل کن (aiogram 3)
pip install aiogram aiohttp-socks
import asyncio, os
from aiogram import Bot, Dispatcher
from aiogram.client.session.aiohttp import AiohttpSession
session = AiohttpSession(proxy="socks5://127.0.0.1:1080")
bot = Bot(os.environ["BOT_TOKEN"], session=session)
dp = Dispatcher()
# handlerهات اینجا
async def main():
await bot.delete_webhook(drop_pending_updates=False)
await dp.start_polling(bot, polling_timeout=30)
asyncio.run(main())
دو نکتهی مهم:
- فقط ربات از پروکسی رد میشه. درخواستهای دیگه (درگاه پرداخت، APIهای داخلی) مستقیم میرن، که دقیقاً همونیه که میخوای.
delete_webhookرو اول کار صدا بزن. اگه قبلاً وبهوک تنظیم کرده باشی، polling هیچ پیامی نمیگیره و تا مدتها نمیفهمی چرا.
قدم ۳: ربات رو هم سرویس کن
فایل /etc/systemd/system/mybot.service:
[Unit]
Description=Telegram bot
After=tg-tunnel.service
Requires=tg-tunnel.service
[Service]
User=botuser
WorkingDirectory=/home/botuser/bot
EnvironmentFile=/home/botuser/bot/.env
ExecStart=/home/botuser/bot/.venv/bin/python main.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Requires یعنی ربات بدون تونل بالا نمیاد، و اگه تونل ریاستارت بشه ربات هم باهاش ریاستارت میشه. لاگها هم همیشه دم دستن:
journalctl -u mybot -f
پس وبهوک چی؟
وبهوک یعنی تلگرام به سرور تو درخواست بفرسته. روی سرور ایران دو تا مشکل داره:
- تلگرام باید بتونه از بیرون به دامنهت برسه. این همیشه قابلاعتماد نیست، مخصوصاً وقت اختلال.
- خود دستور
setWebhookو جوابدادن به کاربر هنوز به پروکسی نیاز دارن.
پس برای سرور ایران، polling از طریق تونل سادهتر و پایدارتره. وبهوک وقتی میارزه که ترافیک ربات خیلی زیاده و دامنهت از بیرون قابل دسترسه (مثلاً پشت Cloudflare). اون موقع حتماً secret_token بذار تا هر کسی نتونه به آدرس وبهوکت درخواست جعلی بفرسته.
وقتی کار نمیکنه، اینا رو چک کن
| علامت | احتمالاً |
|---|---|
Cannot connect to host api.telegram.org |
تونل خوابیده: systemctl status tg-tunnel |
| ربات بالاست ولی پیام نمیگیره | وبهوک قبلی هنوز فعاله؛ delete_webhook رو صدا بزن |
TelegramConflictError |
یه نسخهی دیگه از ربات جای دیگه داره polling میکنه |
| هر چند ساعت یه بار قطع میشه | ServerAliveInterval نذاشتی یا سرور خارجی ناپایداره |
چکلیست قبل از اینکه خیالت راحت بشه
- تونل با
systemctl status tg-tunnelفعاله و بعد از ریبوت سرور هم خودش بالا میاد. - پروکسی فقط روی
127.0.0.1گوش میده، نه روی همهی آیپیها. - ربات با
Requiresبه تونل وابستهست و باRestart=alwaysاجرا میشه. - توکن ربات توی فایل
.envهست، نه وسط کد یا توی گیت. - یه بار عمداً تونل رو ریاستارت کن و ببین ربات بدون دخالت تو دوباره جواب میده.
اگه این پنج تا تیک خوردن، رباتت روی سرور ایران تقریباً بدون مراقبت کار میکنه.
سؤالهای رایج
بهجای تونل SSH میشه از V2Ray یا پروکسی آماده استفاده کرد؟
آره، هر چیزی که یه SOCKS5 یا HTTP پروکسی روی 127.0.0.1 بده با همین کد کار میکنه. فقط آدرس proxy رو عوض کن. تونل SSH رو پیشنهاد کردم چون ابزار اضافه نمیخواد و راحت سرویس میشه.
اگه نت ملی بشه چی؟
ارتباط سرور ایران با بیرون قطع میشه و این روش هم از کار میفته. اون موقع فقط رباتهایی کار میکنن که روی سرور خارجی هستن.
python-telegram-bot دارم، نه aiogram.
اونم پروکسی رو پشتیبانی میکنه (با نصب python-telegram-bot[socks]). موقع ساختن Application هم .proxy(...) رو بذار و هم .get_updates_proxy(...)؛ اگه دومی رو یادت بره، ربات پیام میفرسته ولی پیامی دریافت نمیکنه.


