[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 4/5] hotplug/linux: Add IPv6 support to the iptables logic



This adds the same functions for ip6tables as the one for iptables.
The 'ip' variable can now contain ipv6s for the domain and add
appropriate rules

 - If the 'ip' var is empty then both full IPv4 and IPv6 are allowed.
 - If only IPv4 ips are present, then IPv6 will be completely disallowed.
 - If only IPv6 ips are present, then IPv4 will be completely disallowed.
 - You can use ::0/0 or 0.0.0.0/0 to allow v6 or v4 globally but filter
   the other one.

 (see below for examples of rules generated after this patch)

This gracefully handles if the dom0 doesn't have IPv6. If
the call to ip6tables doesn't succeed, it just ignores any
IPv6 stuff.

Examples of rules added :

 * ip=""

 iptables:

  ACCEPT  all  0.0.0.0/0  0.0.0.0/0  PHYSDEV match --physdev-in
   vif91.0 --physdev-is-bridged
  ACCEPT  all  0.0.0.0/0  0.0.0.0/0  PHYSDEV match --physdev-out
   vif91.0 --physdev-is-bridged

 ip6tables:

  DROP    udp    ::/0  ::/0  PHYSDEV match --physdev-in  vif91.0
   --physdev-is-bridged udp spt:547 dpt:546
  DROP    icmpv6 ::/0  ::/0  PHYSDEV match --physdev-in  vif91.0
   --physdev-is-bridged ipv6-icmptype 134
  ACCEPT  all    ::/0  ::/0  PHYSDEV match --physdev-out vif91.0
   --physdev-is-bridged
  ACCEPT  all    ::/0  ::/0  PHYSDEV match --physdev-in  vif91.0
   --physdev-is-bridged

 * ip="192.168.0.254"

 iptables:

  ACCEPT  udp  0.0.0.0/0      0.0.0.0/0  PHYSDEV match --physdev-in
   vif92.0 --physdev-is-bridged udp spt:68 dpt:67
  ACCEPT  all  0.0.0.0/0      0.0.0.0/0  PHYSDEV match --physdev-out
   vif92.0 --physdev-is-bridged
  ACCEPT  all  192.168.0.254  0.0.0.0/0  PHYSDEV match --physdev-in
   vif92.0 --physdev-is-bridged

 ip6tables:

  [no rules added]

 * ip="2001:aaaa:bbbb:cccc::1 eui64"

 iptables:

  [no rules added]

 ip6tables:

  DROP    udp    ::/0                 ::/0
   PHYSDEV match --physdev-in  vif94.0 --physdev-is-bridged udp spt:547
 dpt:546
  DROP    icmpv6 ::/0                 ::/0
   PHYSDEV match --physdev-in  vif94.0 --physdev-is-bridged ipv6-icmptype
 134
  ACCEPT  udp    ::/0                 ::/0
   PHYSDEV match --physdev-in  vif94.0 --physdev-is-bridged udp spt:546
   dpt:547
  ACCEPT  all    fe80::216:3eff:fed0:da2d/128  ::/0
   PHYSDEV match --physdev-in  vif94.0 --physdev-is-bridged
  ACCEPT  all    ::/0                 ::/0
   PHYSDEV match --physdev-out vif94.0 --physdev-is-bridged
  ACCEPT  all    2001:aaaa:bbbb:cccc::1/128  ::/0
   PHYSDEV match --physdev-in  vif94.0 --physdev-is-bridged
  ACCEPT  all    ::216:3eff:fed0:da2d/::ffff:ffff:ffff:ffff  ::/0
   PHYSDEV match --physdev-in  vif94.0 --physdev-is-bridged

 * ip="192.168.0.254 2001:aaaa:bbbb:cccc::1" (either ipv4 or ipv6 can
 be replaced by the 0.0.0.0/0 or ::0/0 address to allow any, the
 dhcp/nd rules might be redudant then).

 iptables:

  ACCEPT  udp  0.0.0.0/0      0.0.0.0/0  PHYSDEV match --physdev-in
   vif95.0 --physdev-is-bridged udp spt:68 dpt:67
  ACCEPT  all  0.0.0.0/0      0.0.0.0/0  PHYSDEV match --physdev-out
   vif95.0 --physdev-is-bridged
  ACCEPT  all  192.168.0.254  0.0.0.0/0  PHYSDEV match --physdev-in
   vif95.0 --physdev-is-bridged

 ip6tables:

  DROP    udp    ::/0                 ::/0           PHYSDEV match
   --physdev-in  vif95.0 --physdev-is-bridged udp spt:547 dpt:546
  DROP    icmpv6 ::/0                 ::/0           PHYSDEV match
   --physdev-in  vif95.0 --physdev-is-bridged ipv6-icmptype 134
  ACCEPT  udp    ::/0                 ::/0           PHYSDEV match
   --physdev-in  vif95.0 --physdev-is-bridged udp spt:546 dpt:547
  ACCEPT  all    fe80::216:3eff:fed0:da2d/128  ::/0  PHYSDEV match
   --physdev-in  vif95.0 --physdev-is-bridged
  ACCEPT  all    ::/0                 ::/0           PHYSDEV match
   --physdev-out vif95.0 --physdev-is-bridged

