[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xense-devel] [RFC][PATCH][ACM] enforcing ACM policy on network traffic between virtual network interfaces
This patch adds an ACM hook into the network scripts (/etc/xen/scripts). It adds iptables rules that enforce mandatory access control on network packets exchanged between virtual interfaces. If ACM is active, this patch sets the default FORWARD policy in Dom0 to DROP and adds iptables ACCEPT rules between vifs that belong to domains that are permitted to share (determined by using the get_decision ACM hypervisor call). If ACM is not active, this patch is transparent to the operation of networking in Xen. This topic was discussed here <http://lists.xensource.com/archives/html/xen-devel/2006-07/msg01005.html> as were the implications. For example, the recent suggestion to move packets directly between physical and virtual interfaces to avoid running through the bridge <http://lists.xensource.com/archives/html/xen-devel/2006-08/msg01583.html>, would, if implemented, bypass this access control unless those new mechanisms call the netfilter hooks that are called by the bridge. Attached are examples for iptables rulesets in bridging, routing, nat-ing network setups. Also attached the patch. Please note that many iptables rules shown below could be collapsed if we assumed that all domains are permitted to talk to Domain0, i.e., all vifX.Y can communicate to vif0.Y. In this case, we can just add two rules saying in/out traffic through vif0.Y is always ACCEPTed. This patch does currently not leverage this simplification because we anticipate that Domain0 will become less powerful than it is today. Comments welcome. Thanks ReinerThe following show examples of routes related to running domains. The policy is setup so that domains 1,4, and 5 are permitted to communicate among each other and all domains can communicate with Domain0. ACM enforcement-related iptables rules are moved into the FORWARD chain; any antispoof rules go into the INPUT chain. Example with 1 bridge and 5 domains: ========================== [root@941e-4 ~]# ip Chain FORWARD (policy DROP 13 packets, 4302 bytes)pkts bytes target prot opt in out source destination 5329 445K ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-in peth0 1593 272K ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-out peth0 2 1152 ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-in vif1.0 --physdev-out vif0.0 178 18153 ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-in vif0.0 --physdev-out vif1.0 2 1152 ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-in vif2.0 --physdev-out vif0.0 142 15519 ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-in vif0.0 --physdev-out vif2.0 2 1152 ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-in vif3.0 --physdev-out vif0.0 98 12646 ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-in vif0.0 --physdev-out vif3.0 0 0 ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-in vif4.0 --physdev-out vif0.0 0 0 ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-in vif0.0 --physdev-out vif4.0 0 0 ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-in vif4.0 --physdev-out vif1.0 0 0 ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-in vif1.0 --physdev-out vif4.0 0 0 ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-in vif5.0 --physdev-out vif0.0 0 0 ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-in vif0.0 --physdev-out vif5.0 0 0 ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-in vif5.0 --physdev-out vif1.0 0 0 ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-in vif1.0 --physdev-out vif5.0 0 0 ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-in vif5.0 --physdev-out vif4.0 0 0 ACCEPT all -- any any anywhere anywhere PHYSDEV match --physdev-in vif4.0 --physdev-out vif5.0 Chain INPUT (policy ACCEPT 3343 packets, 312K bytes)pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 1595 packets, 269K bytes)pkts bytes target prot opt in out source destination [root@941e-4 ~]# xm list --label Name ID Mem(MiB) VCPUs State Time(s) Label domain1 1 164 1 -b---- 6.5 Avis domain4 4 164 1 -b---- 6.6 Avis domain5 5 164 1 -b---- 6.5 Avis domain3 3 164 1 -b---- 6.6 CocaCola domain2 2 164 1 -b---- 6.4 HertzDomain-0 0 1948 4 r----- 218.4 SystemManagement Example for Nat: ============ [root@941e-4 ~]# iptables -L -v Chain FORWARD (policy DROP 0 packets, 0 bytes)pkts bytes target prot opt in out source destination 0 0 ACCEPT all -- eth0 any anywhere anywhere 0 0 ACCEPT all -- any eth0 anywhere anywhere 0 0 ACCEPT all -- vif4.0 vif1.0 anywhere anywhere 0 0 ACCEPT all -- vif1.0 vif4.0 anywhere anywhere 0 0 ACCEPT all -- vif5.0 vif1.0 anywhere anywhere 0 0 ACCEPT all -- vif1.0 vif5.0 anywhere anywhere 0 0 ACCEPT all -- vif5.0 vif4.0 anywhere anywhere 0 0 ACCEPT all -- vif4.0 vif5.0 anywhere anywhere Chain INPUT (policy ACCEPT 37165 packets, 4945K bytes)pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 11709 packets, 7277K bytes)pkts bytes target prot opt in out source destination [root@941e-4 ~]# xm list --label Name ID Mem(MiB) VCPUs State Time(s) Label domain1 1 164 1 -b---- 0.3 Avis domain4 4 164 1 -b---- 0.3 Avis domain5 5 164 1 -b---- 0.3 Avis domain3 3 164 1 -b---- 0.3 CocaCola domain2 2 164 1 -b---- 0.3 HertzDomain-0 0 1948 4 r----- 319.9 SystemManagement Example for Route (w/antispoof) ======================= [root@941e-4 route]# ip Chain FORWARD (policy DROP 0 packets, 0 bytes)pkts bytes target prot opt in out source destination 0 0 ACCEPT all -- eth0 any anywhere anywhere 0 0 ACCEPT all -- any eth0 anywhere anywhere 0 0 ACCEPT all -- vif2.0 vif1.0 anywhere anywhere 0 0 ACCEPT all -- vif1.0 vif2.0 anywhere anywhere Chain INPUT (policy DROP 48 packets, 2880 bytes)pkts bytes target prot opt in out source destination 17099 2070K ACCEPT all -- eth0 * 0.0.0.0/0 0.0.0.0/0 0 0 ACCEPT all -- vif1.0 * 9.2.15.138 0.0.0.0/0 0 0 ACCEPT all -- vif2.0 * 9.2.15.142 0.0.0.0/0 0 0 ACCEPT all -- vif3.0 * 9.2.15.139 0.0.0.0/0 Chain OUTPUT (policy ACCEPT 6792 packets, 3717K bytes)pkts bytes target prot opt in out source destination [root@941e-4 route]# xm list --label Name ID Mem(MiB) VCPUs State Time(s) Label domain1 1 164 1 -b---- 6.3 Avis domain4 2 164 1 -b---- 0.3 Avis domain2 3 164 1 -b---- 0.3 HertzDomain-0 0 1948 4 r----- 236.2 SystemManagement Signed-off by: Reiner Sailer <sailer@xxxxxxxxxx> --- 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=<N> 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 <sailer@xxxxxxxxxx> +#============================================================================ +# 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" ] _______________________________________________ Xense-devel mailing list Xense-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xense-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |