]> xenbits.xensource.com Git - libvirt.git/commitdiff
network: allow DHCP/DNS/TFTP explicitly in OUTPUT rules
authorMalina Salina <malina.salina@protonmail.com>
Fri, 27 Sep 2019 16:10:34 +0000 (17:10 +0100)
committerDaniel P. Berrangé <berrange@redhat.com>
Fri, 18 Oct 2019 17:49:54 +0000 (18:49 +0100)
While the default iptables setup used by Fedora/RHEL distros
only restricts traffic on the INPUT and/or FORWARD rules,
some users might have custom firewalls that restrict the
OUTPUT rules too.

These can prevent DHCP/DNS/TFTP responses from dnsmasq
from reaching the guest VMs. We should thus whitelist
these protocols in the OUTPUT chain, as well as the
INPUT chain.

Signed-off-by: Malina Salina <malina.salina@protonmail.com>
Initial patch then modified to add unit tests and IPv6
support

Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
src/libvirt_private.syms
src/network/bridge_driver_linux.c
src/util/viriptables.c
src/util/viriptables.h
tests/networkxml2firewalldata/nat-default-linux.args
tests/networkxml2firewalldata/nat-ipv6-linux.args
tests/networkxml2firewalldata/nat-many-ips-linux.args
tests/networkxml2firewalldata/nat-no-dhcp-linux.args
tests/networkxml2firewalldata/nat-tftp-linux.args
tests/networkxml2firewalldata/route-default-linux.args

index 206295bef079309dbf699268e4f376eb6901d33b..15bfc711f50b42a531603f9e918e9cec75a3282a 100644 (file)
@@ -2192,6 +2192,7 @@ iptablesAddForwardRejectIn;
 iptablesAddForwardRejectOut;
 iptablesAddOutputFixUdpChecksum;
 iptablesAddTcpInput;
+iptablesAddTcpOutput;
 iptablesAddUdpInput;
 iptablesAddUdpOutput;
 iptablesRemoveDontMasquerade;
@@ -2204,6 +2205,7 @@ iptablesRemoveForwardRejectIn;
 iptablesRemoveForwardRejectOut;
 iptablesRemoveOutputFixUdpChecksum;
 iptablesRemoveTcpInput;
+iptablesRemoveTcpOutput;
 iptablesRemoveUdpInput;
 iptablesRemoveUdpOutput;
 iptablesSetDeletePrivate;
index d62fb899b94b61f9bcd6f97d32e579acc9e49a77..9de8e93c608b5d1f4a5b82210ab0916d61d1e723 100644 (file)
@@ -553,18 +553,23 @@ networkAddGeneralIPv4FirewallRules(virFirewallPtr fw,
             break;
     }
 
-    /* allow DHCP requests through to dnsmasq */
+    /* allow DHCP requests through to dnsmasq & back out */
     iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67);
     iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67);
+    iptablesAddTcpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 68);
     iptablesAddUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 68);
 
-    /* allow DNS requests through to dnsmasq */
+    /* allow DNS requests through to dnsmasq & back out */
     iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53);
     iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53);
+    iptablesAddTcpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53);
+    iptablesAddUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53);
 
-    /* allow TFTP requests through to dnsmasq if necessary */
-    if (ipv4def && ipv4def->tftproot)
+    /* allow TFTP requests through to dnsmasq if necessary & back out*/
+    if (ipv4def && ipv4def->tftproot) {
         iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 69);
+        iptablesAddUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 69);
+    }
 
     /* Catch all rules to block forwarding to/from bridges */
     iptablesAddForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge);
@@ -592,13 +597,18 @@ networkRemoveGeneralIPv4FirewallRules(virFirewallPtr fw,
     iptablesRemoveForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge);
     iptablesRemoveForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge);
 
-    if (ipv4def && ipv4def->tftproot)
+    if (ipv4def && ipv4def->tftproot) {
         iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 69);
+        iptablesRemoveUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 69);
+    }
 
     iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53);
     iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53);
+    iptablesRemoveUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53);
+    iptablesRemoveTcpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53);
 
     iptablesRemoveUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 68);
+    iptablesRemoveTcpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 68);
     iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67);
     iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67);
 }
@@ -626,10 +636,14 @@ networkAddGeneralIPv6FirewallRules(virFirewallPtr fw,
     iptablesAddForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge);
 
     if (virNetworkDefGetIPByIndex(def, AF_INET6, 0)) {
-        /* allow DNS over IPv6 */
+        /* allow DNS over IPv6 & back out */
         iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53);
         iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53);
+        iptablesAddTcpOutput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53);
+        iptablesAddUdpOutput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53);
+        /* allow DHCPv6 & back out */
         iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 547);
+        iptablesAddUdpOutput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 546);
     }
 }
 
