feat(telegram): auto-discover fallback IPs via DoH when api.telegram.org is unreachable#3376
Merged
feat(telegram): auto-discover fallback IPs via DoH when api.telegram.org is unreachable#3376
Conversation
…org is unreachable On some networks (university, corporate), api.telegram.org resolves to a valid Telegram IP that is unreachable due to routing/firewall rules. A different IP in the same Telegram-owned 149.154.160.0/20 block works fine. This adds automatic fallback IP discovery at connect time: 1. Query Google and Cloudflare DNS-over-HTTPS for api.telegram.org A records 2. Exclude the system-DNS IP (the unreachable one), use the rest as fallbacks 3. If DoH is also blocked, fall back to a seed list (149.154.167.220) 4. TelegramFallbackTransport tries primary first, sticks to whichever works No configuration needed — works automatically. TELEGRAM_FALLBACK_IPS env var still available as manual override. Zero impact on healthy networks (primary path succeeds on first attempt, fallback never exercised). No new dependencies (uses httpx already in deps + stdlib socket).
- Use single TelegramFallbackTransport shared between request and get_updates_request so sticky IP is shared across polling and API calls - Keep separate HTTPXRequest instances (different timeout settings) - Downgrade "using seed fallback IPs" from warning to info to avoid noisy logs on healthy networks
…t files The original PR missed test_dm_topics.py and test_telegram_network_reconnect.py — both need the telegram.request mock module. The reconnect test also needs _no_auto_discovery since _handle_polling_network_error calls connect() which now invokes discover_fallback_ips().
4 tasks
StreamOfRon
pushed a commit
to StreamOfRon/hermes-agent
that referenced
this pull request
Mar 29, 2026
…org is unreachable (NousResearch#3376) * feat(telegram): auto-discover fallback IPs via DoH when api.telegram.org is unreachable On some networks (university, corporate), api.telegram.org resolves to a valid Telegram IP that is unreachable due to routing/firewall rules. A different IP in the same Telegram-owned 149.154.160.0/20 block works fine. This adds automatic fallback IP discovery at connect time: 1. Query Google and Cloudflare DNS-over-HTTPS for api.telegram.org A records 2. Exclude the system-DNS IP (the unreachable one), use the rest as fallbacks 3. If DoH is also blocked, fall back to a seed list (149.154.167.220) 4. TelegramFallbackTransport tries primary first, sticks to whichever works No configuration needed — works automatically. TELEGRAM_FALLBACK_IPS env var still available as manual override. Zero impact on healthy networks (primary path succeeds on first attempt, fallback never exercised). No new dependencies (uses httpx already in deps + stdlib socket). * fix: share transport instance and downgrade seed fallback log to info - Use single TelegramFallbackTransport shared between request and get_updates_request so sticky IP is shared across polling and API calls - Keep separate HTTPXRequest instances (different timeout settings) - Downgrade "using seed fallback IPs" from warning to info to avoid noisy logs on healthy networks * fix: add telegram.request mock and discovery fixture to remaining test files The original PR missed test_dm_topics.py and test_telegram_network_reconnect.py — both need the telegram.request mock module. The reconnect test also needs _no_auto_discovery since _handle_polling_network_error calls connect() which now invokes discover_fallback_ips(). --------- Co-authored-by: Mohan Qiao <Gavin-Qiao@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Salvaged from PR #3129 by @Gavin-Qiao. Closes #3128.
On restricted networks (university, corporate),
api.telegram.orgmay resolve to an IP that is unreachable due to routing or firewall rules. This PR adds automatic fallback IP discovery via DNS-over-HTTPS so the Telegram adapter can find and use an alternative endpoint.How it works
dns.google/resolve) and Cloudflare DoH (cloudflare-dns.com/dns-query) in parallel forapi.telegram.orgA records149.154.167.220— verified in Telegram's 149.154.160.0/20 range, AS62041)TelegramFallbackTransport(httpx async transport) tries the primary endpoint first, then sticks to the first working fallback IPSecurity audit
Verified safe:
sni_hostnameextension controls both SNI and certificate hostname verification in httpx → httpcore → Python ssl. A malicious IP would fail the TLS handshake (no valid cert forapi.telegram.org)verify=Falseanywhere — default httpx TLS verification useddns.google/resolveandcloudflare-dns.com/dns-queryconfirmed via official Google/Cloudflare developer docs149.154.167.220is in Telegram's official CIDR range (core.telegram.org/resources/cidr.txt), announced by AS62041 with valid RPKI/ROAOn healthy networks, behavior is unchanged — the primary connection succeeds immediately.
Files changed
gateway/platforms/telegram_network.pygateway/platforms/telegram.pygateway/config.pyTELEGRAM_FALLBACK_IPSenv var supporttests/gateway/test_telegram_network.pytelegram.requestmock +_no_auto_discoveryfixtureFollow-up fixes (on top of cherry-pick)
telegram.requestmock totest_dm_topics.pyandtest_telegram_network_reconnect.py(missed by original PR)_no_auto_discoveryfixture to reconnect test (reconnect handler callsconnect()which now invokesdiscover_fallback_ips())Test plan