From ab0cba603d96e25ee151222bb5fcf550459cfc7a Mon Sep 17 00:00:00 2001 From: Cory Wright Date: Mon, 20 Dec 2010 17:24:08 -0500 Subject: Rewrite of vif_rules.py to meet coding standards and be more pythonic in general. Use absolute paths for iptables/ebtables/arptables in host-rules. --- plugins/xenserver/networking/etc/init.d/host-rules | 54 ++++--- .../etc/xensource/scripts/vif_5.6-fp1.patch | 4 +- .../networking/etc/xensource/scripts/vif_rules.py | 180 +++++++++++++-------- 3 files changed, 146 insertions(+), 92 deletions(-) (limited to 'plugins/xenserver/networking') diff --git a/plugins/xenserver/networking/etc/init.d/host-rules b/plugins/xenserver/networking/etc/init.d/host-rules index 980396bae4..385c596290 100755 --- a/plugins/xenserver/networking/etc/init.d/host-rules +++ b/plugins/xenserver/networking/etc/init.d/host-rules @@ -5,50 +5,54 @@ # chkconfig: 2345 85 15 # description: Networking Host Rules for Multi Tenancy Protections +IPTABLES=/sbin/iptables +EBTABLES=/sbin/ebtables +ARPTABLES=/sbin/arptables + iptables-up() { - iptables -P FORWARD DROP - iptables -A FORWARD -m physdev --physdev-in eth0 -j ACCEPT - iptables -A FORWARD -m physdev --physdev-in eth1 -j ACCEPT + $IPTABLES -P FORWARD DROP + $IPTABLES -A FORWARD -m physdev --physdev-in eth0 -j ACCEPT + $IPTABLES -A FORWARD -m physdev --physdev-in eth1 -j ACCEPT } ebtables-up() { - ebtables -P FORWARD DROP - ebtables -A FORWARD -o eth0 -j ACCEPT - ebtables -A FORWARD -o eth1 -j ACCEPT + $EBTABLES -P FORWARD DROP + $EBTABLES -A FORWARD -o eth0 -j ACCEPT + $EBTABLES -A FORWARD -o eth1 -j ACCEPT } arptables-up() { - arptables -P FORWARD DROP - arptables -A FORWARD --opcode Request --in-interface eth0 -j ACCEPT - arptables -A FORWARD --opcode Reply --in-interface eth0 -j ACCEPT - arptables -A FORWARD --opcode Request --in-interface eth1 -j ACCEPT - arptables -A FORWARD --opcode Reply --in-interface eth1 -j ACCEPT + $ARPTABLES -P FORWARD DROP + $ARPTABLES -A FORWARD --opcode Request --in-interface eth0 -j ACCEPT + $ARPTABLES -A FORWARD --opcode Reply --in-interface eth0 -j ACCEPT + $ARPTABLES -A FORWARD --opcode Request --in-interface eth1 -j ACCEPT + $ARPTABLES -A FORWARD --opcode Reply --in-interface eth1 -j ACCEPT } iptables-down() { - iptables -P FORWARD ACCEPT - iptables -D FORWARD -m physdev --physdev-in eth0 -j ACCEPT - iptables -D FORWARD -m physdev --physdev-in eth1 -j ACCEPT + $IPTABLES -P FORWARD ACCEPT + $IPTABLES -D FORWARD -m physdev --physdev-in eth0 -j ACCEPT + $IPTABLES -D FORWARD -m physdev --physdev-in eth1 -j ACCEPT } ebtables-down() { - ebtables -P FORWARD ACCEPT - ebtables -D FORWARD -o eth0 -j ACCEPT - ebtables -D FORWARD -o eth1 -j ACCEPT + $EBTABLES -P FORWARD ACCEPT + $EBTABLES -D FORWARD -o eth0 -j ACCEPT + $EBTABLES -D FORWARD -o eth1 -j ACCEPT } arptables-down() { - arptables -P FORWARD ACCEPT - arptables -D FORWARD --opcode Request --in-interface eth0 -j ACCEPT - arptables -D FORWARD --opcode Reply --in-interface eth0 -j ACCEPT - arptables -D FORWARD --opcode Request --in-interface eth1 -j ACCEPT - arptables -D FORWARD --opcode Reply --in-interface eth1 -j ACCEPT + $ARPTABLES -P FORWARD ACCEPT + $ARPTABLES -D FORWARD --opcode Request --in-interface eth0 -j ACCEPT + $ARPTABLES -D FORWARD --opcode Reply --in-interface eth0 -j ACCEPT + $ARPTABLES -D FORWARD --opcode Request --in-interface eth1 -j ACCEPT + $ARPTABLES -D FORWARD --opcode Reply --in-interface eth1 -j ACCEPT } start() @@ -68,16 +72,20 @@ stop() case "$1" in start) start + RETVAL=$? ;; stop) stop + RETVAL=$? ;; restart) stop start + RETVAL=$? ;; *) echo $"Usage: $0 {start|stop|restart}" exit 1 + ;; esac -exit 0 +exit $RETVAL diff --git a/plugins/xenserver/networking/etc/xensource/scripts/vif_5.6-fp1.patch b/plugins/xenserver/networking/etc/xensource/scripts/vif_5.6-fp1.patch index 142096ff1d..feaf1312dd 100644 --- a/plugins/xenserver/networking/etc/xensource/scripts/vif_5.6-fp1.patch +++ b/plugins/xenserver/networking/etc/xensource/scripts/vif_5.6-fp1.patch @@ -4,7 +4,7 @@ # xs-xen.pq.hq:91e986b8e49f netback-wait-for-hotplug xenstore-write "/local/domain/0/backend/vif/${DOMID}/${DEVID}/hotplug-status" "connected" -+ python /etc/xensource/scripts/vif_rules.py ${DOMID} online 2>&1 >> /dev/null ++ python /etc/xensource/scripts/vif_rules.py ${DOMID} online 2>&1 > /dev/null fi ;; @@ -12,7 +12,7 @@ remove) if [ "${TYPE}" = "vif" ] ;then -+ python /etc/xensource/scripts/vif_rules.py ${DOMID} offline 2>&1 >> /dev/null ++ python /etc/xensource/scripts/vif_rules.py ${DOMID} offline 2>&1 > /dev/null xenstore-rm "${HOTPLUG}/hotplug" fi logger -t scripts-vif "${dev} has been removed" diff --git a/plugins/xenserver/networking/etc/xensource/scripts/vif_rules.py b/plugins/xenserver/networking/etc/xensource/scripts/vif_rules.py index 05141630b3..dd27d3c6b7 100755 --- a/plugins/xenserver/networking/etc/xensource/scripts/vif_rules.py +++ b/plugins/xenserver/networking/etc/xensource/scripts/vif_rules.py @@ -1,72 +1,118 @@ #!/usr/bin/env python -from os import system, popen4 +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 OpenStack LLC. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" +This script is used to configure iptables, ebtables, and arptables rules for +XenServer instances. +""" + +import os +import subprocess import sys + +# This is written to Python 2.4, since that is what is available on XenServer import simplejson as json -from itertools import chain - -# order is important, mmmkay? 1 is domid, 2 command, 3 is vif -# when we add rules, we delete first, to make sure we only keep the one rule we need - -def main(): - fin,fout = popen4("/usr/bin/xenstore-ls /local/domain/%s/vm-data/networking" % sys.argv[1] ) - macs = fout.read().split("\n")[0:-1] - - for mac in macs: - m = mac.split("=")[0].strip() - fin,fout = popen4("/usr/bin/xenstore-read /local/domain/%s/vm-data/networking/%s" % (sys.argv[1],m)) - mjson = json.loads(fout.read()) - for ip in mjson['ips']: - if mjson["label"] == "public": - label = 0 - else: - label = 1 - - VIF = "vif%s.%s" % (sys.argv[1],label) - - if (len(sys.argv) == 4 and sys.argv[3] == VIF) or (len(sys.argv) == 3): - run_rules( - IP = ip['ip'], - VIF = VIF, - MAC = mjson['mac'], - STATUS = (sys.argv[2] == 'online') and '-A' or '-D' - ) - -def run_rules(**kwargs): - map(system, chain(ebtables(**kwargs), arptables(**kwargs), iptables(**kwargs) )) - -def iptables(**kwargs): - return [ - "/sbin/iptables -D FORWARD -m physdev --physdev-in %s -s %s -j ACCEPT 2>&1 > /dev/null" % ( kwargs['VIF'], kwargs['IP']), - "/sbin/iptables %s FORWARD -m physdev --physdev-in %s -s %s -j ACCEPT" % (kwargs['STATUS'], kwargs['VIF'], kwargs['IP']) - ] - -def arptables(**kwargs): - return [ - "/sbin/arptables -D FORWARD --opcode Request --in-interface %s --source-ip %s --source-mac %s -j ACCEPT 2>&1 > /dev/null" % (kwargs['VIF'], kwargs['IP'], kwargs['MAC']), - "/sbin/arptables -D FORWARD --opcode Reply --in-interface %s --source-ip %s --source-mac %s -j ACCEPT 2>&1 > /dev/null" % (kwargs['VIF'], kwargs['IP'], kwargs['MAC']), - "/sbin/arptables %s FORWARD --opcode Request --in-interface %s --source-ip %s --source-mac %s -j ACCEPT" % (kwargs['STATUS'], kwargs['VIF'], kwargs['IP'], kwargs['MAC']), - "/sbin/arptables %s FORWARD --opcode Reply --in-interface %s --source-ip %s --source-mac %s -j ACCEPT" % (kwargs['STATUS'], kwargs['VIF'], kwargs['IP'], kwargs['MAC']) - ] - -def ebtables(**kwargs): - cmds = [ - "/sbin/ebtables -D FORWARD -p 0806 -o %s --arp-ip-dst %s -j ACCEPT 2>&1 >> /dev/null" % (kwargs['VIF'], kwargs['IP']), - "/sbin/ebtables -D FORWARD -p 0800 -o %s --ip-dst %s -j ACCEPT 2>&1 >> /dev/null" % (kwargs['VIF'], kwargs['IP']), - "/sbin/ebtables %s FORWARD -p 0806 -o %s --arp-ip-dst %s -j ACCEPT 2>&1 " % (kwargs['STATUS'], kwargs['VIF'], kwargs['IP']), - "/sbin/ebtables %s FORWARD -p 0800 -o %s --ip-dst %s -j ACCEPT 2>&1 " % (kwargs['STATUS'], kwargs['VIF'], kwargs['IP']) - ] - if kwargs['STATUS'] == "-A": - cmds.append("/sbin/ebtables -D FORWARD -s ! %s -i %s -j DROP 2>&1 > /dev/null" % (kwargs['MAC'], kwargs['VIF'])) - cmds.append("/sbin/ebtables -I FORWARD 1 -s ! %s -i %s -j DROP" % (kwargs['MAC'], kwargs['VIF'])) - else: - cmds.append("/sbin/ebtables %s FORWARD -s ! %s -i %s -j DROP" % (kwargs['STATUS'], kwargs['MAC'], kwargs['VIF'])) - return cmds - -def usage(): - print "Usage: slice_vifs.py optional: " + + +def main(dom_id, command, only_this_vif=None): + xsls = execute("/usr/bin/xenstore-ls /local/domain/%s/vm-data/networking" \ + % dom_id, True) + macs = [line.split("=")[0].strip() for line in xsls.splitlines()] + + for mac in macs: + xsr = "/usr/bin/xenstore-read /local/domain/%s/vm-data/networking/%s" + xsread = execute(xsr % (dom_id, mac), True) + data = json.loads(xsread) + for ip in data['ips']: + if data["label"] == "public": + vif = "vif%s.0" % dom_id + else: + vif = "vif%s.1" % dom_id + + if (only_this_vif is None) or (vif == only_this_vif): + params = dict(IP=ip['ip'], VIF=vif, MAC=data['mac']) + apply_ebtables_rules(command, params) + apply_arptables_rules(command, params) + apply_iptables_rules(command, params) + + +def execute(command, return_stdout=False): + devnull = open(os.devnull, 'w') + proc = subprocess.Popen(command, shell=True, close_fds=True, + stdout=subprocess.PIPE, stderr=devnull) + if return_stdout: + return proc.stdout.read() + else: + return None + +# A note about adding rules: +# Whenever we add any rule to iptables, arptables or ebtables we first +# delete the same rule to ensure the rule only exists once. + + +def apply_iptables_rules(command, params): + iptables = lambda rule: execute("/sbin/iptables %s" % rule) + + iptables("-D FORWARD -m physdev --physdev-in %(VIF)s -s %(IP)s \ + -j ACCEPT" % params) + if command == 'online': + iptables("-A FORWARD -m physdev --physdev-in %(VIF)s -s %(IP)s \ + -j ACCEPT" % params) + + +def apply_arptables_rules(command, params): + arptables = lambda rule: execute("/sbin/arptables %s" % rule) + + arptables("-D FORWARD --opcode Request --in-interface %(VIF)s \ + --source-ip %(IP)s --source-mac %(MAC)s -j ACCEPT" % params) + arptables("-D FORWARD --opcode Reply --in-interface %(VIF)s \ + --source-ip %(IP)s --source-mac %(MAC)s -j ACCEPT" % params) + if command == 'online': + arptables("-A FORWARD --opcode Request --in-interface %(VIF)s \ + --source-ip %(IP)s --source-mac %(MAC)s -j ACCEPT" % params) + arptables("-A FORWARD --opcode Reply --in-interface %(VIF)s \ + --source-ip %(IP)s --source-mac %(MAC)s -j ACCEPT" % params) + + +def apply_ebtables_rules(command, params): + ebtables = lambda rule: execute("/sbin/ebtables %s" % rule) + + ebtables("-D FORWARD -p 0806 -o %(VIF)s --arp-ip-dst %(IP)s -j ACCEPT" % + params) + ebtables("-D FORWARD -p 0800 -o %(VIF)s --ip-dst %(IP)s -j ACCEPT" % + params) + if command == 'online': + ebtables("-A FORWARD -p 0806 -o %(VIF)s --arp-ip-dst %(IP)s \ + -j ACCEPT" % params) + ebtables("-A FORWARD -p 0800 -o %(VIF)s --ip-dst %(IP)s \ + -j ACCEPT" % params) + + ebtables("-D FORWARD -s ! %(MAC)s -i %(VIF)s -j DROP" % params) + if command == 'online': + ebtables("-I FORWARD 1 -s ! %(MAC)s -i %(VIF)s -j DROP" % params) + if __name__ == "__main__": - if len(sys.argv) < 3: - usage() - else: - main() + if len(sys.argv) < 3: + print "usage: %s dom_id online|offline [vif]" % \ + os.path.basename(sys.argv[0]) + sys.exit(1) + else: + dom_id, command = sys.argv[1:3] + vif = len(sys.argv) == 4 and sys.argv[3] or None + main(dom_id, command, vif) -- cgit v1.2.1