Skip to content

Commit

Permalink
Merge pull request #297 from robhoes/CA-226099
Browse files Browse the repository at this point in the history
CA-226099: setup-vif-rules: drop all traffic on disabled VIFs
  • Loading branch information
Jon Ludlam authored Oct 20, 2016
2 parents f000685 + 826adc2 commit d150401
Showing 1 changed file with 83 additions and 79 deletions.
162 changes: 83 additions & 79 deletions scripts/setup-vif-rules
Original file line number Diff line number Diff line change
Expand Up @@ -75,33 +75,36 @@ def clear_bridge_rules(vif_name):
do_chain_action(ebtables, "-X", vif_chain)

def create_bridge_rules(vif_name, config):
vif_chain = get_chain_name(vif_name)
# Forward all traffic on this VIF to a new chain, with default policy DROP.
do_chain_action(ebtables, "-N", vif_chain)
do_chain_action(ebtables, "-A", "FORWARD", ["-i", vif_name, "-j", vif_chain])
do_chain_action(ebtables, "-A", "FORWARD", ["-o", vif_name, "-j", vif_chain])
do_chain_action(ebtables, "-P", vif_chain, ["DROP"])
# We now need to create rules to allow valid traffic.
mac = config["mac"]
# We only fully support IPv4 multitenancy with bridge.
# We allow all IPv6 traffic if any IPv6 addresses are associated with the VIF.
ipv4_allowed = config["ipv4_allowed"]
ipv6_allowed = config["ipv6_allowed"]
# Accept all traffic going to the VM.
do_chain_action(ebtables, "-A", vif_chain, ["-o", vif_name, "-j", "ACCEPT"])
# Drop everything not coming from the correct MAC.
do_chain_action(ebtables, "-A", vif_chain, ["-s", "!", mac, "-i", vif_name, "-j", "DROP"])
# Accept DHCP.
do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv4", "-i", vif_name, "--ip-protocol", "UDP", "--ip-dport", "67", "-j", "ACCEPT"])
for ipv4 in ipv4_allowed:
# Accept ARP travelling from known IP addresses, also filtering ARP replies by MAC.
do_chain_action(ebtables, "-A", vif_chain, ["-p", "ARP", "-i", vif_name, "--arp-opcode", "Request", "--arp-ip-src", ipv4, "-j", "ACCEPT"])
do_chain_action(ebtables, "-A", vif_chain, ["-p", "ARP", "-i", vif_name, "--arp-opcode", "Reply", "--arp-ip-src", ipv4, "--arp-mac-src", mac, "-j", "ACCEPT"])
# Accept IP travelling from known IP addresses.
do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv4", "-i", vif_name, "--ip-src", ipv4, "-j", "ACCEPT"])
if ipv6_allowed != []:
# Accept all IPv6 traffic.
do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv6", "-i", vif_name, "-j", "ACCEPT"])
locking_mode = config["locking_mode"]
if locking_mode == "locked" or locking_mode == "disabled":
vif_chain = get_chain_name(vif_name)
# Forward all traffic on this VIF to a new chain, with default policy DROP.
do_chain_action(ebtables, "-N", vif_chain)
do_chain_action(ebtables, "-A", "FORWARD", ["-i", vif_name, "-j", vif_chain])
do_chain_action(ebtables, "-A", "FORWARD", ["-o", vif_name, "-j", vif_chain])
do_chain_action(ebtables, "-P", vif_chain, ["DROP"])
if locking_mode == "locked":
# We now need to create rules to allow valid traffic.
mac = config["mac"]
# We only fully support IPv4 multitenancy with bridge.
# We allow all IPv6 traffic if any IPv6 addresses are associated with the VIF.
ipv4_allowed = config["ipv4_allowed"]
ipv6_allowed = config["ipv6_allowed"]
# Accept all traffic going to the VM.
do_chain_action(ebtables, "-A", vif_chain, ["-o", vif_name, "-j", "ACCEPT"])
# Drop everything not coming from the correct MAC.
do_chain_action(ebtables, "-A", vif_chain, ["-s", "!", mac, "-i", vif_name, "-j", "DROP"])
# Accept DHCP.
do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv4", "-i", vif_name, "--ip-protocol", "UDP", "--ip-dport", "67", "-j", "ACCEPT"])
for ipv4 in ipv4_allowed:
# Accept ARP travelling from known IP addresses, also filtering ARP replies by MAC.
do_chain_action(ebtables, "-A", vif_chain, ["-p", "ARP", "-i", vif_name, "--arp-opcode", "Request", "--arp-ip-src", ipv4, "-j", "ACCEPT"])
do_chain_action(ebtables, "-A", vif_chain, ["-p", "ARP", "-i", vif_name, "--arp-opcode", "Reply", "--arp-ip-src", ipv4, "--arp-mac-src", mac, "-j", "ACCEPT"])
# Accept IP travelling from known IP addresses.
do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv4", "-i", vif_name, "--ip-src", ipv4, "-j", "ACCEPT"])
if ipv6_allowed != []:
# Accept all IPv6 traffic.
do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv6", "-i", vif_name, "-j", "ACCEPT"])

