]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Allow to request metadata proxy only with redirection
authorCedric Brandily <zzelle@gmail.com>
Mon, 10 Nov 2014 13:46:51 +0000 (14:46 +0100)
committerCedric Brandily <zzelle@gmail.com>
Fri, 30 Jan 2015 09:34:49 +0000 (09:34 +0000)
metadata service should be requested on 169.254.169.254:80 and router
namespace iptables rules redirect the request to the metadata-ns-proxy
on 127.0.0.1:$metadata_port. But currently the metadata-ns-proxy can be
requested directly on $router-ip:$metadata_port.

To avoid such behavior, this change marks packets redirection in mangle
table (PREROUTING), redirects (PREROUTING) them in nat table, accepts
them in filter table (INPUT) using the mark. Packets send to the
metadata proxy port without mark (so directly) are dropped. The
mark can be configured through the new option metadata_access_mark.

Remark: redirected packets are not local packets (in general), so
setting metadata proxy server host to 127.0.0.1 will disallow direct
queries but so redirected queries.

DocImpact
Partial-Bug: #1187102
Change-Id: I6a9bb12c8bf68c6fcf4e4060f8dfe44a309a41da

etc/l3_agent.ini
neutron/agent/l3/config.py
neutron/agent/metadata/driver.py
neutron/tests/unit/agent/metadata/test_driver.py

index 0c158370decae5dc62cee8112a40fe6071622dea..eca07f0f362ce064b926d17a5ae7410cc0bd98b6 100644 (file)
@@ -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
 
index d91bcdfe0aac71e297b927da85763336b68d4971..986317ff28467fd852a40731eb3ac089ae920b3e 100644 (file)
@@ -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'))
 ]
index 5c778f39c248b5db16fcf0f43a88f719a299fbf0..24a2fa9f39468bb1bbadcb552e0786608ed0efe9 100644 (file)
@@ -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):
index 48f87ea8d251dd5c92a2fa3643169417723f2eb4..0ce344d333c5c8264283b8e80f0a7542f1b6c225 100644 (file)
@@ -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=''):