Skip to content

Commit d150401

Browse files
author
Jon Ludlam
authored
Merge pull request #297 from robhoes/CA-226099
CA-226099: setup-vif-rules: drop all traffic on disabled VIFs
2 parents f000685 + 826adc2 commit d150401

File tree

1 file changed

+83
-79
lines changed

1 file changed

+83
-79
lines changed

scripts/setup-vif-rules

Lines changed: 83 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -75,33 +75,36 @@ def clear_bridge_rules(vif_name):
7575
do_chain_action(ebtables, "-X", vif_chain)
7676

7777
def create_bridge_rules(vif_name, config):
78-
vif_chain = get_chain_name(vif_name)
79-
# Forward all traffic on this VIF to a new chain, with default policy DROP.
80-
do_chain_action(ebtables, "-N", vif_chain)
81-
do_chain_action(ebtables, "-A", "FORWARD", ["-i", vif_name, "-j", vif_chain])
82-
do_chain_action(ebtables, "-A", "FORWARD", ["-o", vif_name, "-j", vif_chain])
83-
do_chain_action(ebtables, "-P", vif_chain, ["DROP"])
84-
# We now need to create rules to allow valid traffic.
85-
mac = config["mac"]
86-
# We only fully support IPv4 multitenancy with bridge.
87-
# We allow all IPv6 traffic if any IPv6 addresses are associated with the VIF.
88-
ipv4_allowed = config["ipv4_allowed"]
89-
ipv6_allowed = config["ipv6_allowed"]
90-
# Accept all traffic going to the VM.
91-
do_chain_action(ebtables, "-A", vif_chain, ["-o", vif_name, "-j", "ACCEPT"])
92-
# Drop everything not coming from the correct MAC.
93-
do_chain_action(ebtables, "-A", vif_chain, ["-s", "!", mac, "-i", vif_name, "-j", "DROP"])
94-
# Accept DHCP.
95-
do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv4", "-i", vif_name, "--ip-protocol", "UDP", "--ip-dport", "67", "-j", "ACCEPT"])
96-
for ipv4 in ipv4_allowed:
97-
# Accept ARP travelling from known IP addresses, also filtering ARP replies by MAC.
98-
do_chain_action(ebtables, "-A", vif_chain, ["-p", "ARP", "-i", vif_name, "--arp-opcode", "Request", "--arp-ip-src", ipv4, "-j", "ACCEPT"])
99-
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"])
100-
# Accept IP travelling from known IP addresses.
101-
do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv4", "-i", vif_name, "--ip-src", ipv4, "-j", "ACCEPT"])
102-
if ipv6_allowed != []:
103-
# Accept all IPv6 traffic.
104-
do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv6", "-i", vif_name, "-j", "ACCEPT"])
78+
locking_mode = config["locking_mode"]
79+
if locking_mode == "locked" or locking_mode == "disabled":
80+
vif_chain = get_chain_name(vif_name)
81+
# Forward all traffic on this VIF to a new chain, with default policy DROP.
82+
do_chain_action(ebtables, "-N", vif_chain)
83+
do_chain_action(ebtables, "-A", "FORWARD", ["-i", vif_name, "-j", vif_chain])
84+
do_chain_action(ebtables, "-A", "FORWARD", ["-o", vif_name, "-j", vif_chain])
85+
do_chain_action(ebtables, "-P", vif_chain, ["DROP"])
86+
if locking_mode == "locked":
87+
# We now need to create rules to allow valid traffic.
88+
mac = config["mac"]
89+
# We only fully support IPv4 multitenancy with bridge.
90+
# We allow all IPv6 traffic if any IPv6 addresses are associated with the VIF.
91+
ipv4_allowed = config["ipv4_allowed"]
92+
ipv6_allowed = config["ipv6_allowed"]
93+
# Accept all traffic going to the VM.
94+
do_chain_action(ebtables, "-A", vif_chain, ["-o", vif_name, "-j", "ACCEPT"])
95+
# Drop everything not coming from the correct MAC.
96+
do_chain_action(ebtables, "-A", vif_chain, ["-s", "!", mac, "-i", vif_name, "-j", "DROP"])
97+
# Accept DHCP.
98+
do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv4", "-i", vif_name, "--ip-protocol", "UDP", "--ip-dport", "67", "-j", "ACCEPT"])
99+
for ipv4 in ipv4_allowed:
100+
# Accept ARP travelling from known IP addresses, also filtering ARP replies by MAC.
101+
do_chain_action(ebtables, "-A", vif_chain, ["-p", "ARP", "-i", vif_name, "--arp-opcode", "Request", "--arp-ip-src", ipv4, "-j", "ACCEPT"])
102+
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"])
103+
# Accept IP travelling from known IP addresses.
104+
do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv4", "-i", vif_name, "--ip-src", ipv4, "-j", "ACCEPT"])
105+
if ipv6_allowed != []:
106+
# Accept all IPv6 traffic.
107+
do_chain_action(ebtables, "-A", vif_chain, ["-p", "IPv6", "-i", vif_name, "-j", "ACCEPT"])
105108

