diff --git a/etc/l3_agent.ini b/etc/l3_agent.ini index 0c158370dec..eca07f0f362 100644 --- a/etc/l3_agent.ini +++ b/etc/l3_agent.ini @@ -71,6 +71,9 @@ # if the Nova metadata server is not available # enable_metadata_proxy = True +# Iptables mangle mark used to mark metadata valid requests +# metadata_access_mark = 0x1 + # Location of Metadata Proxy UNIX domain socket # metadata_proxy_socket = $state_path/metadata_proxy diff --git a/neutron/agent/l3/config.py b/neutron/agent/l3/config.py index d91bcdfe0aa..986317ff284 100644 --- a/neutron/agent/l3/config.py +++ b/neutron/agent/l3/config.py @@ -55,5 +55,9 @@ OPTS = [ cfg.BoolOpt('enable_metadata_proxy', default=True, help=_("Allow running metadata proxy.")), cfg.BoolOpt('router_delete_namespaces', default=False, - help=_("Delete namespace after removing a router.")) + help=_("Delete namespace after removing a router.")), + cfg.StrOpt('metadata_access_mark', + default='0x1', + help=_('Iptables mangle mark used to mark metadata valid ' + 'requests')) ] diff --git a/neutron/agent/metadata/driver.py b/neutron/agent/metadata/driver.py index 5c778f39c24..24a2fa9f394 100644 --- a/neutron/agent/metadata/driver.py +++ b/neutron/agent/metadata/driver.py @@ -24,6 +24,9 @@ from neutron.services import advanced_service LOG = logging.getLogger(__name__) +# Access with redirection to metadata proxy iptables mark mask +METADATA_ACCESS_MARK_MASK = '0xffffffff' + class MetadataDriver(advanced_service.AdvancedService): @@ -47,10 +50,14 @@ class MetadataDriver(advanced_service.AdvancedService): def __init__(self, l3_agent): super(MetadataDriver, self).__init__(l3_agent) self.metadata_port = l3_agent.conf.metadata_port + self.metadata_access_mark = l3_agent.conf.metadata_access_mark def after_router_added(self, router): - for c, r in self.metadata_filter_rules(self.metadata_port): + for c, r in self.metadata_filter_rules(self.metadata_port, + self.metadata_access_mark): router.iptables_manager.ipv4['filter'].add_rule(c, r) + for c, r in self.metadata_mangle_rules(self.metadata_access_mark): + router.iptables_manager.ipv4['mangle'].add_rule(c, r) for c, r in self.metadata_nat_rules(self.metadata_port): router.iptables_manager.ipv4['nat'].add_rule(c, r) router.iptables_manager.apply() @@ -61,8 +68,11 @@ class MetadataDriver(advanced_service.AdvancedService): self.l3_agent.conf) def before_router_removed(self, router): - for c, r in self.metadata_filter_rules(self.metadata_port): + for c, r in self.metadata_filter_rules(self.metadata_port, + self.metadata_access_mark): router.iptables_manager.ipv4['filter'].remove_rule(c, r) + for c, r in self.metadata_mangle_rules(self.metadata_access_mark): + router.iptables_manager.ipv4['mangle'].remove_rule(c, r) for c, r in self.metadata_nat_rules(self.metadata_port): router.iptables_manager.ipv4['nat'].remove_rule(c, r) router.iptables_manager.apply() @@ -72,9 +82,18 @@ class MetadataDriver(advanced_service.AdvancedService): self.l3_agent.conf) @classmethod - def metadata_filter_rules(cls, port): - return [('INPUT', '-s 0.0.0.0/0 -p tcp -m tcp --dport %s ' - '-j ACCEPT' % port)] + def metadata_filter_rules(cls, port, mark): + return [('INPUT', '-m mark --mark %s -j ACCEPT' % mark), + ('INPUT', '-s 0.0.0.0/0 -p tcp -m tcp --dport %s ' + '-j DROP' % port)] + + @classmethod + def metadata_mangle_rules(cls, mark): + return [('PREROUTING', '-s 0.0.0.0/0 -d 169.254.169.254/32 ' + '-p tcp -m tcp --dport 80 ' + '-j MARK --set-xmark %(value)s/%(mask)s' % + {'value': mark, + 'mask': METADATA_ACCESS_MARK_MASK})] @classmethod def metadata_nat_rules(cls, port): diff --git a/neutron/tests/unit/agent/metadata/test_driver.py b/neutron/tests/unit/agent/metadata/test_driver.py index 48f87ea8d25..0ce344d333c 100644 --- a/neutron/tests/unit/agent/metadata/test_driver.py +++ b/neutron/tests/unit/agent/metadata/test_driver.py @@ -48,10 +48,20 @@ class TestMetadataDriver(base.BaseTestCase): metadata_driver.MetadataDriver.metadata_nat_rules(8775)) def test_metadata_filter_rules(self): - rules = ('INPUT', '-s 0.0.0.0/0 -p tcp -m tcp --dport 8775 -j ACCEPT') + rules = [('INPUT', '-m mark --mark 0x1 -j ACCEPT'), + ('INPUT', '-s 0.0.0.0/0 -p tcp -m tcp --dport 8775 -j DROP')] self.assertEqual( - [rules], - metadata_driver.MetadataDriver.metadata_filter_rules(8775)) + rules, + metadata_driver.MetadataDriver.metadata_filter_rules(8775, '0x1')) + + def test_metadata_mangle_rules(self): + rule = ('PREROUTING', '-s 0.0.0.0/0 -d 169.254.169.254/32 ' + '-p tcp -m tcp --dport 80 ' + '-j MARK --set-xmark 0x1/%s' % + metadata_driver.METADATA_ACCESS_MARK_MASK) + self.assertEqual( + [rule], + metadata_driver.MetadataDriver.metadata_mangle_rules('0x1')) def _test_spawn_metadata_proxy(self, expected_user, expected_group, user='', group=''):