Merge "Fix IP spoofing filter blocking all packets."
This commit is contained in:
@@ -28,8 +28,10 @@ LOG = logging.getLogger(__name__)
|
||||
SG_CHAIN = 'sg-chain'
|
||||
INGRESS_DIRECTION = 'ingress'
|
||||
EGRESS_DIRECTION = 'egress'
|
||||
IP_SPOOF_FILTER = 'ip-spoof-filter'
|
||||
CHAIN_NAME_PREFIX = {INGRESS_DIRECTION: 'i',
|
||||
EGRESS_DIRECTION: 'o'}
|
||||
EGRESS_DIRECTION: 'o',
|
||||
IP_SPOOF_FILTER: 's'}
|
||||
LINUX_DEV_LEN = 14
|
||||
|
||||
|
||||
@@ -94,6 +96,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
|
||||
for port in self.filtered_ports.values():
|
||||
self._remove_chain(port, INGRESS_DIRECTION)
|
||||
self._remove_chain(port, EGRESS_DIRECTION)
|
||||
self._remove_chain(port, IP_SPOOF_FILTER)
|
||||
self._remove_chain_by_name_v4v6(SG_CHAIN)
|
||||
|
||||
def _setup_chain(self, port, DIRECTION):
|
||||
@@ -175,15 +178,32 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
|
||||
def _arp_spoofing_rule(self, port):
|
||||
return ['-m mac ! --mac-source %s -j DROP' % port['mac_address']]
|
||||
|
||||
def _setup_ip_spoof_filter_chain(self, port, table, addresses, rules):
|
||||
if len(addresses) == 1:
|
||||
rules.append('! -s %s -j DROP' % addresses[0])
|
||||
elif addresses:
|
||||
chain_name = self._port_chain_name(port, IP_SPOOF_FILTER)
|
||||
table.add_chain(chain_name)
|
||||
for ip in addresses:
|
||||
table.add_rule(chain_name, '-s %s -j RETURN' % ip)
|
||||
table.add_rule(chain_name, '-j DROP')
|
||||
rules.append('-j $%s' % chain_name)
|
||||
|
||||
def _ip_spoofing_rule(self, port, ipv4_rules, ipv6_rules):
|
||||
#Note(nati) allow dhcp or RA packet
|
||||
ipv4_rules += ['-p udp --sport 68 --dport 67 -j RETURN']
|
||||
ipv6_rules += ['-p icmpv6 -j RETURN']
|
||||
ipv4_addresses = []
|
||||
ipv6_addresses = []
|
||||
for ip in port['fixed_ips']:
|
||||
if netaddr.IPAddress(ip).version == 4:
|
||||
ipv4_rules += ['! -s %s -j DROP' % ip]
|
||||
ipv4_addresses.append(ip)
|
||||
else:
|
||||
ipv6_rules += ['! -s %s -j DROP' % ip]
|
||||
ipv6_addresses.append(ip)
|
||||
self._setup_ip_spoof_filter_chain(port, self.iptables.ipv4['filter'],
|
||||
ipv4_addresses, ipv4_rules)
|
||||
self._setup_ip_spoof_filter_chain(port, self.iptables.ipv6['filter'],
|
||||
ipv6_addresses, ipv6_rules)
|
||||
|
||||
def _drop_dhcp_rule(self):
|
||||
#Note(nati) Drop dhcp packet from VM
|
||||
|
||||
@@ -839,6 +839,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
|
||||
call.add_rule('sg-chain', '-j ACCEPT'),
|
||||
call.ensure_remove_chain('ifake_dev'),
|
||||
call.ensure_remove_chain('ofake_dev'),
|
||||
call.ensure_remove_chain('sfake_dev'),
|
||||
call.ensure_remove_chain('sg-chain'),
|
||||
call.add_chain('sg-chain'),
|
||||
call.add_chain('ifake_dev'),
|
||||
@@ -889,6 +890,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
|
||||
call.add_rule('sg-chain', '-j ACCEPT'),
|
||||
call.ensure_remove_chain('ifake_dev'),
|
||||
call.ensure_remove_chain('ofake_dev'),
|
||||
call.ensure_remove_chain('sfake_dev'),
|
||||
call.ensure_remove_chain('sg-chain'),
|
||||
call.add_chain('sg-chain')]
|
||||
|
||||
@@ -914,3 +916,62 @@ class IptablesFirewallTestCase(base.BaseTestCase):
|
||||
pass
|
||||
self.iptables_inst.assert_has_calls([call.defer_apply_on(),
|
||||
call.defer_apply_off()])
|
||||
|
||||
def test_ip_spoofing_filter_with_multiple_ips(self):
|
||||
port = {'device': 'tapfake_dev',
|
||||
'mac_address': 'ff:ff:ff:ff',
|
||||
'fixed_ips': ['10.0.0.1', 'fe80::1', '10.0.0.2']}
|
||||
self.firewall.prepare_port_filter(port)
|
||||
calls = [call.add_chain('sg-fallback'),
|
||||
call.add_rule('sg-fallback', '-j DROP'),
|
||||
call.ensure_remove_chain('sg-chain'),
|
||||
call.add_chain('sg-chain'),
|
||||
call.add_chain('ifake_dev'),
|
||||
call.add_rule('FORWARD',
|
||||
'-m physdev --physdev-is-bridged '
|
||||
'--physdev-out tapfake_dev '
|
||||
'-j $sg-chain'),
|
||||
call.add_rule('sg-chain',
|
||||
'-m physdev --physdev-is-bridged '
|
||||
'--physdev-out tapfake_dev '
|
||||
'-j $ifake_dev'),
|
||||
call.add_rule(
|
||||
'ifake_dev', '-m state --state INVALID -j DROP'),
|
||||
call.add_rule(
|
||||
'ifake_dev',
|
||||
'-m state --state ESTABLISHED,RELATED -j RETURN'),
|
||||
call.add_rule('ifake_dev', '-j $sg-fallback'),
|
||||
call.add_chain('ofake_dev'),
|
||||
call.add_rule('FORWARD',
|
||||
'-m physdev --physdev-is-bridged '
|
||||
'--physdev-in tapfake_dev '
|
||||
'-j $sg-chain'),
|
||||
call.add_rule('sg-chain',
|
||||
'-m physdev --physdev-is-bridged '
|
||||
'--physdev-in tapfake_dev '
|
||||
'-j $ofake_dev'),
|
||||
call.add_rule('INPUT',
|
||||
'-m physdev --physdev-is-bridged '
|
||||
'--physdev-in tapfake_dev '
|
||||
'-j $ofake_dev'),
|
||||
call.add_chain('sfake_dev'),
|
||||
call.add_rule('sfake_dev', '-s 10.0.0.1 -j RETURN'),
|
||||
call.add_rule('sfake_dev', '-s 10.0.0.2 -j RETURN'),
|
||||
call.add_rule('sfake_dev', '-j DROP'),
|
||||
call.add_rule(
|
||||
'ofake_dev', '-m mac ! --mac-source ff:ff:ff:ff -j DROP'),
|
||||
call.add_rule(
|
||||
'ofake_dev',
|
||||
'-p udp --sport 68 --dport 67 -j RETURN'),
|
||||
call.add_rule('ofake_dev', '-j $sfake_dev'),
|
||||
call.add_rule(
|
||||
'ofake_dev',
|
||||
'-p udp --sport 67 --dport 68 -j DROP'),
|
||||
call.add_rule(
|
||||
'ofake_dev', '-m state --state INVALID -j DROP'),
|
||||
call.add_rule(
|
||||
'ofake_dev',
|
||||
'-m state --state ESTABLISHED,RELATED -j RETURN'),
|
||||
call.add_rule('ofake_dev', '-j $sg-fallback'),
|
||||
call.add_rule('sg-chain', '-j ACCEPT')]
|
||||
self.v4filter_inst.assert_has_calls(calls)
|
||||
|
||||
Reference in New Issue
Block a user