Nothing open on GitHub. Fix merged in #20175 on 5 May 2026. Check it covers your case.
The short answer
0open issues
0open PRs
3items grouped
- Known?
- Yes. 3 related items grouped here, 1 issue already closed.
- Fix event
- A fix was merged to main in PR #20175. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
resolved, deciding PR #20175. That is separate from the fix event. - Still open
- Nothing open on GitHub.
These issues and PRs address a bug where Telegram polling fails when DNS-over-HTTPS resolves to the same IP address as the system DNS. The fixes aim to preserve DoH-confirmed IPs in this matching scenario rather than discarding them.
Open issues0
Open PRs0
Fixes on record
-
#20175 fix(gateway): keep DoH-confirmed Telegram IPs that match system DNS (salvage #17043)
files:
gateway/platforms/telegram_network.py,tests/gateway/test_telegram_network.pyShow the diff
-
gateway/platforms/telegram_network.py@@ -185,10 +185,13 @@ async def _query_doh_provider( async def discover_fallback_ips() -> list[str]: """Auto-discover Telegram API IPs via DNS-over-HTTPS. - Resolves api.telegram.org through Google and Cloudflare DoH, collects all - unique IPs, and excludes the system-DNS-resolved IP (which is presumably - unreachable on this network). Falls back to a hardcoded seed list when DoH - is also unavailable. + Resolves api.telegram.org through Google and Cloudflare DoH and returns all + unique A records. IPs that match the local system resolver are kept rather + than excluded: in many networks the system-DNS IP is the most reliable path + to api.telegram.org and a transient primary-path failure should be retried + against the same address via the IP-rewrite path before the seed list is + consulted (#14520). Falls back to a hardcoded seed list only when DoH + yields no usable answers. """ async with httpx.AsyncClient(timeout=httpx.Timeout(_DOH_TIMEOUT)) as client: doh_tasks = [_query_doh_provider(client, p) for p in _DOH_PROVIDERS] @@ -203,11 +206,11 @@ async def discover_fallback_ips() -> list[str]: if isinstance(r, list): doh_ips.extend(r) - # Deduplicate preserving order, exclude system-DNS IPs + # Deduplicate preserving order seen: set[str] = set() candidates: list[str] = [] for ip in doh_ips: - if ip not in seen and ip not in system_ips: + if ip not in seen: seen.add(ip) candidates.append(ip) @@ -219,7 +222,7 @@ async def discover_fallback_ips() -> list[str]: return validated logger.info( - "DoH discovery yielded no new IPs (system DNS: %s); using seed fallback IPs %s", + "DoH discovery yielded no usable IPs (system DNS: %s); using seed fallback IPs %s", ", ".join(system_ips) or "unknown", ", ".join(_SEED_FALLBACK_IPS), ) -
tests/gateway/test_telegram_network.py@@ -534,15 +534,20 @@ async def test_google_and_cloudflare_ips_collected(self, monkeypatch): assert "149.154.167.221" in ips @pytest.mark.asyncio - async def test_system_dns_ip_excluded(self, monkeypatch): - """The IP from system DNS is the one that doesn't work — exclude it.""" + async def test_system_dns_ip_kept_when_doh_confirms(self, monkeypatch): + """DoH-confirmed IPs are kept even when they match system DNS (#14520). + + The system-DNS IP is often the most reliable path; including it as a + fallback lets the IP-rewrite retry recover from transient primary-path + failures instead of jumping straight to the hardcoded seed list. + """ self._patch_doh(monkeypatch, { "https://dns.google": (200, _doh_answer("149.154.166.110", "149.154.167.220")), "https://cloudflare-dns.com": (200, _doh_answer("149.154.166.110")), }, system_dns_ips=["149.154.166.110"]) ips = await tnet.discover_fallback_ips() - assert ips == ["149.154.167.220"] + assert ips == ["149.154.166.110", "149.154.167.220"] @pytest.mark.asyncio async def test_doh_results_deduplicated(self, monkeypatch): @@ -607,15 +612,21 @@ async def test_system_dns_failure_keeps_all_doh_ips(self, monkeypatch): assert "149.154.167.220" in ips @pytest.mark.asyncio - async def test_all_doh_ips_same_as_system_dns_uses_seed(self, monkeypatch): - """DoH returns only the same blocked IP — seed list is the fallback.""" + async def test_all_doh_ips_same_as_system_dns_kept(self, monkeypatch): + """DoH agrees with system DNS — keep that IP instead of seed list (#14520). + + Previous behavior fell through to ``_SEED_FALLBACK_IPS`` here, but the + seed addresses are not routable on every network. When DoH confirms + the system IP, that IP is the best candidate we have and should be + used as the fallback target. + """ self._patch_doh(monkeypatch, { "https://dns.google": (200, _doh_answer("149.154.166.110")), "https://cloudflare-dns.com": (200, _doh_answer("149.154.166.110")), }, system_dns_ips=["149.154.166.110"]) ips = await tnet.discover_fallback_ips() - assert ips == tnet._SEED_FALLBACK_IPS + assert ips == ["149.154.166.110"] @pytest.mark.asyncio async def test_cloudflare_gets_accept_header(self, monkeypatch):
-
1 PR closed without merging
From the close comments: closed without comment 1
- #17043 fix(gateway): keep DoH-confirmed Telegram IPs that match system DNS (#14520) · closed without comment
Closed issues · 1
- Closed#14520Telegram polling fails when DoH returns same IP as system DNS
How this cluster was grouped
-
Link evidence (
structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference. -
Pairwise link density
0.67: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Merged PRs
- #20175
- Closed issues
- 1
- Attempts
- 1 PR closed without merging
- Fix link checked
- 5 May 2026