Allow to request metadata proxy only with redirection
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
This commit is contained in:
parent
4143763913
commit
1d776bc16c
|
@ -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
|
||||
|
||||
|
|
|
@ -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'))
|
||||
]
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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=''):
|
||||
|
|
Loading…
Reference in New Issue