Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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