Signed-off-by: Sylvain Munaut <s.munaut@xxxxxxxxxxxxxxxxxxxx>
---
 docs/man/xl-network-configuration.markdown.5 | 16 +++++
 tools/hotplug/Linux/vif-common.sh            | 89 ++++++++++++++++++++++++++++
 2 files changed, 105 insertions(+)

diff --git a/docs/man/xl-network-configuration.markdown.5 
b/docs/man/xl-network-configuration.markdown.5
index 3c439d4..5b86974 100644
--- a/docs/man/xl-network-configuration.markdown.5
+++ b/docs/man/xl-network-configuration.markdown.5
@@ -128,6 +128,21 @@ configured. A typically behaviour (exhibited by the 
example hotplug
 scripts) if set might be to configure firewall rules to allow only the
 specified IP address to be used by the guest (blocking all others).
 
+The linux hotplug script supports both IPv4 and IPv6 in this field. When
+the field is omitted or empty, both will be fully allowed. If only IPv4s
+are listed, then IPv6 will be blocked completely. Symmetrically, if only
+IPv6s are listed, then IPv4 will be blocked. If you wish to filter one
+but not the other, you can use the wildcard addresses 0.0.0.0/0 and
+::0/0 for IPv4/6 respectively.
+
+As a special case, you can use 'eui64' token as an IPv6 address and this
+will allow traffic all traffic from the VM where the lower 64 bits are
+matched against the [EUI64] generated from the mac address of the VIF. It
+is up to the network administrator to filter the network part of the
+address globally if necessary. This is of course only usable for the
+vif-bridge script as the vif-route will require a fully defined address
+in the 'ip' field.
+
 ### backend
 
 Specifies the backend domain which this device should attach to. This
@@ -166,3 +181,4 @@ on the underlying netback implementation.
 [oui]: http://en.wikipedia.org/wiki/Organizationally_Unique_Identifier
 [net]: http://wiki.xen.org/wiki/HostConfiguration/Networking
 [vifroute]: http://wiki.xen.org/wiki/Vif-route
+[EUI64]: http://en.wikipedia.org/wiki/IPv6_address#Modified_EUI-64
diff --git a/tools/hotplug/Linux/vif-common.sh 
b/tools/hotplug/Linux/vif-common.sh
index 3755f0a..b92c36c 100644
--- a/tools/hotplug/Linux/vif-common.sh
+++ b/tools/hotplug/Linux/vif-common.sh
@@ -121,6 +121,7 @@ ip=${ip:-}
 ip=$(xenstore_read_default "$XENBUS_PATH/ip" "$ip")
 
 chain_v4=FORWARD
+chain_v6=FORWARD
 
 frob_iptable()
 {
@@ -169,6 +170,71 @@ frob_iptable()
   fi
 }
 
