From 8e83e007e9125aa6a27d8d368259546620c8e2ac Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Fri, 27 Mar 2020 11:54:32 +0100 Subject: [PATCH] DNS loop protection (#1599) * DNS loop protection * Update supervisor/dns.py Co-Authored-By: Franck Nijhof * cleanup not needed code * Fix Co-authored-by: Franck Nijhof --- supervisor/dns.py | 26 +++++++++++++++++++++++--- supervisor/tasks.py | 4 +++- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/supervisor/dns.py b/supervisor/dns.py index d985041fa..98b20cf57 100644 --- a/supervisor/dns.py +++ b/supervisor/dns.py @@ -45,6 +45,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes): self.coredns_template: Optional[jinja2.Template] = None self._hosts: List[HostEntry] = [] + self._loop: bool = False @property def corefile(self) -> Path: @@ -209,16 +210,36 @@ class CoreDNS(JsonConfig, CoreSysAttributes): self.hosts.unlink() self._init_hosts() + # Reset loop protection + self._loop = False + await self.sys_addons.sync_dns() + async def loop_detection(self) -> None: + """Check if there was a loop found.""" + log = await self.instance.logs() + + # Check the log for loop plugin output + if b"plugin/loop: Loop" in log: + _LOGGER.error("Detect a DNS loop in local Network!") + self._loop = True + else: + self._loop = False + def _write_corefile(self) -> None: """Write CoreDNS config.""" dns_servers: List[str] = [] + local_dns: List[str] = [] + servers: List[str] = [] # Prepare DNS serverlist: Prio 1 Manual, Prio 2 Local, Prio 3 Fallback - local_dns: List[str] = self.sys_host.network.dns_servers or ["dns://127.0.0.11"] - servers: List[str] = self.servers + local_dns + if not self._loop: + local_dns = self.sys_host.network.dns_servers or ["dns://127.0.0.11"] + servers = self.servers + local_dns + else: + _LOGGER.warning("Ignore user DNS settings because of loop") + # Print some usefully debug data _LOGGER.debug( "config-dns = %s, local-dns = %s , backup-dns = CloudFlare DoT", self.servers, @@ -339,7 +360,6 @@ class CoreDNS(JsonConfig, CoreSysAttributes): def is_fails(self) -> Awaitable[bool]: """Return True if a Docker container is fails state. - Return a coroutine. """ return self.instance.is_fails() diff --git a/supervisor/tasks.py b/supervisor/tasks.py index bab7a8211..444453ea8 100644 --- a/supervisor/tasks.py +++ b/supervisor/tasks.py @@ -232,9 +232,11 @@ class Tasks(CoreSysAttributes): return _LOGGER.warning("Watchdog found a problem with CoreDNS plugin!") + # Reset of fails if await self.sys_dns.is_fails(): - _LOGGER.warning("CoreDNS plugin is in fails state / Reset config") + _LOGGER.error("CoreDNS plugin is in fails state / Reset config") await self.sys_dns.reset() + await self.sys_dns.loop_detection() try: await self.sys_dns.start()