106109
def acquire_lock(path):
107110
lock_file = open(path, 'w')
@@ -123,9 +126,7 @@ def handle_bridge(vif_name, domuuid, devid, action):
123126
clear_bridge_rules(vif_name)
124127
if action == "filter":
125128
config = get_locking_config(domuuid, devid)
126-
locking_mode = config["locking_mode"]
127-
if locking_mode == "locked":
128-
create_bridge_rules(vif_name, config)
129+
create_bridge_rules(vif_name, config)
129130
ip_link_set(vif_name, "up")
130131

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

145146
def create_vswitch_rules(bridge_name, port, config):
146-
mac = config["mac"]
147-
ipv4_allowed = config["ipv4_allowed"]
148-
ipv6_allowed = config["ipv6_allowed"]
149-
# Allow DHCP traffic (outgoing UDP on port 67).
150-
add_flow(bridge_name, "in_port=%s,priority=8000,dl_type=0x0800,nw_proto=0x11,"
151-
"tp_dst=67,dl_src=%s,idle_timeout=0,action=normal" % (port, mac))
152-
# Filter ARP requests.
153-
add_flow(bridge_name, "in_port=%s,priority=7000,dl_type=0x0806,dl_src=%s,arp_sha=%s,"
154-
"nw_src=0.0.0.0,idle_timeout=0,action=normal" % (port, mac, mac))
155-
for ipv4 in ipv4_allowed:
156-
# Filter ARP responses.
147+
locking_mode = config["locking_mode"]
148+
if locking_mode == "locked":
149+
mac = config["mac"]
150+
ipv4_allowed = config["ipv4_allowed"]
151+
ipv6_allowed = config["ipv6_allowed"]
152+
# Allow DHCP traffic (outgoing UDP on port 67).
153+
add_flow(bridge_name, "in_port=%s,priority=8000,dl_type=0x0800,nw_proto=0x11,"
154+
"tp_dst=67,dl_src=%s,idle_timeout=0,action=normal" % (port, mac))
155+
# Filter ARP requests.
157156
add_flow(bridge_name, "in_port=%s,priority=7000,dl_type=0x0806,dl_src=%s,arp_sha=%s,"
158-
"nw_src=%s,idle_timeout=0,action=normal" % (port, mac, mac, ipv4))
159-
# Allow traffic from specified ipv4 addresses.
160-
add_flow(bridge_name, "in_port=%s,priority=6000,dl_type=0x0800,nw_src=%s,"
161-
"dl_src=%s,idle_timeout=0,action=normal" % (port, ipv4, mac))
162-
for ipv6 in ipv6_allowed:
163-
# Neighbour solicitation.
164-
add_flow(bridge_name, "in_port=%s,priority=8000,dl_src=%s,icmp6,ipv6_src=%s,"
165-
"icmp_type=135,nd_sll=%s,idle_timeout=0,action=normal" % (port, mac, ipv6, mac))
166-
# Neighbour advertisement.
167-
add_flow(bridge_name, "in_port=%s,priority=8000,dl_src=%s,icmp6,ipv6_src=%s,"
168-
"icmp_type=136,nd_target=%s,idle_timeout=0,action=normal" % (port, mac, ipv6, ipv6))
169-
# Allow traffic from specified ipv6 addresses.
170-
add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,icmp6,action=normal" % (port, mac, ipv6))
171-
add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,tcp6,action=normal" % (port, mac, ipv6))
172-
add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,udp6,action=normal" % (port, mac, ipv6))
173-
# Drop all other neighbour discovery.
174-
add_flow(bridge_name, "in_port=%s,priority=7000,icmp6,icmp_type=135,action=drop" % port)
175-
add_flow(bridge_name, "in_port=%s,priority=7000,icmp6,icmp_type=136,action=drop" % port)
176-
# Drop other specific ICMPv6 types.
177-
# Router advertisement.
178-
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=134,action=drop" % port)
179-
# Redirect gateway.
180-
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=137,action=drop" % port)
181-
# Mobile prefix solicitation.
182-
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=146,action=drop" % port)
183-
# Mobile prefix advertisement.
184-
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=147,action=drop" % port)
185-
# Multicast router advertisement.
186-
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=151,action=drop" % port)
187-
# Multicast router solicitation.
188-
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=152,action=drop" % port)
189-
# Multicast router termination.
190-
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=153,action=drop" % port)
191-
# Drop everything else.
192-
add_flow(bridge_name, "in_port=%s,priority=4000,idle_timeout=0,action=drop" % port)
157+
"nw_src=0.0.0.0,idle_timeout=0,action=normal" % (port, mac, mac))
158+
for ipv4 in ipv4_allowed:
159+
# Filter ARP responses.
160+
add_flow(bridge_name, "in_port=%s,priority=7000,dl_type=0x0806,dl_src=%s,arp_sha=%s,"
161+
"nw_src=%s,idle_timeout=0,action=normal" % (port, mac, mac, ipv4))
162+
# Allow traffic from specified ipv4 addresses.
163+
add_flow(bridge_name, "in_port=%s,priority=6000,dl_type=0x0800,nw_src=%s,"
164+
"dl_src=%s,idle_timeout=0,action=normal" % (port, ipv4, mac))
165+
for ipv6 in ipv6_allowed:
166+
# Neighbour solicitation.
167+
add_flow(bridge_name, "in_port=%s,priority=8000,dl_src=%s,icmp6,ipv6_src=%s,"
168+
"icmp_type=135,nd_sll=%s,idle_timeout=0,action=normal" % (port, mac, ipv6, mac))
169+
# Neighbour advertisement.
170+
add_flow(bridge_name, "in_port=%s,priority=8000,dl_src=%s,icmp6,ipv6_src=%s,"
171+
"icmp_type=136,nd_target=%s,idle_timeout=0,action=normal" % (port, mac, ipv6, ipv6))
172+
# Allow traffic from specified ipv6 addresses.
173+
add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,icmp6,action=normal" % (port, mac, ipv6))
174+
add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,tcp6,action=normal" % (port, mac, ipv6))
175+
add_flow(bridge_name, "in_port=%s,priority=5000,dl_src=%s,ipv6_src=%s,udp6,action=normal" % (port, mac, ipv6))
176+
# Drop all other neighbour discovery.
177+
add_flow(bridge_name, "in_port=%s,priority=7000,icmp6,icmp_type=135,action=drop" % port)
178+
add_flow(bridge_name, "in_port=%s,priority=7000,icmp6,icmp_type=136,action=drop" % port)
179+
# Drop other specific ICMPv6 types.
180+
# Router advertisement.
181+
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=134,action=drop" % port)
182+
# Redirect gateway.
183+
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=137,action=drop" % port)
184+
# Mobile prefix solicitation.
185+
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=146,action=drop" % port)
186+
# Mobile prefix advertisement.
187+
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=147,action=drop" % port)
188+
# Multicast router advertisement.
189+
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=151,action=drop" % port)
190+
# Multicast router solicitation.
191+
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=152,action=drop" % port)
192+
# Multicast router termination.
193+
add_flow(bridge_name, "in_port=%s,priority=6000,icmp6,icmp_type=153,action=drop" % port)
194+
# Drop everything else.
195+
add_flow(bridge_name, "in_port=%s,priority=4000,idle_timeout=0,action=drop" % port)
196+
elif locking_mode == "disabled":
197+
# Drop everything coming in on this port.
198+
add_flow(bridge_name, "in_port=%s,priority=4000,idle_timeout=0,action=drop" % port)
193199

194200
def get_bridge_name_vswitch(vif_name):
195201
'''return bridge vif belong to'''
@@ -208,9 +214,7 @@ def handle_vswitch(vif_name, domuuid, devid, action):
208214
clear_vswitch_rules(bridge_name, port)
209215
if action == "filter":
210216
config = get_locking_config(domuuid, devid)
211-
locking_mode = config["locking_mode"]
212-
if locking_mode == "locked":
213-
create_vswitch_rules(bridge_name, port, config)
217+
create_vswitch_rules(bridge_name, port, config)
214218
ip_link_set(vif_name, "up")
215219

216220
###############################################################################

0 commit comments

Comments
 (0)