diff --git a/test/Dockerfile b/test/Dockerfile
index 5c4015405676ca3130b5d73180edc9839f919669..4cf0707f8b8563a09892d9612293156d24a5a1bb 100644
--- a/test/Dockerfile
+++ b/test/Dockerfile
@@ -1,7 +1,7 @@
 FROM debian:stable
 
 RUN apt-get -q update && env DEBIAN_FRONTEND=noninteractive \
-    apt-get install --no-install-recommends -y python3 python3-pip python3-setuptools python3-yaml python3-jinja2 python3-nose
+    apt-get install --no-install-recommends -y python3 python3-pip python3-setuptools python3-yaml python3-jinja2 python3-nose python3-dnspython
 
 ADD . /src
 WORKDIR /src
diff --git a/test/float_integration_test/__init__.py b/test/float_integration_test/__init__.py
index a22c2d6f3dd051112155007dc6d22d2ebfbde330..f3ff2e52e31b2220890fd625532cc458a97da36f 100644
--- a/test/float_integration_test/__init__.py
+++ b/test/float_integration_test/__init__.py
@@ -52,6 +52,11 @@ class TestBase(unittest.TestCase):
         host = random.choice(hosts_in_group('frontend'))
         return ANSIBLE_VARS['hostvars'][host]['ip']
 
+    def all_frontend_ips(self):
+        """Return all IPs in the 'frontend' group."""
+        return [ANSIBLE_VARS['hostvars'][x]['ip']
+                for x in hosts_in_group('frontend')]
+
     def sso_conversation(self, sso_username=None, sso_password=None):
         url = _ansible_eval(
             '{{ sso_server_url | default("https://login." + domain_public[0]) }}')
diff --git a/test/float_integration_test/test_system.py b/test/float_integration_test/test_system.py
index cbee3bf87f80e7c7f6a97bc9e86ed715695d7cab..114eac305805ad20e9acb3bc0b7e38d59c290c1c 100644
--- a/test/float_integration_test/test_system.py
+++ b/test/float_integration_test/test_system.py
@@ -1,6 +1,7 @@
 import json
 import time
 import unittest
+from dns.resolver import Resolver
 from float_integration_test import TestBase, ANSIBLE_VARS
 
 
@@ -34,6 +35,26 @@ class TestHTTPRouter(URLTestBase):
         self.assertTrue(UNKNOWN_DOMAIN_MSG in result['body'])
 
 
+class TestDNS(TestBase):
+
+    def setUp(self):
+        self.resolver = Resolver(configure=False)
+        self.resolver.nameservers = self.all_frontend_ips()
+
+    def test_public_dns_entries_for_services(self):
+        frontend_ips = set(self.all_frontend_ips())
+        for service in ANSIBLE_VARS['services'].values():
+            for pe in service.get('public_endpoints', []):
+                if pe.get('skip_dns', False):
+                    continue
+                name = '%s.%s' % (pe['name'],
+                                  ANSIBLE_VARS['domain_public'][0])
+                print(f'querying {name}')
+                resp = self.resolver.query(name, 'A')
+                for record in resp:
+                    self.assertTrue(str(record) in frontend_ips)
+
+
 class TestBuiltinServiceURLs(URLTestBase):
     """Verify that all the public_endpoints are reachable.
 
diff --git a/test/setup.py b/test/setup.py
index 734aa5a38c765e90583efee55f49be02841f8781..3aafda5eb44513c128dee84bb99888941ec89b16 100755
--- a/test/setup.py
+++ b/test/setup.py
@@ -11,7 +11,7 @@ setup(
     url="https://git.autistici.org/ai3/float",
     install_requires=["Jinja2",
                       "PyYAML",
-                      ],
+                      "dnspython"],
     setup_requires=[],
     zip_safe=True,
     packages=find_packages(),