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
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):
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
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'),
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')]
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)