@@ -643,7 +657,10 @@ networkRemoveGeneralIPv6FirewallRules(virFirewallPtr fw,
     }
 
     if (virNetworkDefGetIPByIndex(def, AF_INET6, 0)) {
+        iptablesRemoveUdpOutput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 546);
         iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 547);
+        iptablesRemoveUdpOutput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53);
+        iptablesRemoveTcpOutput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53);
         iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53);
         iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53);
     }
index e240b97d72589f9568a7856b7a136fa7d45d91b2..e95aaa4773a05455fef37b9654d26c3e51d0fdb9 100644 (file)
@@ -303,6 +303,42 @@ iptablesRemoveUdpInput(virFirewallPtr fw,
     iptablesInput(fw, layer, deletePrivate, iface, port, REMOVE, 0);
 }
 
+/**
+ * iptablesAddTcpOutput:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the TCP port to add
+ *
+ * Add an output to the IP table allowing access to the given @port from
+ * the given @iface interface for TCP packets
+ */
+void
+iptablesAddTcpOutput(virFirewallPtr fw,
+                     virFirewallLayer layer,
+                     const char *iface,
+                     int port)
+{
+    iptablesOutput(fw, layer, true, iface, port, ADD, 1);
+}
+
+/**
+ * iptablesRemoveTcpOutput:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the UDP port to remove
+ *
+ * Removes an output from the IP table, hence forbidding access to the given
+ * @port from the given @iface interface for TCP packets
+ */
+void
+iptablesRemoveTcpOutput(virFirewallPtr fw,
+                        virFirewallLayer layer,
+                        const char *iface,
+                        int port)
+{
+    iptablesOutput(fw, layer, deletePrivate, iface, port, REMOVE, 1);
+}
+
 /**
  * iptablesAddUdpOutput:
  * @ctx: pointer to the IP table context
index de2695617854c66573d82ac0c23a7884ea984d9f..c4c6595a2d485b2ddf4e385951c8f942a96f9104 100644 (file)
@@ -45,6 +45,14 @@ void             iptablesRemoveUdpInput          (virFirewallPtr fw,
                                                   const char *iface,
                                                   int port);
 
+void             iptablesAddTcpOutput            (virFirewallPtr fw,
+                                                  virFirewallLayer layer,
+                                                  const char *iface,
+                                                  int port);
+void             iptablesRemoveTcpOutput         (virFirewallPtr fw,
+                                                  virFirewallLayer layer,
+                                                  const char *iface,
+                                                  int port);
 void             iptablesAddUdpOutput            (virFirewallPtr fw,
                                                   virFirewallLayer layer,
                                                   const char *iface,
index c9d523d0435b34a9d1c1b1332763942981e7578e..ab18f30bd0a06b78c374dda1bbfff24fc2d2a865 100644 (file)
@@ -16,6 +16,13 @@ iptables \
 --table filter \
 --insert LIBVIRT_OUT \
 --out-interface virbr0 \
+--protocol tcp \
+--destination-port 68 \
+--jump ACCEPT
+iptables \
+--table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
 --protocol udp \
 --destination-port 68 \
 --jump ACCEPT
@@ -35,6 +42,20 @@ iptables \
 --jump ACCEPT
 iptables \
 --table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol tcp \
+--destination-port 53 \
+--jump ACCEPT
+iptables \
+--table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol udp \
+--destination-port 53 \
+--jump ACCEPT
+iptables \
+--table filter \
 --insert LIBVIRT_FWO \
 --in-interface virbr0 \
 --jump REJECT
index a57b9266afad9bfb66be7e6c711291e6820c2ee3..05d9ee33ca4731aaac0b295c5813be834c722cc1 100644 (file)
@@ -16,6 +16,13 @@ iptables \
 --table filter \
 --insert LIBVIRT_OUT \
 --out-interface virbr0 \
+--protocol tcp \
+--destination-port 68 \
+--jump ACCEPT
+iptables \
+--table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
 --protocol udp \
 --destination-port 68 \
 --jump ACCEPT
@@ -35,6 +42,20 @@ iptables \
 --jump ACCEPT
 iptables \
 --table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol tcp \
+--destination-port 53 \
+--jump ACCEPT
+iptables \
+--table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol udp \
+--destination-port 53 \
+--jump ACCEPT
+iptables \
+--table filter \
 --insert LIBVIRT_FWO \
 --in-interface virbr0 \
 --jump REJECT
@@ -81,11 +102,32 @@ ip6tables \
 --jump ACCEPT
 ip6tables \
 --table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol tcp \
+--destination-port 53 \
+--jump ACCEPT
+ip6tables \
+--table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol udp \
+--destination-port 53 \
+--jump ACCEPT
+ip6tables \
+--table filter \
 --insert LIBVIRT_INP \
 --in-interface virbr0 \
 --protocol udp \
 --destination-port 547 \
 --jump ACCEPT
+ip6tables \
+--table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol udp \
+--destination-port 546 \
+--jump ACCEPT
 iptables \
 --table filter \
 --insert LIBVIRT_FWO \
index 1bdc43fd6a1519ba4cb9ff0a68f36e0346b29a82..82e1380f51838aa72bc8cbabde3a8a945e029863 100644 (file)
@@ -16,6 +16,13 @@ iptables \
 --table filter \
 --insert LIBVIRT_OUT \
 --out-interface virbr0 \
+--protocol tcp \
+--destination-port 68 \
+--jump ACCEPT
+iptables \
+--table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
 --protocol udp \
 --destination-port 68 \
 --jump ACCEPT
@@ -35,6 +42,20 @@ iptables \
 --jump ACCEPT
 iptables \
 --table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol tcp \
+--destination-port 53 \
+--jump ACCEPT
+iptables \
+--table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol udp \
+--destination-port 53 \
+--jump ACCEPT
+iptables \
+--table filter \
 --insert LIBVIRT_FWO \
 --in-interface virbr0 \
 --jump REJECT
index 7d359f3824dd3f80d24a6a7dd82846d1de167a6e..8954cc5473cc62be7147192c5175bdad7fbd6f00 100644 (file)
@@ -16,6 +16,13 @@ iptables \
 --table filter \
 --insert LIBVIRT_OUT \
 --out-interface virbr0 \
+--protocol tcp \
+--destination-port 68 \
+--jump ACCEPT
+iptables \
+--table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
 --protocol udp \
 --destination-port 68 \
 --jump ACCEPT
@@ -35,6 +42,20 @@ iptables \
 --jump ACCEPT
 iptables \
 --table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol tcp \
+--destination-port 53 \
+--jump ACCEPT
+iptables \
+--table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol udp \
+--destination-port 53 \
+--jump ACCEPT
+iptables \
+--table filter \
 --insert LIBVIRT_FWO \
 --in-interface virbr0 \
 --jump REJECT
@@ -81,11 +102,32 @@ ip6tables \
 --jump ACCEPT
 ip6tables \
 --table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol tcp \
+--destination-port 53 \
+--jump ACCEPT
+ip6tables \
+--table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol udp \
+--destination-port 53 \
+--jump ACCEPT
+ip6tables \
+--table filter \
 --insert LIBVIRT_INP \
 --in-interface virbr0 \
 --protocol udp \
 --destination-port 547 \
 --jump ACCEPT
+ip6tables \
+--table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol udp \
+--destination-port 546 \
+--jump ACCEPT
 iptables \
 --table filter \
 --insert LIBVIRT_FWO \
index b721801b7062cccced3eaff4781cd67cbe043582..88e9929b6244cb0938c60dbabb2c65d3a402f5ae 100644 (file)
@@ -16,6 +16,13 @@ iptables \
 --table filter \
 --insert LIBVIRT_OUT \
 --out-interface virbr0 \
+--protocol tcp \
+--destination-port 68 \
+--jump ACCEPT
+iptables \
+--table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
 --protocol udp \
 --destination-port 68 \
 --jump ACCEPT
@@ -35,6 +42,20 @@ iptables \
 --jump ACCEPT
 iptables \
 --table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol tcp \
+--destination-port 53 \
+--jump ACCEPT
+iptables \
+--table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol udp \
+--destination-port 53 \
+--jump ACCEPT
+iptables \
+--table filter \
 --insert LIBVIRT_INP \
 --in-interface virbr0 \
 --protocol udp \
@@ -42,6 +63,13 @@ iptables \
 --jump ACCEPT
 iptables \
 --table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol udp \
+--destination-port 69 \
+--jump ACCEPT
+iptables \
+--table filter \
 --insert LIBVIRT_FWO \
 --in-interface virbr0 \
 --jump REJECT
index ed3c560f7446b7d9c2ab5cedeb8bbc3543a3b132..c427d9602dc3a244957872bec6368559a850c7e0 100644 (file)
@@ -16,6 +16,13 @@ iptables \
 --table filter \
 --insert LIBVIRT_OUT \
 --out-interface virbr0 \
+--protocol tcp \
+--destination-port 68 \
+--jump ACCEPT
+iptables \
+--table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
 --protocol udp \
 --destination-port 68 \
 --jump ACCEPT
@@ -35,6 +42,20 @@ iptables \
 --jump ACCEPT
 iptables \
 --table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol tcp \
+--destination-port 53 \
+--jump ACCEPT
+iptables \
+--table filter \
+--insert LIBVIRT_OUT \
+--out-interface virbr0 \
+--protocol udp \
+--destination-port 53 \
+--jump ACCEPT
+iptables \
+--table filter \
 --insert LIBVIRT_FWO \
 --in-interface virbr0 \
 --jump REJECT