Skip to content

Commit d425a40

Browse files
Rene Diepstratenyadvr
authored andcommitted
sg: add secondary ips to the correct ipset based on ip family (#2990)
Currently secondary ipv6 addresses are added to the ipv4 ipset in security_group.py. This doesn't work, so this patch adds a function to split a set of ips in ipv4 and ipv6 addresses. Both the default_network_rules and network_rules_vmSecondaryIp functions now utilise this function and add the ips to the appropriate ipsets.
1 parent a84f7df commit d425a40

File tree

1 file changed

+51
-21
lines changed

1 file changed

+51
-21
lines changed

scripts/vm/network/security_group.py

Lines changed: 51 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,21 @@ def ipv6_link_local_addr(mac=None):
189189
return IPAddress('fe80::' + ':'.join(re.findall(r'.{4}', eui64)))
190190

191191

192+
def split_ips_by_family(ips):
193+
if type(ips) is str:
194+
ips = [ip for ip in ips.split(';') if ip != '']
195+
196+
ip4s = []
197+
ip6s = []
198+
for ip in ips:
199+
version = IPNetwork(ip).version
200+
if version == 4:
201+
ip4s.append(ip)
202+
elif version == 6:
203+
ip6s.append(ip)
204+
return ip4s, ip6s
205+
206+
192207
def destroy_network_rules_for_vm(vm_name, vif=None):
193208
vmchain = iptables_chain_name(vm_name)
194209
vmchain_egress = egress_chain_name(vm_name)
@@ -420,10 +435,17 @@ def network_rules_vmSecondaryIp(vm_name, ip_secondary, action):
420435
domid = getvmId(vm_name)
421436

422437
vmchain = vm_name
423-
add_to_ipset(vmchain, [ip_secondary], action)
438+
vmchain6 = vmchain + '-6'
439+
440+
ip4s, ip6s = split_ips_by_family(ip_secondary)
441+
442+
add_to_ipset(vmchain, ip4s, action)
424443

425-
#add ebtables rules for the secondary ip
426-
ebtables_rules_vmip(vm_name, [ip_secondary], action)
444+
#add ebtables rules for the secondary ips
445+
ebtables_rules_vmip(vm_name, ip4s, action)
446+
447+
#add ipv6 addresses to ipv6 ipset
448+
add_to_ipset(vmchain6, ip6s, action)
427449

428450
return 'true'
429451

@@ -473,6 +495,8 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vm_mac, vif, brname, se
473495

474496
action = "-A"
475497
vmipsetName = ipset_chain_name(vm_name)
498+
vmipsetName6 = vmipsetName + '-6'
499+
476500
#create ipset and add vm ips to that ip set
477501
if create_ipset_forvm(vmipsetName) == False:
478502
logging.debug(" failed to create ipset for rule " + str(tokens))
@@ -487,12 +511,17 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vm_mac, vif, brname, se
487511
secIpSet = "1"
488512
ips = sec_ips.split(';')
489513
ips.pop()
490-
if ips[0] == "0":
491-
secIpSet = "0";
514+
if len(ips) == 0 or ips[0] == "0":
515+
secIpSet = "0"
516+
ip4s = []
517+
ip6s = []
492518

493519
if secIpSet == "1":
494-
logging.debug("Adding ipset for secondary ips")
495-
add_to_ipset(vmipsetName, ips, action)
520+
logging.debug("Adding ipset for secondary ipv4 addresses")
521+
ip4s, ip6s = split_ips_by_family(ips)
522+
523+
add_to_ipset(vmipsetName, ip4s, action)
524+
496525
if write_secip_log_for_vm(vm_name, sec_ips, vm_id) == False:
497526
logging.debug("Failed to log default network rules, ignoring")
498527

@@ -518,15 +547,13 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vm_mac, vif, brname, se
518547

519548
default_ebtables_rules(vm_name, vm_ip, vm_mac, vif)
520549
#default ebtables rules for vm secondary ips
521-
ebtables_rules_vmip(vm_name, ips, "-I")
550+
ebtables_rules_vmip(vm_name, ip4s, "-I")
522551

523552
if vm_ip is not None:
524553
if write_rule_log_for_vm(vmName, vm_id, vm_ip, domID, '_initial_', '-1') == False:
525554
logging.debug("Failed to log default network rules, ignoring")
526555

527-
vm_ip6_set_name = vm_name + '-6'
528-
529-
if not create_ipset_forvm(vm_ip6_set_name, family='inet6', type='hash:net'):
556+
if not create_ipset_forvm(vmipsetName6, family='inet6', type='hash:net'):
530557
logging.debug(" failed to create ivp6 ipset for rule " + str(tokens))
531558
return 'false'
532559

@@ -538,7 +565,10 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vm_mac, vif, brname, se
538565
except AddrFormatError:
539566
pass
540567

541-
add_to_ipset(vm_ip6_set_name, vm_ip6_addr, action)
568+
add_to_ipset(vmipsetName6, vm_ip6_addr, action)
569+
if secIpSet == "1":
570+
logging.debug("Adding ipset for secondary ipv6 addresses")
571+
add_to_ipset(vmipsetName6, ip6s, action)
542572

543573
try:
544574
execute('ip6tables -A ' + brfw + '-OUT' + ' -m physdev --physdev-is-bridged --physdev-out ' + vif + ' -j ' + vmchain_default)
@@ -553,20 +583,20 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vm_mac, vif, brname, se
553583
# Allow neighbor solicitations and advertisements
554584
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -p icmpv6 --icmpv6-type neighbor-solicitation -m hl --hl-eq 255 -j RETURN')
555585
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-out ' + vif + ' -p icmpv6 --icmpv6-type neighbor-solicitation -m hl --hl-eq 255 -j ACCEPT')
556-
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -p icmpv6 --icmpv6-type neighbor-advertisement -m set --match-set ' + vm_ip6_set_name + ' src -m hl --hl-eq 255 -j RETURN')
586+
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -p icmpv6 --icmpv6-type neighbor-advertisement -m set --match-set ' + vmipsetName6 + ' src -m hl --hl-eq 255 -j RETURN')
557587
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-out ' + vif + ' -p icmpv6 --icmpv6-type neighbor-advertisement -m hl --hl-eq 255 -j ACCEPT')
558588

559589
# Packets to allow as per RFC4890
560-
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -p icmpv6 --icmpv6-type packet-too-big -m set --match-set ' + vm_ip6_set_name + ' src -j RETURN')
590+
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -p icmpv6 --icmpv6-type packet-too-big -m set --match-set ' + vmipsetName6 + ' src -j RETURN')
561591
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-out ' + vif + ' -p icmpv6 --icmpv6-type packet-too-big -j ACCEPT')
562592

563-
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -p icmpv6 --icmpv6-type destination-unreachable -m set --match-set ' + vm_ip6_set_name + ' src -j RETURN')
593+
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -p icmpv6 --icmpv6-type destination-unreachable -m set --match-set ' + vmipsetName6 + ' src -j RETURN')
564594
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-out ' + vif + ' -p icmpv6 --icmpv6-type destination-unreachable -j ACCEPT')
565595

566-
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -p icmpv6 --icmpv6-type time-exceeded -m set --match-set ' + vm_ip6_set_name + ' src -j RETURN')
596+
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -p icmpv6 --icmpv6-type time-exceeded -m set --match-set ' + vmipsetName6 + ' src -j RETURN')
567597
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-out ' + vif + ' -p icmpv6 --icmpv6-type time-exceeded -j ACCEPT')
568598

569-
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -p icmpv6 --icmpv6-type parameter-problem -m set --match-set ' + vm_ip6_set_name + ' src -j RETURN')
599+
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -p icmpv6 --icmpv6-type parameter-problem -m set --match-set ' + vmipsetName6 + ' src -j RETURN')
570600
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-out ' + vif + ' -p icmpv6 --icmpv6-type parameter-problem -j ACCEPT')
571601

572602
# MLDv2 discovery packets
@@ -578,14 +608,14 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vm_mac, vif, brname, se
578608
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -p udp --sport 547 ! --dst fe80::/64 -j DROP')
579609

580610
# Always allow outbound DNS over UDP and TCP
581-
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -p udp --dport 53 -m set --match-set ' + vm_ip6_set_name + ' src -j RETURN')
582-
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -p tcp --dport 53 -m set --match-set ' + vm_ip6_set_name + ' src -j RETURN')
611+
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -p udp --dport 53 -m set --match-set ' + vmipsetName6 + ' src -j RETURN')
612+
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -p tcp --dport 53 -m set --match-set ' + vmipsetName6 + ' src -j RETURN')
583613

584614
# Prevent source address spoofing
585-
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -m set ! --match-set ' + vm_ip6_set_name + ' src -j DROP')
615+
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -m set ! --match-set ' + vmipsetName6 + ' src -j DROP')
586616

587617
# Send proper traffic to the egress chain of the Instance
588-
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -m set --match-set ' + vm_ip6_set_name + ' src -j ' + vmchain_egress)
618+
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-in ' + vif + ' -m set --match-set ' + vmipsetName6 + ' src -j ' + vmchain_egress)
589619

590620
execute('ip6tables -A ' + vmchain_default + ' -m physdev --physdev-is-bridged --physdev-out ' + vif + ' -j ' + vmchain)
591621

0 commit comments

Comments
 (0)