Use ebtables to isolate dhcp traffic
Iptables doesn't properly block the broadcast traffic crossing the bridge, so use ebtables instead. Removes test which is no longer valid since we are not using iptables anymore. Change-Id: I43e5f1fe9512dd3ec9595c7203bc46837cef3cad Closes-Bug: #1318104
This commit is contained in:
parent
0fa99567ab
commit
1236b09076
@ -1634,29 +1634,14 @@ def isolate_dhcp_address(interface, address):
|
|||||||
% (interface, address))
|
% (interface, address))
|
||||||
rules.append('OUTPUT -p ARP -o %s --arp-ip-src %s -j DROP'
|
rules.append('OUTPUT -p ARP -o %s --arp-ip-src %s -j DROP'
|
||||||
% (interface, address))
|
% (interface, address))
|
||||||
|
rules.append('FORWARD -p IPv4 -i %s --ip-protocol udp '
|
||||||
|
'--ip-destination-port 67:68 -j DROP'
|
||||||
|
% interface)
|
||||||
|
rules.append('FORWARD -p IPv4 -o %s --ip-protocol udp '
|
||||||
|
'--ip-destination-port 67:68 -j DROP'
|
||||||
|
% interface)
|
||||||
# NOTE(vish): the above is not possible with iptables/arptables
|
# NOTE(vish): the above is not possible with iptables/arptables
|
||||||
ensure_ebtables_rules(rules)
|
ensure_ebtables_rules(rules)
|
||||||
# block dhcp broadcast traffic across the interface
|
|
||||||
ipv4_filter = iptables_manager.ipv4['filter']
|
|
||||||
ipv4_filter.add_rule('FORWARD',
|
|
||||||
('-m physdev --physdev-in %s -d 255.255.255.255 '
|
|
||||||
'-p udp --dport 67 -j %s'
|
|
||||||
% (interface, CONF.iptables_drop_action)),
|
|
||||||
top=True)
|
|
||||||
ipv4_filter.add_rule('FORWARD',
|
|
||||||
('-m physdev --physdev-out %s -d 255.255.255.255 '
|
|
||||||
'-p udp --dport 67 -j %s'
|
|
||||||
% (interface, CONF.iptables_drop_action)),
|
|
||||||
top=True)
|
|
||||||
# block ip traffic to address across the interface
|
|
||||||
ipv4_filter.add_rule('FORWARD',
|
|
||||||
('-m physdev --physdev-in %s -d %s -j %s'
|
|
||||||
% (interface, address, CONF.iptables_drop_action)),
|
|
||||||
top=True)
|
|
||||||
ipv4_filter.add_rule('FORWARD',
|
|
||||||
('-m physdev --physdev-out %s -s %s -j %s'
|
|
||||||
% (interface, address, CONF.iptables_drop_action)),
|
|
||||||
top=True)
|
|
||||||
|
|
||||||
|
|
||||||
def remove_isolate_dhcp_address(interface, address):
|
def remove_isolate_dhcp_address(interface, address):
|
||||||
@ -1666,38 +1651,14 @@ def remove_isolate_dhcp_address(interface, address):
|
|||||||
% (interface, address))
|
% (interface, address))
|
||||||
rules.append('OUTPUT -p ARP -o %s --arp-ip-src %s -j DROP'
|
rules.append('OUTPUT -p ARP -o %s --arp-ip-src %s -j DROP'
|
||||||
% (interface, address))
|
% (interface, address))
|
||||||
|
rules.append('FORWARD -p IPv4 -i %s --ip-protocol udp '
|
||||||
|
'--ip-destination-port 67:68 -j DROP'
|
||||||
|
% interface)
|
||||||
|
rules.append('FORWARD -p IPv4 -o %s --ip-protocol udp '
|
||||||
|
'--ip-destination-port 67:68 -j DROP'
|
||||||
|
% interface)
|
||||||
remove_ebtables_rules(rules)
|
remove_ebtables_rules(rules)
|
||||||
# NOTE(vish): the above is not possible with iptables/arptables
|
# NOTE(vish): the above is not possible with iptables/arptables
|
||||||
# block dhcp broadcast traffic across the interface
|
|
||||||
ipv4_filter = iptables_manager.ipv4['filter']
|
|
||||||
|
|
||||||
drop_actions = ['DROP']
|
|
||||||
if CONF.iptables_drop_action != 'DROP':
|
|
||||||
drop_actions.append(CONF.iptables_drop_action)
|
|
||||||
|
|
||||||
for drop_action in drop_actions:
|
|
||||||
ipv4_filter.remove_rule('FORWARD',
|
|
||||||
('-m physdev --physdev-in %s '
|
|
||||||
'-d 255.255.255.255 '
|
|
||||||
'-p udp --dport 67 -j %s'
|
|
||||||
% (interface, drop_action)),
|
|
||||||
top=True)
|
|
||||||
ipv4_filter.remove_rule('FORWARD',
|
|
||||||
('-m physdev --physdev-out %s '
|
|
||||||
'-d 255.255.255.255 '
|
|
||||||
'-p udp --dport 67 -j %s'
|
|
||||||
% (interface, drop_action)),
|
|
||||||
top=True)
|
|
||||||
|
|
||||||
# block ip traffic to address across the interface
|
|
||||||
ipv4_filter.remove_rule('FORWARD',
|
|
||||||
('-m physdev --physdev-in %s -d %s -j %s'
|
|
||||||
% (interface, address, drop_action)),
|
|
||||||
top=True)
|
|
||||||
ipv4_filter.remove_rule('FORWARD',
|
|
||||||
('-m physdev --physdev-out %s -s %s -j %s'
|
|
||||||
% (interface, address, drop_action)),
|
|
||||||
top=True)
|
|
||||||
|
|
||||||
|
|
||||||
def get_gateway_rules(bridge):
|
def get_gateway_rules(bridge):
|
||||||
|
@ -655,13 +655,9 @@ class LinuxNetworkTestCase(test.NoDBTestCase):
|
|||||||
linux_net.IptablesManager())
|
linux_net.IptablesManager())
|
||||||
self.stubs.Set(linux_net, 'binary_name', 'test')
|
self.stubs.Set(linux_net, 'binary_name', 'test')
|
||||||
executes = []
|
executes = []
|
||||||
inputs = []
|
|
||||||
|
|
||||||
def fake_execute(*args, **kwargs):
|
def fake_execute(*args, **kwargs):
|
||||||
executes.append(args)
|
executes.append(args)
|
||||||
process_input = kwargs.get('process_input')
|
|
||||||
if process_input:
|
|
||||||
inputs.append(process_input)
|
|
||||||
return "", ""
|
return "", ""
|
||||||
|
|
||||||
self.stubs.Set(utils, 'execute', fake_execute)
|
self.stubs.Set(utils, 'execute', fake_execute)
|
||||||
@ -691,27 +687,26 @@ class LinuxNetworkTestCase(test.NoDBTestCase):
|
|||||||
iface, '--arp-ip-src', dhcp, '-j', 'DROP'),
|
iface, '--arp-ip-src', dhcp, '-j', 'DROP'),
|
||||||
('ebtables', '-t', 'filter', '-I', 'OUTPUT', '-p', 'ARP', '-o',
|
('ebtables', '-t', 'filter', '-I', 'OUTPUT', '-p', 'ARP', '-o',
|
||||||
iface, '--arp-ip-src', dhcp, '-j', 'DROP'),
|
iface, '--arp-ip-src', dhcp, '-j', 'DROP'),
|
||||||
|
('ebtables', '-t', 'filter', '-D', 'FORWARD', '-p', 'IPv4', '-i',
|
||||||
|
iface, '--ip-protocol', 'udp', '--ip-destination-port', '67:68',
|
||||||
|
'-j', 'DROP'),
|
||||||
|
('ebtables', '-t', 'filter', '-I', 'FORWARD', '-p', 'IPv4', '-i',
|
||||||
|
iface, '--ip-protocol', 'udp', '--ip-destination-port', '67:68',
|
||||||
|
'-j', 'DROP'),
|
||||||
|
('ebtables', '-t', 'filter', '-D', 'FORWARD', '-p', 'IPv4', '-o',
|
||||||
|
iface, '--ip-protocol', 'udp', '--ip-destination-port', '67:68',
|
||||||
|
'-j', 'DROP'),
|
||||||
|
('ebtables', '-t', 'filter', '-I', 'FORWARD', '-p', 'IPv4', '-o',
|
||||||
|
iface, '--ip-protocol', 'udp', '--ip-destination-port', '67:68',
|
||||||
|
'-j', 'DROP'),
|
||||||
('iptables-save', '-c'),
|
('iptables-save', '-c'),
|
||||||
('iptables-restore', '-c'),
|
('iptables-restore', '-c'),
|
||||||
('ip6tables-save', '-c'),
|
('ip6tables-save', '-c'),
|
||||||
('ip6tables-restore', '-c'),
|
('ip6tables-restore', '-c'),
|
||||||
]
|
]
|
||||||
self.assertEqual(executes, expected)
|
self.assertEqual(executes, expected)
|
||||||
expected_inputs = [
|
|
||||||
'-A test-FORWARD -m physdev --physdev-in %s '
|
|
||||||
'-d 255.255.255.255 -p udp --dport 67 -j DROP' % iface,
|
|
||||||
'-A test-FORWARD -m physdev --physdev-out %s '
|
|
||||||
'-d 255.255.255.255 -p udp --dport 67 -j DROP' % iface,
|
|
||||||
'-A test-FORWARD -m physdev --physdev-in %s '
|
|
||||||
'-d 192.168.1.1 -j DROP' % iface,
|
|
||||||
'-A test-FORWARD -m physdev --physdev-out %s '
|
|
||||||
'-s 192.168.1.1 -j DROP' % iface,
|
|
||||||
]
|
|
||||||
for inp in expected_inputs:
|
|
||||||
self.assertIn(inp, inputs[0])
|
|
||||||
|
|
||||||
executes = []
|
executes = []
|
||||||
inputs = []
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def fake_remove(bridge, gateway):
|
def fake_remove(bridge, gateway):
|
||||||
@ -726,106 +721,14 @@ class LinuxNetworkTestCase(test.NoDBTestCase):
|
|||||||
iface, '--arp-ip-dst', dhcp, '-j', 'DROP'),
|
iface, '--arp-ip-dst', dhcp, '-j', 'DROP'),
|
||||||
('ebtables', '-t', 'filter', '-D', 'OUTPUT', '-p', 'ARP', '-o',
|
('ebtables', '-t', 'filter', '-D', 'OUTPUT', '-p', 'ARP', '-o',
|
||||||
iface, '--arp-ip-src', dhcp, '-j', 'DROP'),
|
iface, '--arp-ip-src', dhcp, '-j', 'DROP'),
|
||||||
('iptables-save', '-c'),
|
('ebtables', '-t', 'filter', '-D', 'FORWARD', '-p', 'IPv4', '-i',
|
||||||
('iptables-restore', '-c'),
|
iface, '--ip-protocol', 'udp', '--ip-destination-port', '67:68',
|
||||||
('ip6tables-save', '-c'),
|
'-j', 'DROP'),
|
||||||
('ip6tables-restore', '-c'),
|
('ebtables', '-t', 'filter', '-D', 'FORWARD', '-p', 'IPv4', '-o',
|
||||||
|
iface, '--ip-protocol', 'udp', '--ip-destination-port', '67:68',
|
||||||
|
'-j', 'DROP'),
|
||||||
]
|
]
|
||||||
self.assertEqual(executes, expected)
|
self.assertEqual(executes, expected)
|
||||||
for inp in expected_inputs:
|
|
||||||
self.assertNotIn(inp, inputs[0])
|
|
||||||
|
|
||||||
def test_isolated_host_iptables_logdrop(self):
|
|
||||||
# Ensure that a different drop action for iptables doesn't change
|
|
||||||
# the drop action for ebtables.
|
|
||||||
self.flags(fake_network=False,
|
|
||||||
share_dhcp_address=True,
|
|
||||||
iptables_drop_action='LOGDROP')
|
|
||||||
|
|
||||||
# NOTE(vish): use a fresh copy of the manager for each test
|
|
||||||
self.stubs.Set(linux_net, 'iptables_manager',
|
|
||||||
linux_net.IptablesManager())
|
|
||||||
self.stubs.Set(linux_net, 'binary_name', 'test')
|
|
||||||
executes = []
|
|
||||||
inputs = []
|
|
||||||
|
|
||||||
def fake_execute(*args, **kwargs):
|
|
||||||
executes.append(args)
|
|
||||||
process_input = kwargs.get('process_input')
|
|
||||||
if process_input:
|
|
||||||
inputs.append(process_input)
|
|
||||||
return "", ""
|
|
||||||
|
|
||||||
self.stubs.Set(utils, 'execute', fake_execute)
|
|
||||||
|
|
||||||
driver = linux_net.LinuxBridgeInterfaceDriver()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def fake_ensure(bridge, interface, network, gateway):
|
|
||||||
return bridge
|
|
||||||
|
|
||||||
self.stubs.Set(linux_net.LinuxBridgeInterfaceDriver,
|
|
||||||
'ensure_bridge', fake_ensure)
|
|
||||||
|
|
||||||
iface = 'eth0'
|
|
||||||
dhcp = '192.168.1.1'
|
|
||||||
network = {'dhcp_server': dhcp,
|
|
||||||
'share_address': False,
|
|
||||||
'bridge': 'br100',
|
|
||||||
'bridge_interface': iface}
|
|
||||||
driver.plug(network, 'fakemac')
|
|
||||||
expected = [
|
|
||||||
('ebtables', '-t', 'filter', '-D', 'INPUT', '-p', 'ARP', '-i',
|
|
||||||
iface, '--arp-ip-dst', dhcp, '-j', 'DROP'),
|
|
||||||
('ebtables', '-t', 'filter', '-I', 'INPUT', '-p', 'ARP', '-i',
|
|
||||||
iface, '--arp-ip-dst', dhcp, '-j', 'DROP'),
|
|
||||||
('ebtables', '-t', 'filter', '-D', 'OUTPUT', '-p', 'ARP', '-o',
|
|
||||||
iface, '--arp-ip-src', dhcp, '-j', 'DROP'),
|
|
||||||
('ebtables', '-t', 'filter', '-I', 'OUTPUT', '-p', 'ARP', '-o',
|
|
||||||
iface, '--arp-ip-src', dhcp, '-j', 'DROP'),
|
|
||||||
('iptables-save', '-c'),
|
|
||||||
('iptables-restore', '-c'),
|
|
||||||
('ip6tables-save', '-c'),
|
|
||||||
('ip6tables-restore', '-c'),
|
|
||||||
]
|
|
||||||
self.assertEqual(executes, expected)
|
|
||||||
expected_inputs = [
|
|
||||||
('-A test-FORWARD -m physdev --physdev-in %s '
|
|
||||||
'-d 255.255.255.255 -p udp --dport 67 -j LOGDROP' % iface),
|
|
||||||
('-A test-FORWARD -m physdev --physdev-out %s '
|
|
||||||
'-d 255.255.255.255 -p udp --dport 67 -j LOGDROP' % iface),
|
|
||||||
('-A test-FORWARD -m physdev --physdev-in %s '
|
|
||||||
'-d 192.168.1.1 -j LOGDROP' % iface),
|
|
||||||
('-A test-FORWARD -m physdev --physdev-out %s '
|
|
||||||
'-s 192.168.1.1 -j LOGDROP' % iface),
|
|
||||||
]
|
|
||||||
for inp in expected_inputs:
|
|
||||||
self.assertIn(inp, inputs[0])
|
|
||||||
|
|
||||||
executes = []
|
|
||||||
inputs = []
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def fake_remove(bridge, gateway):
|
|
||||||
return
|
|
||||||
|
|
||||||
self.stubs.Set(linux_net.LinuxBridgeInterfaceDriver,
|
|
||||||
'remove_bridge', fake_remove)
|
|
||||||
|
|
||||||
driver.unplug(network)
|
|
||||||
expected = [
|
|
||||||
('ebtables', '-t', 'filter', '-D', 'INPUT', '-p', 'ARP', '-i',
|
|
||||||
iface, '--arp-ip-dst', dhcp, '-j', 'DROP'),
|
|
||||||
('ebtables', '-t', 'filter', '-D', 'OUTPUT', '-p', 'ARP', '-o',
|
|
||||||
iface, '--arp-ip-src', dhcp, '-j', 'DROP'),
|
|
||||||
('iptables-save', '-c'),
|
|
||||||
('iptables-restore', '-c'),
|
|
||||||
('ip6tables-save', '-c'),
|
|
||||||
('ip6tables-restore', '-c'),
|
|
||||||
]
|
|
||||||
self.assertEqual(executes, expected)
|
|
||||||
for inp in expected_inputs:
|
|
||||||
self.assertNotIn(inp, inputs[0])
|
|
||||||
|
|
||||||
def _test_initialize_gateway(self, existing, expected, routes=''):
|
def _test_initialize_gateway(self, existing, expected, routes=''):
|
||||||
self.flags(fake_network=False)
|
self.flags(fake_network=False)
|
||||||
|
Loading…
Reference in New Issue
Block a user