+frob_ip6table()
+{
+  local has_err="no"
+  local has_any="no"
+  local mac=$(xenstore_read "$XENBUS_PATH/mac")
+  local eui64=$(echo $mac | awk '{split($1,i,":"); print xor(i[1],2) i[2] ":" 
i[3] "ff:fe" i[4] ":" i[5] i[6] }')
+      # Refer to http://en.wikipedia.org/wiki/IPv6_address#Modified_EUI-64
+
+  # Add or remove
+  if [ "$command" == "online" -o "$command" == "add" ]
+  then
+    local c="-I"
+  else
+    local c="-D"
+  fi
+
+  # Add rules for each address
+  local addr
+
+  for addr in $@; do
+    if [ "$addr" = "any" ]; then
+      addr="::0/0"
+      has_any="yes"
+    elif [ "$addr" = "eui64" ]; then
+      addr="::$eui64/::ffff:ffff:ffff:ffff"
+    fi
+
+    ip6tables "$c" "$chain_v6" -w $dev_in_match "$dev" \
+      -s "$addr" -j ACCEPT 2>/dev/null || has_err="yes"
+  done
+
+  # Always Allow all packets _to_ the domain
+  ip6tables "$c" "$chain_v6" -w $dev_out_match "$dev" \
+    -j ACCEPT 2>/dev/null || has_err="yes"
+
+  # If 'any' isn't allowed, we needs to allow a few more things
+  if [ "$has_any" != "yes" ]
+  then
+
+    # Always allow ICMP messages from link-local addresses (for ND)
+    ip6tables "$c" "$chain_v6" -w $dev_in_match "$dev" \
+      -s "fe80::$eui64" -j ACCEPT 2>/dev/null || has_err="yes"
+
+    # Always allow the domain to talk to a DHCP server
+    ip6tables "$c" "$chain_v6" -w $dev_in_match "$dev" \
+      -p udp --sport 546 --dport 547 -j ACCEPT 2>/dev/null || has_err="yes"
+
+  fi
+
+  # Error handling
+  if [ \( "$command" == "online" -o "$command" == "add" \) -a "$has_err" == 
"yes" ]
+  then
+    log err "ip6tables setup failed. This may affect guest networking."
+  fi
+}
+
+
+##
+# Check if the given IP is IPv6 or not
+#
+is_ipv6()
+{
+  echo "$1" | awk '/:|eui64/ { print "yes" }'
+}
+
 
 ##
 # Add or remove the appropriate entries in the iptables.  With antispoofing
@@ -198,19 +264,34 @@ handle_iptable()
     return
   fi
 
+  # User has a working IPv4 iptables, but maybe no IPv6 support ...
+  local do_ipv6="yes"
+
+  if ! ip6tables -L -w -n >&/dev/null
+  then
+    do_ipv6="no"
+  fi
+
   # Scan through the addresses
   local ipv4_addrs
+  local ipv6_addrs
 
   if [ "$ip" != "" ]
   then
     local addr
     for addr in $ip
     do
+      result=$(is_ipv6 "$addr")
+      if [ -z "$result" ] ; then
         ipv4_addrs="$addr $ipv4_addrs"
+      else
+        ipv6_addrs="$addr $ipv6_addrs"
+      fi
     done
   else
     # No IP addresses have been specified, so allow anything.
     ipv4_addrs="any"
+    ipv6_addrs="any"
   fi
 
   # Actually add the rules
@@ -221,6 +302,14 @@ handle_iptable()
     frob_iptable $ipv4_addrs
   fi
 
+  if [ "$ipv6_addrs" != "" -a "$do_ipv6" = "yes" ]
+  then
+    frob_ip6table $ipv6_addrs
+  elif [ "$ipv6_addrs" != "" -a "$ipv6_addrs" != "any" ]
+  then
+    log err "ip6tables setup skipped. This may affect guest networking."
+  fi
+
   release_lock "iptables"
 }
 
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.