]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Fixed up IPtables rules to be more strict
authorDaniel P. Berrange <berrange@redhat.com>
Tue, 10 Apr 2007 23:17:46 +0000 (23:17 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Tue, 10 Apr 2007 23:17:46 +0000 (23:17 +0000)
ChangeLog
qemud/conf.c
qemud/internal.h
qemud/iptables.c
qemud/iptables.h
qemud/qemud.c

index 2916f7a3b39cb689ee1ad1acf651b057f6a94dee..b423a63d0196fe4f30aac839eb28a1a2c2a453e3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Tue Apr 10 19:17:29 EST 2007 Daniel P. Berrange <berrange@redhat.com>
+
+       * qemud/conf.c, qemu/internal.h, qemud/iptables.c, qemud/iptables.h,
+       qemud/qemud.c: Some adjustment to IPTables rules to tighten up traffic
+       flow to/from virtual networks & avoid accidentally NAT'ing wrong packets.
+       Fixed XML dump when using auto-generated bridge device name.
+
 Tue Apr 10 19:15:29 EST 2007 Daniel P. Berrange <berrange@redhat.com>
 
        * python/libvir.c, python/libvirt-python-api.xml: Added manual
index fa4e463210f46cc69fb55b9150c4d9daddfcd12e..58cf71b0a66beb7ad20319178eeb15b6aea47aeb 100644 (file)
@@ -32,6 +32,8 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/wait.h>
+#include <arpa/inet.h>
+
 
 #include <libxml/parser.h>
 #include <libxml/tree.h>
@@ -44,7 +46,6 @@
 #include "internal.h"
 #include "conf.h"
 #include "driver.h"
-#include "iptables.h"
 #include "uuid.h"
 #include "buf.h"
 
@@ -1127,15 +1128,6 @@ qemudNetworkIfaceConnect(struct qemud_server *server,
         goto error;
     }
 
-    if (net->type == QEMUD_NET_NETWORK && network->def->forward) {
-        if ((err = iptablesAddPhysdevForward(server->iptables, ifname))) {
-            qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
-                             "Failed to add iptables rule to allow bridging from '%s' :%s",
-                             ifname, strerror(err));
-            goto error;
-        }
-    }
-
     snprintf(tapfdstr, sizeof(tapfdstr), "tap,fd=%d,script=,vlan=%d", tapfd, vlan);
 
     if (!(retval = strdup(tapfdstr)))