def acquire_lock(path):
lock_file = open(path, 'w')
Expand All @@ -123,9 +126,7 @@ def handle_bridge(vif_name, domuuid, devid, action):
clear_bridge_rules(vif_name)
if action == "filter":
config = get_locking_config(domuuid, devid)
locking_mode = config["locking_mode"]
if locking_mode == "locked":
create_bridge_rules(vif_name, config)
create_bridge_rules(vif_name, config)
ip_link_set(vif_name, "up")

###############################################################################
Expand All @@ -143,53 +144,58 @@ def add_flow(bridge_name, args):
doexec([ofctl, "add-flow", bridge_name, "cookie=1," + args])

def create_vswitch_rules(bridge_name, port, config):
mac = config["mac"]
ipv4_allowed = config["ipv4_allowed"]
ipv6_allowed = config["ipv6_allowed"]
# Allow DHCP traffic (outgoing UDP on port 67).
add_flow(bridge_name, "in_port=%s,priority=8000,dl_type=0x0800,nw_proto=0x11,"
"tp_dst=67,dl_src=%s,idle_timeout=0,action=normal" % (port, mac))
# Filter ARP requests.
add_flow(bridge_name, "in_port=%s,priority=7000,dl_type=0x0806,dl_src=%s,arp_sha=%s,"
"nw_src=0.0.0.0,idle_timeout=0,action=normal" % (port, mac, mac))
for ipv4 in ipv4_allowed:
# Filter ARP responses.
locking_mode = config["locking_mode"]
if locking_mode == "locked":
mac = config["mac"]
ipv4_allowed = config["ipv4_allowed"]
ipv6_allowed = config["ipv6_allowed"]
# Allow DHCP traffic (outgoing UDP on port 67).
add_flow(bridge_name, "in_port=%s,priority=8000,dl_type=0x0800,nw_proto=0x11,"
"tp_dst=67,dl_src=%s,idle_timeout=0,action=normal" % (port, mac))
# Filter ARP requests.
add_flow(bridge_name, "in_port=%s,priority=7000,dl_type=0x0806,dl_src=%s,arp_sha=%s,"
"nw_src=%s,idle_timeout=0,action=normal" % (port, mac, mac, ipv4))
# Allow traffic from specified ipv4 addresses.
add_flow(bridge_name, "in_port=%s,priority=6000,dl_type=0x0800,nw_src=%s,"
"dl_src=%s,idle_timeout=0,action=normal" % (port, ipv4, mac))
for ipv6 in ipv6_allowed:
# Neighbour solicitation.
add_flow(bridge_name, "in_port=%s,priority=8000,dl_src=%s,icmp6,ipv6_src=%s,"
"icmp_type=135,nd_sll=%s,idle_timeout=0,action=normal" % (port, mac, ipv6, mac))
# Neighbour advertisement.
add_flow(bridge_name, "in_port=%s,priority=8000,dl_src=%s,icmp6,ipv6_src=%s,"
"icmp_type=136,nd_target=%s,idle_timeout=0,action=normal" % (port, mac, ipv6, ipv6))
# Allow traffic from specified ipv6 addresses.
add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,icmp6,action=normal" % (port, mac, ipv6))
add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,tcp6,action=normal" % (port, mac, ipv6))
add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,udp6,action=normal" % (port, mac, ipv6))
# Drop all other neighbour discovery.
add_flow(bridge_name, "in_port=%s,priority=7000,icmp6,icmp_type=135,action=drop" % port)
add_flow(bridge_name, "in_port=%s,priority=7000,icmp6,icmp_type=136,action=drop" % port)
# Drop other specific ICMPv6 types.
# Router advertisement.
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=134,action=drop" % port)
# Redirect gateway.
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=137,action=drop" % port)
# Mobile prefix solicitation.
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=146,action=drop" % port)
# Mobile prefix advertisement.
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=147,action=drop" % port)
# Multicast router advertisement.
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=151,action=drop" % port)
# Multicast router solicitation.
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=152,action=drop" % port)
# Multicast router termination.
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=153,action=drop" % port)
# Drop everything else.
add_flow(bridge_name, "in_port=%s,priority=4000,idle_timeout=0,action=drop" % port)
"nw_src=0.0.0.0,idle_timeout=0,action=normal" % (port, mac, mac))
for ipv4 in ipv4_allowed:
# Filter ARP responses.
add_flow(bridge_name, "in_port=%s,priority=7000,dl_type=0x0806,dl_src=%s,arp_sha=%s,"
"nw_src=%s,idle_timeout=0,action=normal" % (port, mac, mac, ipv4))
# Allow traffic from specified ipv4 addresses.
add_flow(bridge_name, "in_port=%s,priority=6000,dl_type=0x0800,nw_src=%s,"
"dl_src=%s,idle_timeout=0,action=normal" % (port, ipv4, mac))
for ipv6 in ipv6_allowed:
# Neighbour solicitation.
add_flow(bridge_name, "in_port=%s,priority=8000,dl_src=%s,icmp6,ipv6_src=%s,"
"icmp_type=135,nd_sll=%s,idle_timeout=0,action=normal" % (port, mac, ipv6, mac))
# Neighbour advertisement.
add_flow(bridge_name, "in_port=%s,priority=8000,dl_src=%s,icmp6,ipv6_src=%s,"
"icmp_type=136,nd_target=%s,idle_timeout=0,action=normal" % (port, mac, ipv6, ipv6))
# Allow traffic from specified ipv6 addresses.
add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,icmp6,action=normal" % (port, mac, ipv6))
add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,tcp6,action=normal" % (port, mac, ipv6))
add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,udp6,action=normal" % (port, mac, ipv6))
# Drop all other neighbour discovery.
add_flow(bridge_name, "in_port=%s,priority=7000,icmp6,icmp_type=135,action=drop" % port)
add_flow(bridge_name, "in_port=%s,priority=7000,icmp6,icmp_type=136,action=drop" % port)
# Drop other specific ICMPv6 types.
# Router advertisement.
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=134,action=drop" % port)
# Redirect gateway.
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=137,action=drop" % port)
# Mobile prefix solicitation.
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=146,action=drop" % port)
# Mobile prefix advertisement.
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=147,action=drop" % port)
# Multicast router advertisement.
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=151,action=drop" % port)
# Multicast router solicitation.
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=152,action=drop" % port)
# Multicast router termination.
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=153,action=drop" % port)
# Drop everything else.
add_flow(bridge_name, "in_port=%s,priority=4000,idle_timeout=0,action=drop" % port)
elif locking_mode == "disabled":
# Drop everything coming in on this port.
add_flow(bridge_name, "in_port=%s,priority=4000,idle_timeout=0,action=drop" % port)

def get_bridge_name_vswitch(vif_name):
'''return bridge vif belong to'''
Expand All @@ -208,9 +214,7 @@ def handle_vswitch(vif_name, domuuid, devid, action):
clear_vswitch_rules(bridge_name, port)
if action == "filter":
config = get_locking_config(domuuid, devid)
locking_mode = config["locking_mode"]
if locking_mode == "locked":
create_vswitch_rules(bridge_name, port, config)
create_vswitch_rules(bridge_name, port, config)
ip_link_set(vif_name, "up")

###############################################################################
Expand Down

0 comments on commit d150401

Please sign in to comment.