--- tools/examples/Makefile | 1 tools/examples/network-bridge | 11 + tools/examples/network-nat | 2 tools/examples/network-route | 40 ++++++ tools/examples/vif-acm-hook | 259 ++++++++++++++++++++++++++++++++++++++++++ tools/examples/vif-bridge | 2 tools/examples/vif-common.sh | 12 + tools/examples/vif-nat | 2 tools/examples/vif-route | 2 9 files changed, 325 insertions(+), 6 deletions(-) Index: xen-unstable.hg-shype/tools/examples/Makefile =================================================================== --- xen-unstable.hg-shype.orig/tools/examples/Makefile +++ xen-unstable.hg-shype/tools/examples/Makefile @@ -32,6 +32,7 @@ XEN_SCRIPTS += blktap XEN_SCRIPTS += vtpm vtpm-delete XEN_SCRIPTS += xen-hotplug-cleanup XEN_SCRIPTS += external-device-migrate +XEN_SCRIPTS += vif-acm-hook XEN_SCRIPT_DATA = xen-script-common.sh locking.sh logging.sh XEN_SCRIPT_DATA += xen-hotplug-common.sh xen-network-common.sh vif-common.sh XEN_SCRIPT_DATA += block-common.sh vtpm-common.sh vtpm-hotplug-common.sh Index: xen-unstable.hg-shype/tools/examples/network-bridge =================================================================== --- xen-unstable.hg-shype.orig/tools/examples/network-bridge +++ xen-unstable.hg-shype/tools/examples/network-bridge @@ -229,8 +229,13 @@ using loopback.nloopbacks= on the dom transfer_routes ${netdev} ${bridge} fi - if [ ${antispoof} = 'yes' ] ; then - antispoofing + if [ `/etc/xen/scripts/vif-acm-hook "acm_on?"` != "OFF" ] ; then + echo /etc/xen/scripts/vif-acm-hook "network-bridge-up" "$pdev" "${antispoof:-no}" + /etc/xen/scripts/vif-acm-hook "network-bridge-up" "$pdev" "${antispoof:-no}" + else + if [ ${antispoof} = 'yes' ] ; then + antispoofing + fi fi } @@ -267,6 +272,8 @@ op_stop () { ip link set ${bridge} down fi brctl delbr ${bridge} + + /etc/xen/scripts/vif-acm-hook "network-bridge-down" "$pdev" "${antispoof:-no}" } # adds $dev to $bridge but waits for $dev to be in running state first Index: xen-unstable.hg-shype/tools/examples/network-nat =================================================================== --- xen-unstable.hg-shype.orig/tools/examples/network-nat +++ xen-unstable.hg-shype/tools/examples/network-nat @@ -71,12 +71,14 @@ op_start() { echo 1 >/proc/sys/net/ipv4/ip_forward iptables -t nat -A POSTROUTING -o ${netdev} -j MASQUERADE [ "$dhcp" != 'no' ] && dhcp_start + /etc/xen/scripts/vif-acm-hook "network-nat-up" "$netdev" "${antispoof:-no}" } op_stop() { [ "$dhcp" != 'no' ] && dhcp_stop iptables -t nat -D POSTROUTING -o ${netdev} -j MASQUERADE + /etc/xen/scripts/vif-acm-hook "network-nat-down" "$netdev" "${antispoof:-no}" } Index: xen-unstable.hg-shype/tools/examples/network-route =================================================================== --- xen-unstable.hg-shype.orig/tools/examples/network-route +++ xen-unstable.hg-shype/tools/examples/network-route @@ -16,4 +16,42 @@ # #============================================================================ -echo 1 >/proc/sys/net/ipv4/ip_forward + +dir=$(dirname "$0") +. "$dir/xen-script-common.sh" +. "$dir/xen-network-common.sh" + +findCommand "$@" +evalVariables "$@" + +show_status() { + echo '============================================================' + ifconfig + echo ' ' + ip route list + echo ' ' + route -n + echo '============================================================' + +} + +case "$command" in + start) + echo 1 >/proc/sys/net/ipv4/ip_forward + /etc/xen/scripts/vif-acm-hook "network-route-up" "${netdev:-eth0}" "${antispoof:-yes}" + ;; + + stop) + echo 0 >/proc/sys/net/ipv4/ip_forward + /etc/xen/scripts/vif-acm-hook "network-route-down" "${netdev:-eth0}" "${antispoof:-yes}" + ;; + + status) + show_status + ;; + + *) + echo "Unknown command: $command" >&2 + echo 'Valid commands are: start, stop, status' >&2 + exit 1 +esac Index: xen-unstable.hg-shype/tools/examples/vif-acm-hook =================================================================== --- /dev/null +++ xen-unstable.hg-shype/tools/examples/vif-acm-hook @@ -0,0 +1,259 @@ +#!/usr/bin/env python +# -*- mode: python; -*- +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2006 International Business Machines Corp. +# Author: Reiner Sailer +#============================================================================ +# Arguments: +# +# +# 1 arg [1]commands - "acm_on?" +# +# 3 arg [1]commands - "network-nat-up"/"network-nat-down" +# "network-bridge-up"/"network-brigde-down" +# "network-route-up"/"network-route-down" +# [2]netdev - usually "pethX" or "ethX" +# [3]antispoof - "yes/no" +# +# 4-5 arg +# [1]commands - "online/offline" , +# [2]vif - "usually "ethX" or "vif0.X" +# [3]antispoof - "yes/no" ('yes' not supported yet everywhere!) +# [4]type - "nat/bridge/route", +# [5]ip adrs - list of static ip addresses (required for antispoof) +## + +"""Set IP filters betwen virtual interfaces if ACM security is ON +""" +import sys, commands, string +sys.path.insert(-1, '/usr/lib/python') +sys.path.insert(-1, '/usr/lib64/python') +from xen.util import security + + +def do_command(c, ignore_error): + print c + (ret, output) = commands.getstatusoutput(c) + if ret and not ignore_error: + sys.exit(-1) + return output + + +def vif2domid(vif): + tmp = string.split(vif, ".")[0] + return int(tmp[len("vif"):]) + + +def getOnlineVifs(): + # create list of existing user domain vifX.Y + viflist = [] + listcommand = "/sbin/ifconfig | /bin/grep \"Link encap\" | /bin/grep \"vif\"" + output = do_command(listcommand, "Reading vif interfaces.") + if output == '': + return [] + for line in string.split(output, "\n"): + upvif = string.split(line, " ")[0] + viflist.append(upvif) + return viflist + + +## +# +# BRIDGING ACM IPTABLES SUPPORT +# +# antispoof: antispoof=yes -> DomU interfaces without pre-set IP cannot send/start +# + +#default to DROP, allow in/out from/to peth (network) +# -- Later REDIRECT external traffic to create secure labeled tunnel +def network_bridge_up(netdev, antispoof): + print "netdev=%s, antispoof=%s" % (netdev, antispoof) + vifDom0="vif0." + netdev[4:] + #FORWARD becomes the MAC enforcement for domU traffic + do_command("/sbin/iptables -P FORWARD DROP", False) + do_command("/sbin/iptables -A FORWARD -m physdev --physdev-in %s -j ACCEPT" % netdev, False) + do_command("/sbin/iptables -A FORWARD -m physdev --physdev-out %s -j ACCEPT" % netdev, False) + + #INPUT implements antispoof + if (antispoof != "no"): + do_command("/sbin/iptables -P INPUT DROP", False) + do_command("/sbin/iptables -A INPUT -m physdev --physdev-in %s -j ACCEPT" % netdev, False) + do_command("/sbin/iptables -A INPUT -m physdev --physdev-in %s -j ACCEPT" % vifDom0, False) + return + + +def network_bridge_down(netdev, antispoof): + vifDom0="vif0." + netdev[4:] + # leave drop policy in case there are other bridges + do_command("/sbin/iptables -D FORWARD -m physdev --physdev-in %s -j ACCEPT" % netdev, True) + do_command("/sbin/iptables -D FORWARD -m physdev --physdev-out %s -j ACCEPT" % netdev, True) + + if (antispoof != "no"): + do_command("/sbin/iptables -D INPUT -m physdev --physdev-in %s -j ACCEPT" % netdev, True) + do_command("/sbin/iptables -D INPUT -m physdev --physdev-in %s -j ACCEPT" % vifDom0, True) + return + + +#### +# +# NAT IPTABLES SUPPORT +# +def network_nat_up(netdev, antispoof): + if antispoof == 'yes': #not supported + sys.exit(-1) + do_command("/sbin/iptables -P FORWARD DROP", False) + do_command("/sbin/iptables -A FORWARD -i %s -j ACCEPT" % netdev, False) + do_command("/sbin/iptables -A FORWARD -o %s -j ACCEPT" % netdev, False) + return + + +def network_nat_down(netdev, antispoof): + if antispoof == 'yes': #not supported + sys.exit(-1) + do_command("/sbin/iptables -D FORWARD -i %s -j ACCEPT" % netdev, True) + do_command("/sbin/iptables -D FORWARD -o %s -j ACCEPT" % netdev, True) + return + + +#### +# +# ROUTING IPTABLES SUPPORT +# +def network_route_up(netdev, antispoof): + do_command("/sbin/iptables -P FORWARD DROP", False) + do_command("/sbin/iptables -A FORWARD -i %s -j ACCEPT" % netdev, False) + do_command("/sbin/iptables -A FORWARD -o %s -j ACCEPT" % netdev, False) + + if (antispoof != "no"): + do_command("/sbin/iptables -P INPUT DROP", False) + do_command("/sbin/iptables -A INPUT -i %s -j ACCEPT" % netdev, False) + return + +def network_route_down(netdev, antispoof): + do_command("/sbin/iptables -D FORWARD -i %s -j ACCEPT" % netdev, True) + do_command("/sbin/iptables -D FORWARD -o %s -j ACCEPT" % netdev, True) + + if (antispoof != "no"): + do_command("/sbin/iptables -D INPUT -i %s -j ACCEPT" % netdev, True) + return + +## +# maintain_mac_filters +# +# Sets/unsets 'filter' between all existing vifs and 'newviw' +# depending on the hypervisor policy (security.get_decision) +# +def maintain_filters(mac_filter, as_filter, action, newvif, antispoof, ips, viflist): + if (action == "online"): + (cmd, ignore_error) = ("-A", False) + else: + (cmd, ignore_error) = ("-D", True) + + print viflist + + for vif in viflist: + if (vif == newvif): + continue + newvifid = vif2domid(newvif) + vifid = vif2domid(vif) + if (action == "online"): + # only allow traffic to other vif interfaces if Xen/ACM permits this + if (security.get_decision(['domid', vifid], ['domid', newvifid]) == "PERMITTED"): + do_command(mac_filter % (cmd, newvif, vif), ignore_error) + do_command(mac_filter % (cmd, vif, newvif), ignore_error) + else: + # offline --> domains gone -> no decisions possible, just delete all possibly set related filters + do_command(mac_filter % (cmd, newvif, vif), ignore_error) + do_command(mac_filter % (cmd, vif, newvif), ignore_error) + + #support antispoof only with static ip (s) + if (antispoof != "no"): + for ip in ips: + do_command(as_filter % (cmd, ip, newvif), ignore_error) + return + + +def vifupdown(argv): + (command, newvif, antispoof, fwtype) = (argv[1], argv[2], argv[3], argv[4]) + if len(argv) > 5: + ips = string.split(argv[5], " ") + else: + ips = [] + + if (fwtype == "bridge"): + mac_filter = "/sbin/iptables %s FORWARD -m physdev --physdev-in %s --physdev-out %s -j ACCEPT" + as_filter = "/sbin/iptables %s INPUT --source %s -m physdev --physdev-in %s -j ACCEPT" + + elif (fwtype == "nat"): + mac_filter = "/sbin/iptables %s FORWARD -i %s -o %s -j ACCEPT" + as_filter = "" + + elif (fwtype == "route"): + mac_filter = "/sbin/iptables %s FORWARD -i %s -o %s -j ACCEPT" + as_filter = "/sbin/iptables %s INPUT --source %s -i %s -j ACCEPT" + + else: + sys.exit(-1) + + maintain_filters(mac_filter, as_filter, command, newvif, antispoof, ips, getOnlineVifs()) + return + + +def main (argv): + if len(argv) < 2: + sys.exit(-1) + + if argv[1] == 'acm_on?': + if security.on(): + print 'ON' + else: + print 'OFF' + return + + if not security.on(): + # nothing to do + return + + if len(argv) < 4: + sys.exit(-1) + # following hooks are activated once when the network is setup/shutdown + if argv[1] == "network-bridge-up": + network_bridge_up(argv[2], argv[3]) + elif argv[1] == "network-bridge-down": + network_bridge_down(argv[2], argv[3]) + elif argv[1] == "network-route-up": + network_route_up(argv[2], argv[3]) + elif argv[1] == "network-route-down": + network_route_down(argv[2], argv[3]) + elif argv[1] == "network-nat-up": + network_nat_up(argv[2], argv[3]) + elif argv[1] == "network-nat-down": + network_nat_down(argv[2], argv[3]) + + # following hooks are activated whenever an interface goes online/offline + elif argv[1] in ["online", "offline"]: + if (len(argv) < 5) or (argv[4] not in ['nat', 'bridge', 'route']) or \ + (argv[3] not in ['yes', 'no']): + sys.exit(-1) + vifupdown(argv) + else: + #illegal command + sys.exit(-1) + return + + +if __name__ == '__main__': + main(sys.argv) Index: xen-unstable.hg-shype/tools/examples/vif-bridge =================================================================== --- xen-unstable.hg-shype.orig/tools/examples/vif-bridge +++ xen-unstable.hg-shype/tools/examples/vif-bridge @@ -58,7 +58,7 @@ case "$command" in ;; esac -handle_iptable +generic_handle_iptable "bridge" log debug "Successful vif-bridge $command for $vif, bridge $bridge." if [ "$command" == "online" ] Index: xen-unstable.hg-shype/tools/examples/vif-common.sh =================================================================== --- xen-unstable.hg-shype.orig/tools/examples/vif-common.sh +++ xen-unstable.hg-shype/tools/examples/vif-common.sh @@ -116,6 +116,18 @@ function handle_iptable() fi } +function generic_handle_iptable() +{ + if [ $1 == "route" ] ; then + antispoof=${antispoof:-yes} + fi + + if [ `/etc/xen/scripts/vif-acm-hook "acm_on?"` != "OFF" ] ; then + /etc/xen/scripts/vif-acm-hook "$command" "$vif" "${antispoof:-no}" "${1:-illegal}" "$ip" + else + handle_iptable + fi +} ## # ip_of interface Index: xen-unstable.hg-shype/tools/examples/vif-nat =================================================================== --- xen-unstable.hg-shype.orig/tools/examples/vif-nat +++ xen-unstable.hg-shype/tools/examples/vif-nat @@ -149,7 +149,7 @@ case "$command" in esac -handle_iptable +generic_handle_iptable "nat" log debug "Successful vif-nat $command for $vif." if [ "$command" == "online" ] Index: xen-unstable.hg-shype/tools/examples/vif-route =================================================================== --- xen-unstable.hg-shype.orig/tools/examples/vif-route +++ xen-unstable.hg-shype/tools/examples/vif-route @@ -47,7 +47,7 @@ if [ "${ip}" ] ; then done fi -handle_iptable +generic_handle_iptable "route" log debug "Successful vif-route $command for $vif." if [ "$command" == "online" ]