diff --git a/neutron/agent/linux/dhcp.py b/neutron/agent/linux/dhcp.py index 7bd89bab4ff..ce37f862557 100644 --- a/neutron/agent/linux/dhcp.py +++ b/neutron/agent/linux/dhcp.py @@ -334,24 +334,21 @@ class Dnsmasq(DhcpLocalProcess): 'dnsmasq', '--no-hosts', _no_resolv, - '--except-interface=lo', '--pid-file=%s' % pid_file, '--dhcp-hostsfile=%s' % self.get_conf_file_name('host'), '--addn-hosts=%s' % self.get_conf_file_name('addn_hosts'), '--dhcp-optsfile=%s' % self.get_conf_file_name('opts'), '--dhcp-leasefile=%s' % self.get_conf_file_name('leases'), '--dhcp-match=set:ipxe,175', + '--local-service', ] if self.device_manager.driver.bridged: cmd += [ '--bind-interfaces', - '--interface=%s' % self.interface_name, ] else: cmd += [ '--bind-dynamic', - '--interface=%s' % self.interface_name, - '--interface=tap*', '--bridge-interface=%s,tap*' % self.interface_name, ] diff --git a/neutron/cmd/sanity/checks.py b/neutron/cmd/sanity/checks.py index 560285afd04..1093f9a6e60 100644 --- a/neutron/cmd/sanity/checks.py +++ b/neutron/cmd/sanity/checks.py @@ -198,6 +198,21 @@ def get_dnsmasq_version_with_dhcp_release6(): return DNSMASQ_VERSION_DHCP_RELEASE6 +def dnsmasq_local_service_supported(): + cmd = ['dnsmasq', '--test', '--local-service'] + env = {'LC_ALL': 'C'} + obj, cmd = agent_utils.create_process(cmd, addl_env=env) + _stdout, _stderr = obj.communicate() + returncode = obj.returncode + if returncode == 127: + LOG.debug("Exception while checking dnsmasq version. " + "dnsmasq: No such file or directory") + return False + elif returncode == 1: + return False + return True + + def dnsmasq_version_supported(): try: cmd = ['dnsmasq', '--version'] diff --git a/neutron/cmd/sanity_check.py b/neutron/cmd/sanity_check.py index 82020c549d2..af9ba7e9e88 100644 --- a/neutron/cmd/sanity_check.py +++ b/neutron/cmd/sanity_check.py @@ -118,6 +118,15 @@ def check_dnsmasq_version(): return result +def check_dnsmasq_local_service_supported(): + result = checks.dnsmasq_local_service_supported() + if not result: + LOG.error('The installed version of dnsmasq is too old. ' + 'Please update to a version supporting the ' + '--local-service option.') + return result + + def check_keepalived_ipv6_support(): result = checks.keepalived_ipv6_supported() if not result: @@ -304,6 +313,9 @@ OPTS = [ help=_('Check for VF extended management support')), BoolOptCallback('read_netns', check_read_netns, help=_('Check netns permission settings')), + BoolOptCallback('dnsmasq_local_service_supported', + check_dnsmasq_local_service_supported, + help=_('Check for local-service support in dnsmasq')), BoolOptCallback('dnsmasq_version', check_dnsmasq_version, help=_('Check minimal dnsmasq version'), deprecated_for_removal=True, @@ -367,6 +379,9 @@ def enable_tests_from_config(): cfg.CONF.set_default('read_netns', True) if cfg.CONF.OVS.ovsdb_interface == 'native': cfg.CONF.set_default('ovsdb_native', True) + if cfg.CONF.dhcp_driver == 'neutron.agent.linux.dhcp.Dnsmasq': + cfg.CONF.set_default('dnsmasq_local_service_supported', True) + cfg.CONF.set_default('dnsmasq_version', True) if cfg.CONF.l3_ha: cfg.CONF.set_default('keepalived_ipv6_support', True) cfg.CONF.set_default('ip_nonlocal_bind', True) diff --git a/neutron/tests/unit/agent/linux/test_dhcp.py b/neutron/tests/unit/agent/linux/test_dhcp.py index 34ea174d357..46af2bd44dc 100644 --- a/neutron/tests/unit/agent/linux/test_dhcp.py +++ b/neutron/tests/unit/agent/linux/test_dhcp.py @@ -1233,15 +1233,14 @@ class TestDnsmasq(TestBase): 'dnsmasq', '--no-hosts', no_resolv, - '--except-interface=lo', '--pid-file=%s' % expected_pid_file, '--dhcp-hostsfile=/dhcp/%s/host' % network.id, '--addn-hosts=/dhcp/%s/addn_hosts' % network.id, '--dhcp-optsfile=/dhcp/%s/opts' % network.id, '--dhcp-leasefile=/dhcp/%s/leases' % network.id, '--dhcp-match=set:ipxe,175', + '--local-service', '--bind-interfaces', - '--interface=tap0', ] seconds = '' diff --git a/releasenotes/notes/dnsmasq-local-service-c8eaa91894a7d6d4.yaml b/releasenotes/notes/dnsmasq-local-service-c8eaa91894a7d6d4.yaml new file mode 100644 index 00000000000..50933ae1a5c --- /dev/null +++ b/releasenotes/notes/dnsmasq-local-service-c8eaa91894a7d6d4.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - | + Fixes bug `1501206 `_. + This ensures that DHCP agent instances running dnsmasq as a DNS server + can no longer be exploited as DNS amplifiers when the tenant network is + using publicly routed IP addresses by adding an option that will allow + them to only serve DNS requests from local networks.