This commit is contained in:
Andrew Pimenov 2026-10-07 06:56:18 +03:00 • committed by GitHub
commit 17720bbcb1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -82,8 +82,12 @@ def build_dns_leak(results: list[AdapterLeakResult], ecs_leaked: bool) -> DnsLea
parts.append("No adapter resolves DNS outside the egress ASN.") parts.append("No adapter resolves DNS outside the egress ASN.")
parts_ru.append("Ни один адаптер не резолвит DNS за пределами egress ASN.") parts_ru.append("Ни один адаптер не резолвит DNS за пределами egress ASN.")
if ecs_leaked: if ecs_leaked:
parts.append("The resolver forwards your EDNS Client Subnet, exposing your network to authoritative servers.") parts.append(
parts_ru.append("Резолвер пересылает ваш EDNS Client Subnet, раскрывая вашу сеть авторитативным серверам.") "The resolver forwards your EDNS Client Subnet, exposing your network to authoritative servers."
)
parts_ru.append(
"Резолвер пересылает ваш EDNS Client Subnet, раскрывая вашу сеть авторитативным серверам."
)
parts.append(_LEAK_NOTE) parts.append(_LEAK_NOTE)
parts_ru.append(_LEAK_NOTE_RU) parts_ru.append(_LEAK_NOTE_RU)
return DnsLeak( return DnsLeak(
@ -121,7 +125,9 @@ def _resolver_for(server: str, timeout: float) -> dns.asyncresolver.Resolver:
return resolver return resolver
async def echo_probe(resolver_ip: str, timeout: float) -> tuple[str | None, dict[str, str]]: async def echo_probe(
resolver_ip: str, timeout: float
) -> tuple[str | None, dict[str, str]]:
resolver = _resolver_for(resolver_ip, timeout) resolver = _resolver_for(resolver_ip, timeout)
myaddr, akahelp = await asyncio.gather( myaddr, akahelp = await asyncio.gather(
_txt(resolver, MYADDR_NAME), _txt(resolver, AKAHELP_NAME) _txt(resolver, MYADDR_NAME), _txt(resolver, AKAHELP_NAME)
@ -145,22 +151,46 @@ async def asn_for_ip(ip: str, zone: str, timeout: float) -> str | None:
return None return None
async def _probe_adapter(
adapter: str,
resolvers: list[str],
cymru_zone: str,
egress_asn: str | None,
timeout: float,
) -> tuple[AdapterLeakResult, bool]:
try:
echoed_ip, akahelp = await echo_probe(resolvers[0], timeout)
except dns.exception.DNSException:
echoed_ip, akahelp = None, {}
leaked = detect_ecs_leak(akahelp)
echoed_asn = await asn_for_ip(echoed_ip, cymru_zone, timeout) if echoed_ip else None
result = build_adapter_result(adapter, resolvers, echoed_ip, echoed_asn, egress_asn)
return result, leaked
async def collect_dns_leak( async def collect_dns_leak(
local: LocalNet, local: LocalNet,
egress_asn: str | None, egress_asn: str | None,
cymru_zone: str, cymru_zone: str,
timeout: float, timeout: float,
) -> DnsLeak: ) -> DnsLeak:
results: list[AdapterLeakResult] = [] tasks = []
ecs_leaked = False
for adapter, resolvers in local.dns_servers_per_adapter.items(): for adapter, resolvers in local.dns_servers_per_adapter.items():
if not resolvers: if not resolvers:
continue continue
try: tasks.append(
echoed_ip, akahelp = await echo_probe(resolvers[0], timeout) _probe_adapter(adapter, resolvers, cymru_zone, egress_asn, timeout)
except dns.exception.DNSException: )
echoed_ip, akahelp = None, {}
ecs_leaked = ecs_leaked or detect_ecs_leak(akahelp) if not tasks:
echoed_asn = await asn_for_ip(echoed_ip, cymru_zone, timeout) if echoed_ip else None return build_dns_leak([], False)
results.append(build_adapter_result(adapter, resolvers, echoed_ip, echoed_asn, egress_asn))
task_results = await asyncio.gather(*tasks)
results: list[AdapterLeakResult] = []
ecs_leaked = False
for result, leaked in task_results:
results.append(result)
ecs_leaked = ecs_leaked or leaked
return build_dns_leak(results, ecs_leaked) return build_dns_leak(results, ecs_leaked)