@@ -1151,8 +1143,6 @@ qemudNetworkIfaceConnect(struct qemud_server *server,
     return retval;
 
  no_memory:
-    if (net->type == QEMUD_NET_NETWORK && network->def->forward)
-        iptablesRemovePhysdevForward(server->iptables, ifname);
     qemudReportError(server, VIR_ERR_NO_MEMORY, "tapfds");
  error:
     if (retval)
@@ -1765,6 +1755,21 @@ static int qemudParseInetXML(struct qemud_server *server ATTRIBUTE_UNUSED,
         netmask = NULL;
     }
 
+    if (def->ipAddress[0] && def->netmask[0]) {
+        struct in_addr inaddress, innetmask;
+        char *netaddr;
+
+        inet_aton((const char*)def->ipAddress, &inaddress);
+        inet_aton((const char*)def->netmask, &innetmask);
+
+        inaddress.s_addr &= innetmask.s_addr;
+
+        netaddr = inet_ntoa(inaddress);
+
+        snprintf(def->network,sizeof(def->network)-1,
+                 "%s/%s", netaddr, (const char *)def->netmask);
+    }
+
     cur = node->children;
     while (cur != NULL) {
         if (cur->type == XML_ELEMENT_NODE &&
@@ -1835,9 +1840,37 @@ static struct qemud_network_def *qemudParseNetworkXML(struct qemud_server *serve
     }
     xmlXPathFreeObject(obj);
 
+    /* Parse bridge information */
+    obj = xmlXPathEval(BAD_CAST "/network/bridge[1]", ctxt);
+    if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
+        (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) {
+        if (!qemudParseBridgeXML(server, def, obj->nodesetval->nodeTab[0])) {
+            goto error;
+        }
+    }
+    xmlXPathFreeObject(obj);
+
+    /* Parse IP information */
+    obj = xmlXPathEval(BAD_CAST "/network/ip[1]", ctxt);
+    if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
+        (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) {
+        if (!qemudParseInetXML(server, def, obj->nodesetval->nodeTab[0])) {
+            goto error;
+        }
+    }
+    xmlXPathFreeObject(obj);
+
+    /* IPv4 forwarding setup */
     obj = xmlXPathEval(BAD_CAST "count(/network/forward) > 0", ctxt);
     if ((obj != NULL) && (obj->type == XPATH_BOOLEAN) &&
         obj->boolval) {
+        if (!def->ipAddress[0] ||
+            !def->netmask[0]) {
+            qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
+                             "Forwarding requested, but no IPv4 address/netmask provided");
+            goto error;
+        }
+
         def->forward = 1;
         tmp = xmlXPathEval(BAD_CAST "string(/network/forward[1]/@dev)", ctxt);
         if ((tmp != NULL) && (tmp->type == XPATH_STRING) &&
@@ -1860,26 +1893,6 @@ static struct qemud_network_def *qemudParseNetworkXML(struct qemud_server *serve
     }
     xmlXPathFreeObject(obj);
 
-    /* Parse bridge information */
-    obj = xmlXPathEval(BAD_CAST "/network/bridge[1]", ctxt);
-    if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
-        (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) {
-        if (!qemudParseBridgeXML(server, def, obj->nodesetval->nodeTab[0])) {
-            goto error;
-        }
-    }
-    xmlXPathFreeObject(obj);
-
-    /* Parse IP information */
-    obj = xmlXPathEval(BAD_CAST "/network/ip[1]", ctxt);
-    if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
-        (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) {
-        if (!qemudParseInetXML(server, def, obj->nodesetval->nodeTab[0])) {
-            goto error;
-        }
-    }
-    xmlXPathFreeObject(obj);
-
     xmlXPathFreeContext(ctxt);
 
     return def;
@@ -2622,7 +2635,7 @@ char *qemudGenerateXML(struct qemud_server *server,
 
 
 char *qemudGenerateNetworkXML(struct qemud_server *server,
-                              struct qemud_network *network ATTRIBUTE_UNUSED,
+                              struct qemud_network *network,
                               struct qemud_network_def *def) {
     bufferPtr buf = 0;
     unsigned char *uuid;
@@ -2654,11 +2667,17 @@ char *qemudGenerateNetworkXML(struct qemud_server *server,
         }
     }
 
-    if ((def->bridge != '\0' || def->disableSTP || def->forwardDelay) &&
-        bufferVSprintf(buf, "  <bridge name='%s' stp='%s' delay='%d' />\n",
-                          def->bridge,
-                          def->disableSTP ? "off" : "on",
-                          def->forwardDelay) < 0)
+    bufferAdd(buf, "  <bridge", -1);
+    if (qemudIsActiveNetwork(network)) {
+        if (bufferVSprintf(buf, " name='%s'", network->bridge) < 0)
+            goto no_memory;
+    } else if (def->bridge[0]) {
+        if (bufferVSprintf(buf, " name='%s'", def->bridge) < 0)
+            goto no_memory;
+    }
+    if (bufferVSprintf(buf, " stp='%s' forwardDelay='%d' />\n",
+                       def->disableSTP ? "off" : "on",
+                       def->forwardDelay) < 0)
         goto no_memory;
 
     if (def->ipAddress[0] || def->netmask[0]) {
index 8e8be2c86b103d252838cac5e5f4dfe702080036..3b453820ee5560e5a347739efed351a2f5176d11 100644 (file)
@@ -250,6 +250,7 @@ struct qemud_network_def {
 
     char ipAddress[BR_INET_ADDR_MAXLEN];
     char netmask[BR_INET_ADDR_MAXLEN];
+    char network[BR_INET_ADDR_MAXLEN+BR_INET_ADDR_MAXLEN+1];
 
     int nranges;
     struct qemud_dhcp_range_def *ranges;
index f772a8ed3186e726c54f3c460b56da89bd35203e..83613d2b6f9772f3c85acf84bb5c93858d0e17fe 100644 (file)
@@ -656,49 +656,29 @@ iptablesRemoveUdpInput(iptablesContext *ctx,
     return iptablesInput(ctx, iface, port, REMOVE, 0);
 }
 
-static int
-iptablesPhysdevForward(iptablesContext *ctx,
-                       const char *iface,
-                       int action)
-{
-    return iptablesAddRemoveRule(ctx->forward_filter,
-                                 action,
-                                 "--match", "physdev",
-                                 "--physdev-in", iface,
-                                 "--jump", "ACCEPT",
-                                 NULL);
-}
-
-int
-iptablesAddPhysdevForward(iptablesContext *ctx,
-                          const char *iface)
-{
-    return iptablesPhysdevForward(ctx, iface, ADD);
-}
-
-int
-iptablesRemovePhysdevForward(iptablesContext *ctx,
-                             const char *iface)
-{
-    return iptablesPhysdevForward(ctx, iface, REMOVE);
-}
 
+/* Allow all traffic coming from the bridge, with a valid network address
+ * to proceed to WAN
+ */
 static int
-iptablesInterfaceForward(iptablesContext *ctx,
+iptablesForwardAllowOut(iptablesContext *ctx,
+                         const char *network,
                          const char *iface,
-                         const char *target,
+                         const char *physdev,
                          int action)
 {
-    if (target && target[0]) {
+    if (physdev && physdev[0]) {
         return iptablesAddRemoveRule(ctx->forward_filter,
                                      action,
+                                     "--source", network,
                                      "--in-interface", iface,
-                                     "--out-interface", target,
+                                     "--out-interface", physdev,
                                      "--jump", "ACCEPT",
                                      NULL);
     } else {
         return iptablesAddRemoveRule(ctx->forward_filter,
                                      action,
+                                     "--source", network,
                                      "--in-interface", iface,
                                      "--jump", "ACCEPT",
                                      NULL);
@@ -706,31 +686,39 @@ iptablesInterfaceForward(iptablesContext *ctx,
 }
 
 int
-iptablesAddInterfaceForward(iptablesContext *ctx,
+iptablesAddForwardAllowOut(iptablesContext *ctx,
+                            const char *network,
                             const char *iface,
-                            const char *target)
+                            const char *physdev)
 {
-    return iptablesInterfaceForward(ctx, iface, target, ADD);
+    return iptablesForwardAllowOut(ctx, network, iface, physdev, ADD);
 }
 
 int
-iptablesRemoveInterfaceForward(iptablesContext *ctx,
+iptablesRemoveForwardAllowOut(iptablesContext *ctx,
+                               const char *network,
                                const char *iface,
-                               const char *target)
+                               const char *physdev)
 {
-    return iptablesInterfaceForward(ctx, iface, target, REMOVE);
+    return iptablesForwardAllowOut(ctx, network, iface, physdev, REMOVE);
 }
 
+
+/* Allow all traffic destined to the bridge, with a valid network address
+ * and associated with an existing connection
+ */
 static int
-iptablesStateForward(iptablesContext *ctx,
-                     const char *iface,
-                     const char *target,
-                     int action)
+iptablesForwardAllowIn(iptablesContext *ctx,
+                       const char *network,
+                       const char *iface,
+                       const char *physdev,
+                       int action)
 {
-    if (target && target[0]) {
+    if (physdev && physdev[0]) {
         return iptablesAddRemoveRule(ctx->forward_filter,
                                      action,
-                                     "--in-interface", target,
+                                     "--destination", network,
+                                     "--in-interface", physdev,
                                      "--out-interface", iface,
                                      "--match", "state",
                                      "--state", "ESTABLISHED,RELATED",
@@ -739,6 +727,7 @@ iptablesStateForward(iptablesContext *ctx,
     } else {
         return iptablesAddRemoveRule(ctx->forward_filter,
                                      action,
+                                     "--destination", network,
                                      "--out-interface", iface,
                                      "--match", "state",
                                      "--state", "ESTABLISHED,RELATED",
@@ -748,56 +737,154 @@ iptablesStateForward(iptablesContext *ctx,
 }
 
 int
-iptablesAddStateForward(iptablesContext *ctx,
+iptablesAddForwardAllowIn(iptablesContext *ctx,
+                          const char *network,
+                          const char *iface,
+                          const char *physdev)
+{
+    return iptablesForwardAllowIn(ctx, network, iface, physdev, ADD);
+}
+
+int
+iptablesRemoveForwardAllowIn(iptablesContext *ctx,
+                             const char *network,
+                             const char *iface,
+                             const char *physdev)
+{
+    return iptablesForwardAllowIn(ctx, network, iface, physdev, REMOVE);
+}
+
+
+/* Allow all traffic between guests on the same bridge,
+ * with a valid network address
+ */
+static int
+iptablesForwardAllowCross(iptablesContext *ctx,
+                          const char *iface,
+                          int action)
+{
+    return iptablesAddRemoveRule(ctx->forward_filter,
+                                 action,
+                                 "--in-interface", iface,
+                                 "--out-interface", iface,
+                                 "--jump", "ACCEPT",
+                                 NULL);
+}
+
+int
+iptablesAddForwardAllowCross(iptablesContext *ctx,
+                             const char *iface) {
+    return iptablesForwardAllowCross(ctx, iface, ADD);
+}
+
+int
+iptablesRemoveForwardAllowCross(iptablesContext *ctx,
+                                const char *iface) {
+    return iptablesForwardAllowCross(ctx, iface, REMOVE);
+}
+
+
+/* Drop all traffic trying to forward from the bridge.
+ * ie the bridge is the in interface
+ */
+static int
+iptablesForwardRejectOut(iptablesContext *ctx,
+                         const char *iface,
+                         int action)
+{
+    return iptablesAddRemoveRule(ctx->forward_filter,
+                                     action,
+                                     "--in-interface", iface,
+                                     "--jump", "REJECT",
+                                     NULL);
+}
+
+int
+iptablesAddForwardRejectOut(iptablesContext *ctx,
+                            const char *iface)
+{
+    return iptablesForwardRejectOut(ctx, iface, ADD);
+}
+
+int
+iptablesRemoveForwardRejectOut(iptablesContext *ctx,
+                               const char *iface)
+{
+    return iptablesForwardRejectOut(ctx, iface, REMOVE);
+}
+
+
+
+
+/* Drop all traffic trying to forward to the bridge.
+ * ie the bridge is the out interface
+ */
+static int
+iptablesForwardRejectIn(iptablesContext *ctx,
                         const char *iface,
-                        const char *target)
+                        int action)
+{
+    return iptablesAddRemoveRule(ctx->forward_filter,
+                                 action,
+                                 "--out-interface", iface,
+                                 "--jump", "REJECT",
+                                 NULL);
+}
+
+int
+iptablesAddForwardRejectIn(iptablesContext *ctx,
+                           const char *iface)
 {
-    return iptablesStateForward(ctx, iface, target, ADD);
+    return iptablesForwardRejectIn(ctx, iface, ADD);
 }
 
 int
-iptablesRemoveStateForward(iptablesContext *ctx,
-                           const char *iface,
-                           const char *target)
+iptablesRemoveForwardRejectIn(iptablesContext *ctx,
+                              const char *iface)
 {
-    return iptablesStateForward(ctx, iface, target, REMOVE);
+    return iptablesForwardRejectIn(ctx, iface, REMOVE);
 }
 
+
+/* Masquerade all traffic coming from the network associated
+ * with the bridge
+ */
 static int
-iptablesNonBridgedMasq(iptablesContext *ctx,
-                       const char *target,
+iptablesForwardMasquerade(iptablesContext *ctx,
+                       const char *network,
+                       const char *physdev,
                        int action)
 {
-    if (target && target[0]) {
+    if (physdev && physdev[0]) {
         return iptablesAddRemoveRule(ctx->nat_postrouting,
                                      action,
-                                     "--out-interface", target,
-                                     "--match", "physdev",
-                                     "!", "--physdev-is-bridged",
+                                     "--source", network,
+                                     "--out-interface", physdev,
                                      "--jump", "MASQUERADE",
                                      NULL);
     } else {
         return iptablesAddRemoveRule(ctx->nat_postrouting,
                                      action,
-                                     "--match", "physdev",
-                                     "!", "--physdev-is-bridged",
+                                     "--source", network,
                                      "--jump", "MASQUERADE",
                                      NULL);
     }
 }
 
 int
-iptablesAddNonBridgedMasq(iptablesContext *ctx,
-                          const char *target)
+iptablesAddForwardMasquerade(iptablesContext *ctx,
+                             const char *network,
+                             const char *physdev)
 {
-    return iptablesNonBridgedMasq(ctx, target, ADD);
+    return iptablesForwardMasquerade(ctx, network, physdev, ADD);
 }
 
 int
-iptablesRemoveNonBridgedMasq(iptablesContext *ctx,
-                             const char *target)
+iptablesRemoveForwardMasquerade(iptablesContext *ctx,
+                                const char *network,
+                                const char *physdev)
 {
-    return iptablesNonBridgedMasq(ctx, target, REMOVE);
+    return iptablesForwardMasquerade(ctx, network, physdev, REMOVE);
 }
 
 /*
index 9ef5c1e488039ea78fed61ec2fae05974619e7bb..c68fef0ea17ff953d2389db754f7322098ca12ab 100644 (file)
@@ -43,29 +43,45 @@ int              iptablesRemoveUdpInput          (iptablesContext *ctx,
                                                   const char *iface,
                                                   int port);
 
-int              iptablesAddPhysdevForward       (iptablesContext *ctx,
-                                                  const char *iface);
-int              iptablesRemovePhysdevForward    (iptablesContext *ctx,
-                                                  const char *iface);
-
-int              iptablesAddInterfaceForward     (iptablesContext *ctx,
+int              iptablesAddForwardAllowOut      (iptablesContext *ctx,
+                                                  const char *network,
                                                   const char *iface,
-                                                  const char *target);
-int              iptablesRemoveInterfaceForward  (iptablesContext *ctx,
+                                                  const char *physdev);
+int              iptablesRemoveForwardAllowOut   (iptablesContext *ctx,
+                                                  const char *network,
                                                   const char *iface,
-                                                  const char *target);
+                                                  const char *physdev);
 
-int              iptablesAddStateForward         (iptablesContext *ctx,
+int              iptablesAddForwardAllowIn       (iptablesContext *ctx,
+                                                  const char *network,
                                                   const char *iface,
-                                                  const char *target);
-int              iptablesRemoveStateForward      (iptablesContext *ctx,
+                                                  const char *physdev);
+int              iptablesRemoveForwardAllowIn    (iptablesContext *ctx,
+                                                  const char *network,
                                                   const char *iface,
-                                                  const char *target);
+                                                  const char *physdev);
+
+int              iptablesAddForwardAllowCross    (iptablesContext *ctx,
+                                                  const char *iface);
+int              iptablesRemoveForwardAllowCross (iptablesContext *ctx,
+                                                  const char *iface);
+
+int              iptablesAddForwardRejectOut     (iptablesContext *ctx,
+                                                  const char *iface);
+int              iptablesRemoveForwardRejectOut  (iptablesContext *ctx,
+                                                  const char *iface);
+
+int              iptablesAddForwardRejectIn      (iptablesContext *ctx,
+                                                  const char *iface);
+int              iptablesRemoveForwardRejectIn   (iptablesContext *ctx,
+                                                  const char *iface);
 
-int              iptablesAddNonBridgedMasq       (iptablesContext *ctx,
-                                                  const char *target);
-int              iptablesRemoveNonBridgedMasq    (iptablesContext *ctx,
-                                                  const char *target);
+int              iptablesAddForwardMasquerade    (iptablesContext *ctx,
+                                                  const char *network,
+                                                  const char *physdev);
+int              iptablesRemoveForwardMasquerade (iptablesContext *ctx,
+                                                  const char *network,
+                                                  const char *physdev);
 
 #endif /* __QEMUD_IPTABLES_H__ */
 
index e2a0fa401fd9c7091bd347356eee6938f06a3646..7d67bde062f25224f1bde1bdae2d6a6ee7f4808e 100644 (file)
@@ -45,6 +45,7 @@
 #include <getopt.h>
 #include <ctype.h>
 
+
 #include <libvirt/virterror.h>
 
 #include "internal.h"
@@ -1041,26 +1042,8 @@ static int qemudVMData(struct qemud_server *server ATTRIBUTE_UNUSED,
     }
 }
 
-static void
-qemudNetworkIfaceDisconnect(struct qemud_server *server,
-                            struct qemud_vm *vm ATTRIBUTE_UNUSED,
-                            struct qemud_vm_net_def *net) {
-    struct qemud_network *network;
-    if (net->type != QEMUD_NET_NETWORK)
-        return;
-
-    if (!(network = qemudFindNetworkByName(server, net->dst.network.name))) {
-        return;
-    } else if (network->bridge[0] == '\0') {
-        return;
-    }
-
-    iptablesRemovePhysdevForward(server->iptables, net->dst.network.ifname);
-}
 
 int qemudShutdownVMDaemon(struct qemud_server *server, struct qemud_vm *vm) {
-    struct qemud_vm_net_def *net;
-
     if (!qemudIsActiveVM(vm))
         return 0;
 
@@ -1079,13 +1062,6 @@ int qemudShutdownVMDaemon(struct qemud_server *server, struct qemud_vm *vm) {
     vm->monitor = -1;
     server->nvmfds -= 2;
 
-    net = vm->def->nets;
-    while (net) {
-        if (net->type == QEMUD_NET_NETWORK)
-            qemudNetworkIfaceDisconnect(server, vm, net);
-        net = net->next;
-    }
-
     if (waitpid(vm->pid, NULL, WNOHANG) != vm->pid) {
         kill(vm->pid, SIGKILL);
         if (waitpid(vm->pid, NULL, 0) != vm->pid) {
@@ -1251,27 +1227,20 @@ qemudAddIptablesRules(struct qemud_server *server,
         return 1;
     }
 
-    /* allow bridging from the bridge interface itself */
-    if ((err = iptablesAddPhysdevForward(server->iptables, network->bridge))) {
-        qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
-                         "failed to add iptables rule to allow bridging from '%s' : %s\n",
-                         network->bridge, strerror(err));
-        goto err1;
-    }
 
     /* allow DHCP requests through to dnsmasq */
     if ((err = iptablesAddTcpInput(server->iptables, network->bridge, 67))) {
         qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
                          "failed to add iptables rule to allow DHCP requests from '%s' : %s\n",
                          network->bridge, strerror(err));
-        goto err2;
+        goto err1;
     }
 
     if ((err = iptablesAddUdpInput(server->iptables, network->bridge, 67))) {
         qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
                          "failed to add iptables rule to allow DHCP requests from '%s' : %s\n",
                          network->bridge, strerror(err));
-        goto err3;
+        goto err2;
     }
 
     /* allow DNS requests through to dnsmasq */
@@ -1279,60 +1248,107 @@ qemudAddIptablesRules(struct qemud_server *server,
         qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
                          "failed to add iptables rule to allow DNS requests from '%s' : %s\n",
                          network->bridge, strerror(err));
-        goto err4;
+        goto err3;
     }
 
     if ((err = iptablesAddUdpInput(server->iptables, network->bridge, 53))) {
         qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
                          "failed to add iptables rule to allow DNS requests from '%s' : %s\n",
                          network->bridge, strerror(err));
+        goto err4;
+    }
+
+
+    /* Catch all rules to block forwarding to/from bridges */
+
+    if ((err = iptablesAddForwardRejectOut(server->iptables, network->bridge))) {
+        qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
+                         "failed to add iptables rule to block outbound traffic from '%s' : %s\n",
+                         network->bridge, strerror(err));
         goto err5;
     }
 
+    if ((err = iptablesAddForwardRejectIn(server->iptables, network->bridge))) {
+        qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
+                         "failed to add iptables rule to block inbound traffic to '%s' : %s\n",
+                         network->bridge, strerror(err));
+        goto err6;
+    }
+
+    /* Allow traffic between guests on the same bridge */
+    if ((err = iptablesAddForwardAllowCross(server->iptables, network->bridge))) {
+        qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
+                         "failed to add iptables rule to allow cross bridge traffic on '%s' : %s\n",
+                         network->bridge, strerror(err));
+        goto err7;
+    }
+
+
     /* The remaining rules are only needed for IP forwarding */
     if (!network->def->forward)
         return 1;
 
     /* allow forwarding packets from the bridge interface */
-    if ((err = iptablesAddInterfaceForward(server->iptables, network->bridge, network->def->forwardDev))) {
+    if ((err = iptablesAddForwardAllowOut(server->iptables,
+                                          network->def->network,
+                                          network->bridge,
+                                          network->def->forwardDev))) {
         qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
                          "failed to add iptables rule to allow forwarding from '%s' : %s\n",
                          network->bridge, strerror(err));
-        goto err6;
+        goto err8;
     }
 
     /* allow forwarding packets to the bridge interface if they are part of an existing connection */
-    if ((err = iptablesAddStateForward(server->iptables, network->bridge, network->def->forwardDev))) {
+    if ((err = iptablesAddForwardAllowIn(server->iptables,
+                                         network->def->network,
+                                         network->bridge,
+                                         network->def->forwardDev))) {
         qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
                          "failed to add iptables rule to allow forwarding to '%s' : %s\n",
                          network->bridge, strerror(err));
-        goto err7;
+        goto err9;
     }
 
     /* enable masquerading */
-    if ((err = iptablesAddNonBridgedMasq(server->iptables, network->def->forwardDev))) {
+    if ((err = iptablesAddForwardMasquerade(server->iptables,
+                                            network->def->network,
+                                            network->def->forwardDev))) {
         qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
                          "failed to add iptables rule to enable masquerading : %s\n",
                          strerror(err));
-        goto err8;
+        goto err10;
     }
 
     return 1;
 
+ err10:
+    iptablesRemoveForwardAllowIn(server->iptables,
+                                 network->def->network,
+                                 network->bridge,
+                                 network->def->forwardDev);
+ err9:
+    iptablesRemoveForwardAllowOut(server->iptables,
+                                  network->def->network,
+                                  network->bridge,
+                                  network->def->forwardDev);
  err8:
-    iptablesRemoveStateForward(server->iptables, network->bridge, network->def->forwardDev);
+    iptablesRemoveForwardAllowCross(server->iptables,
+                                    network->bridge);
  err7:
-    iptablesRemoveInterfaceForward(server->iptables, network->bridge, network->def->forwardDev);
+    iptablesRemoveForwardRejectIn(server->iptables,
+                                  network->bridge);
  err6:
-    iptablesRemoveUdpInput(server->iptables, network->bridge, 53);
+    iptablesRemoveForwardRejectOut(server->iptables,
+                                   network->bridge);
  err5:
-    iptablesRemoveTcpInput(server->iptables, network->bridge, 53);
+    iptablesRemoveUdpInput(server->iptables, network->bridge, 53);
  err4:
-    iptablesRemoveUdpInput(server->iptables, network->bridge, 67);
+    iptablesRemoveTcpInput(server->iptables, network->bridge, 53);
  err3:
-    iptablesRemoveTcpInput(server->iptables, network->bridge, 67);
+    iptablesRemoveUdpInput(server->iptables, network->bridge, 67);
  err2:
-    iptablesRemovePhysdevForward(server->iptables, network->bridge);
+    iptablesRemoveTcpInput(server->iptables, network->bridge, 67);
  err1:
     return 0;
 }
@@ -1341,15 +1357,25 @@ static void
 qemudRemoveIptablesRules(struct qemud_server *server,
                          struct qemud_network *network) {
     if (network->def->forward) {
-        iptablesRemoveNonBridgedMasq(server->iptables, network->def->forwardDev);
-        iptablesRemoveStateForward(server->iptables, network->bridge, network->def->forwardDev);
-        iptablesRemoveInterfaceForward(server->iptables, network->bridge, network->def->forwardDev);
-    }
+        iptablesRemoveForwardMasquerade(server->iptables,
+                                     network->def->network,
+                                     network->def->forwardDev);
+        iptablesRemoveForwardAllowIn(server->iptables,
+                                   network->def->network,
+                                   network->bridge,
+                                   network->def->forwardDev);
+        iptablesRemoveForwardAllowOut(server->iptables,
+                                      network->def->network,
+                                      network->bridge,
+                                      network->def->forwardDev);
+    }
+    iptablesRemoveForwardAllowCross(server->iptables, network->bridge);
+    iptablesRemoveForwardRejectIn(server->iptables, network->bridge);
+    iptablesRemoveForwardRejectOut(server->iptables, network->bridge);
     iptablesRemoveUdpInput(server->iptables, network->bridge, 53);
     iptablesRemoveTcpInput(server->iptables, network->bridge, 53);
     iptablesRemoveUdpInput(server->iptables, network->bridge, 67);
     iptablesRemoveTcpInput(server->iptables, network->bridge, 67);
-    iptablesRemovePhysdevForward(server->iptables, network->bridge);
 }
 
 static int