From b638d6231b73d3ec663b26f991f785e5bcfb980a Mon Sep 17 00:00:00 2001
From: Zsombor Welker <fedora@zdeqb.com>
Date: Mon, 20 Jun 2022 07:23:49 +0200
Subject: [PATCH] Add explicit handling for the host network

When a container uses the host network the network configuration may not
contain an explicit "IPAddress" value. In those cases use a
pre-configured IP.
---
 README.md                                         | 1 +
 src/systemd_resolved_docker/cli.py                | 3 ++-
 src/systemd_resolved_docker/dockerdnsconnector.py | 4 ++--
 src/systemd_resolved_docker/dockerwatcher.py      | 8 ++++++--
 systemd-resolved-docker.sysconfig                 | 4 ++++
 5 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index e3e2e1a..11e5a4e 100644
--- a/README.md
+++ b/README.md
@@ -133,6 +133,7 @@ If there are link-local, VPN or other DNS servers configured then those will als
 | DOCKER_LISTEN_ADDRESS             | IPs (+port) to listen on for queries from docker containers in the default network.                                     | _ip of the default docker bridge_, often `172.17.0.1`    | `172.17.0.1` or `172.17.0.1:53`   |
 | ALLOWED_DOMAINS                   | Domain which will be handled by the DNS server. If a domain starts with `.` then all subdomains will also be allowed.   | `.docker`                                                | `.docker,.local`                  |
 | DEFAULT_DOMAIN                    | Domain to append to hostnames which are not allowed by `ALLOWED_DOMAINS`.                                               | `docker`                                                 | `docker`                          |
+| DEFAULT_HOST_IP                   | IP address to use for containers on the host network if the container doesn't contain one.                              | `127.0.0.1`                                              | `127.0.0.1`                       |
 | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | --------------------------------- |
 
 ## Install
diff --git a/src/systemd_resolved_docker/cli.py b/src/systemd_resolved_docker/cli.py
index e25c2c7..30556af 100644
--- a/src/systemd_resolved_docker/cli.py
+++ b/src/systemd_resolved_docker/cli.py
@@ -38,6 +38,7 @@ def main():
     docker_listen_address = os.environ.get("DOCKER_LISTEN_ADDRESS", None)
     dns_server = parse_ip_port(os.environ.get("UPSTREAM_DNS_SERVER", "127.0.0.53"))
     default_domain = os.environ.get("DEFAULT_DOMAIN", "docker")
+    default_host_ip = os.environ.get("DEFAULT_HOST_IP", "127.0.0.1")
 
     tld = os.environ.get('ALLOWED_DOMAINS', None)
     if tld is None or len(tld.strip()) == 0:
@@ -64,7 +65,7 @@ def main():
     resolved = SystemdResolvedConnector(systemd_resolved_interface, systemd_resolved_listen_addresses, domains, handler)
 
     dns_connector = DockerDNSConnector(systemd_resolved_listen_addresses + docker_listen_addresses, dns_server, domains,
-                                       default_domain, handler, cli)
+                                       default_domain, default_host_ip, handler, cli)
     dns_connector.start()
 
     resolved.register()
diff --git a/src/systemd_resolved_docker/dockerdnsconnector.py b/src/systemd_resolved_docker/dockerdnsconnector.py
index b40877f..7ffbadf 100644
--- a/src/systemd_resolved_docker/dockerdnsconnector.py
+++ b/src/systemd_resolved_docker/dockerdnsconnector.py
@@ -13,7 +13,7 @@ from .zoneresolver import ZoneResolver
 
 class DockerDNSConnector:
     def __init__(self, listen_addresses: List[IpAndPort], upstream_dns_server: IpAndPort, dns_domains, default_domain,
-                 handler, cli):
+                 default_host_ip, handler, cli):
         super().__init__()
 
         self.default_domain = default_domain
@@ -35,7 +35,7 @@ class DockerDNSConnector:
             server.thread_name = "%s:%s" % (ip_and_port.ip, ip_and_port.port)
             self.servers.append(server)
 
-        self.watcher = DockerWatcher(self, cli)
+        self.watcher = DockerWatcher(self, default_host_ip, cli)
 
     def start(self):
         self.watcher.start()
diff --git a/src/systemd_resolved_docker/dockerwatcher.py b/src/systemd_resolved_docker/dockerwatcher.py
index 95f3063..cee24d4 100644
--- a/src/systemd_resolved_docker/dockerwatcher.py
+++ b/src/systemd_resolved_docker/dockerwatcher.py
@@ -18,7 +18,7 @@ class DockerWatcher(Thread):
         Thread based module for watching for docker container changes.
     """
 
-    def __init__(self, handler, cli=None):
+    def __init__(self, handler, default_host_ip='127.0.0.1', cli=None):
         super().__init__()
 
         if cli is None:
@@ -26,6 +26,7 @@ class DockerWatcher(Thread):
 
         self.daemon = True
         self.handler = handler
+        self.default_host_ip = default_host_ip
         self.cli = cli
 
     def run(self) -> None:
@@ -77,7 +78,10 @@ class DockerWatcher(Thread):
             for netname, network in settings.get('Networks', {}).items():
                 ip = network.get('IPAddress', False)
                 if not ip or ip == "":
-                    continue
+                    if netname == 'host':
+                        ip = self.default_host_ip
+                    else:
+                        continue
 
                 # record the container name DOT network
                 # eg. container is named "foo", and network is "demo",
diff --git a/systemd-resolved-docker.sysconfig b/systemd-resolved-docker.sysconfig
index a6845c3..fde5312 100644
--- a/systemd-resolved-docker.sysconfig
+++ b/systemd-resolved-docker.sysconfig
@@ -24,3 +24,7 @@
 ## will be forwarded to the configured DNS server.
 ## default: .docker
 # ALLOWED_DOMAINS=.docker
+
+## IP address to use with host networks when an IP is not specified
+## default: 127.0.0.1
+# DEFAULT_HOST_ip=127.0.0.1
\ No newline at end of file
-- 
GitLab